From 457fa74d232c7616e4fccadd4d48905dde00cd0c Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 21 Nov 2024 18:28:22 +0000 Subject: [PATCH 1/4] drm/vc4: hdmi: Add a clear_infoframe hook If you disable HDR metadata, then the hardware should stop sending the infoframe, and that is implemented by the clear_infoframe hook which wasn't implemented. Add it. Signed-off-by: Dave Stevenson --- drivers/gpu/drm/vc4/vc4_hdmi.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index cd7db4524ff690..6aa607c389297c 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -779,6 +779,24 @@ static int vc4_hdmi_write_infoframe(struct drm_connector *connector, return ret; } +static int vc4_hdmi_clear_infoframe(struct drm_connector *connector, + enum hdmi_infoframe_type type) +{ + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); + struct drm_device *drm = connector->dev; + int ret; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return 0; + + ret = vc4_hdmi_stop_packet(vc4_hdmi, type, true); + if (ret) + drm_err(drm, "Failed to wait for infoframe to go idle: %d\n", ret); + + drm_dev_exit(idx); + return ret; +} #define SCRAMBLING_POLLING_DELAY_MS 1000 static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) @@ -1739,6 +1757,7 @@ vc4_hdmi_connector_clock_valid(const struct drm_connector *connector, static const struct drm_connector_hdmi_funcs vc4_hdmi_hdmi_connector_funcs = { .tmds_char_rate_valid = vc4_hdmi_connector_clock_valid, .write_infoframe = vc4_hdmi_write_infoframe, + .clear_infoframe = vc4_hdmi_clear_infoframe, }; #define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL From ce940d38129c77c8cfd3171002f2a704c52eec1a Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 21 Nov 2024 18:30:07 +0000 Subject: [PATCH 2/4] drm/connector: Initialise max_bpc to the minimum value supported Using increased bit depth for no reason increases power consumption, and differs from the behaviour prior to the conversion to use the HDMI helper functions. Initialise the state max_bpc and requested_max_bpc to the minimum value supported. This only affects Raspberry Pi, as the other users of the helpers (rockchip/inno_hdmi and sunx4i) only support a bit depth of 8. Signed-off-by: Dave Stevenson --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 2 +- drivers/gpu/drm/drm_connector.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index feb7a3a759811a..ecb9b015b17e8c 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -24,7 +24,7 @@ void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector *connector, unsigned int max_bpc = connector->max_bpc; new_conn_state->max_bpc = max_bpc; - new_conn_state->max_requested_bpc = max_bpc; + new_conn_state->max_requested_bpc = 8; new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO; } EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset); diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 0537f80274e0d4..893a88e7f4f2fc 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -2723,8 +2723,8 @@ int drm_connector_attach_max_bpc_property(struct drm_connector *connector, } drm_object_attach_property(&connector->base, prop, max); - connector->state->max_requested_bpc = max; - connector->state->max_bpc = max; + connector->state->max_requested_bpc = min; + connector->state->max_bpc = min; return 0; } From 5abab559517a5f803409d073c6e7865c38c05956 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 21 Nov 2024 18:33:11 +0000 Subject: [PATCH 3/4] drm/connector: hdmi: Disable the infoframes by default If an infoframe was ever enabled, duplicate_state would memcpy the infoframe including the "set" flag. The infoframe functions then never cleared it, so once set it was always set. This was most obvious with the HDR infoframe as it resulted in bad colour rendering. Signed-off-by: Dave Stevenson --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index ecb9b015b17e8c..331dee1803b91a 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -347,6 +347,8 @@ static int hdmi_generate_avi_infoframe(const struct drm_connector *connector, is_limited_range ? HDMI_QUANTIZATION_RANGE_LIMITED : HDMI_QUANTIZATION_RANGE_FULL; int ret; + infoframe->set = false; + ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, mode); if (ret) return ret; @@ -376,6 +378,8 @@ static int hdmi_generate_spd_infoframe(const struct drm_connector *connector, &infoframe->data.spd; int ret; + infoframe->set = false; + ret = hdmi_spd_infoframe_init(frame, connector->hdmi.vendor, connector->hdmi.product); @@ -398,6 +402,8 @@ static int hdmi_generate_hdr_infoframe(const struct drm_connector *connector, &infoframe->data.drm; int ret; + infoframe->set = false; + if (connector->max_bpc < 10) return 0; @@ -425,6 +431,8 @@ static int hdmi_generate_hdmi_vendor_infoframe(const struct drm_connector *conne &infoframe->data.vendor.hdmi; int ret; + infoframe->set = false; + if (!info->has_hdmi_infoframe) return 0; From 7308701c41de4ea2e83d34bc94994e2a14e6500f Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 21 Nov 2024 18:43:28 +0000 Subject: [PATCH 4/4] drm/connector: hdmi: Attempt YUV422 output if RGB isn't supported Drop from RGB to YUV422 output if RGB couldn't be supported within the defined max_bpc and TMDS rates, and then try dropping max_bpc. Signed-off-by: Dave Stevenson --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index 331dee1803b91a..34d411245fe89e 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -294,6 +294,11 @@ hdmi_compute_format(const struct drm_connector *connector, return 0; } + if (hdmi_try_format_bpc(connector, conn_state, mode, bpc, HDMI_COLORSPACE_YUV422)) { + conn_state->hdmi.output_format = HDMI_COLORSPACE_YUV422; + return 0; + } + drm_dbg_kms(dev, "Failed. No Format Supported for that bpc count.\n"); return -EINVAL;