mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
drm/display: scdc-helper: Add helper to set SCDC version information
The HDMI 2.x specs mandate that compliant Sink devices report their SCDC version in the Sink Version register, which reads as 1 on any SCDC-capable sink. There is also a dedicated Source Version register. Writing it is not compulsory, but the spec advises that compliant Source devices do so, in which case the value must be 1. Add drm_scdc_set_source_version() to follow this recommendation. The Sink Version register is read first, both to log the advertised SCDC version and to guard against non-conformant devices: a sink reporting version 0 is either not SCDC-version-aware or broken, so writing the source version gains nothing and risks upsetting such hardware. In that case the write is skipped. The source version is passed as a parameter rather than hardcoded, as future spec revisions may define additional rules for the allowable version values. The written value is additionally clamped to the sink's reported version so the source never advertises a version the sink does not understand. Acked-by: Maxime Ripard <mripard@kernel.org> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> Tested-by: Maud Spierings <maud_spierings@hotmail.com> Tested-by: Diederik de Haas <diederik@cknow-tech.com> # NanoPC-T6 LTS, Rock 5B Tested-by: Igor Paunovic <royalnet026@gmail.com> # RK3588 Orange Pi 5 Plus, dual HDMI Tested-by: Robin Räber <robin.raebi@gmail.com> Link: https://patch.msgid.link/20260901-dw-hdmi-qp-scramb-v11-9-bc12954a0688@collabora.com Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
This commit is contained in:
parent
62cdbd8d50
commit
f57c219838
|
|
@ -22,12 +22,13 @@
|
|||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/display/drm_scdc_helper.h>
|
||||
#include <drm/drm_connector.h>
|
||||
|
|
@ -306,6 +307,49 @@ bool drm_scdc_set_high_tmds_clock_ratio(struct drm_connector *connector,
|
|||
}
|
||||
EXPORT_SYMBOL(drm_scdc_set_high_tmds_clock_ratio);
|
||||
|
||||
/**
|
||||
* drm_scdc_set_source_version - set SCDC source version on the sink
|
||||
* @connector: connector
|
||||
* @ver: source version to advertise (per spec, 1)
|
||||
*
|
||||
* Reads the sink version for diagnostics and as a guard, then writes
|
||||
* the source version unless the sink reports version 0.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or when skipped; a negative error code when either
|
||||
* the read or the write failed.
|
||||
*/
|
||||
int drm_scdc_set_source_version(struct drm_connector *connector, u8 ver)
|
||||
{
|
||||
u8 sink_ver;
|
||||
int ret;
|
||||
|
||||
ret = drm_scdc_readb(connector->ddc, SCDC_SINK_VERSION, &sink_ver);
|
||||
if (ret) {
|
||||
drm_scdc_dbg(connector, "Failed to read SCDC_SINK_VERSION: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_scdc_dbg(connector, "Sink reported SCDC ver. %u\n", sink_ver);
|
||||
|
||||
/*
|
||||
* Only advertise our source version to sinks that report a
|
||||
* non-zero sink version. A sink reporting version 0 is either
|
||||
* not SCDC-version-aware or non-conformant; writing the source
|
||||
* version gains nothing and may upset broken hardware.
|
||||
*/
|
||||
if (sink_ver) {
|
||||
ret = drm_scdc_writeb(connector->ddc, SCDC_SOURCE_VERSION,
|
||||
min_t(u8, sink_ver, ver));
|
||||
if (ret)
|
||||
drm_scdc_dbg(connector,
|
||||
"Failed to write SCDC_SOURCE_VERSION: %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_scdc_set_source_version);
|
||||
|
||||
static void
|
||||
drm_scdc_parse_status0_flags(u8 val, struct drm_scdc_status_flags *flags)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -168,6 +168,8 @@ bool drm_scdc_get_scrambling_status(struct drm_connector *connector);
|
|||
bool drm_scdc_set_scrambling(struct drm_connector *connector, bool enable);
|
||||
bool drm_scdc_set_high_tmds_clock_ratio(struct drm_connector *connector, bool set);
|
||||
|
||||
int drm_scdc_set_source_version(struct drm_connector *connector, u8 ver);
|
||||
|
||||
int drm_scdc_read_state(struct drm_connector *connector,
|
||||
struct drm_scdc_state *state);
|
||||
void drm_scdc_debugfs_init(struct drm_connector *connector, struct dentry *root);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user