[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20231222174220.55249-21-knaerzche@gmail.com>
Date: Fri, 22 Dec 2023 18:42:11 +0100
From: Alex Bee <knaerzche@...il.com>
To: Sandy Huang <hjc@...k-chips.com>,
Heiko Stübner <heiko@...ech.de>,
Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>,
Maxime Ripard <mripard@...nel.org>,
Thomas Zimmermann <tzimmermann@...e.de>,
Rob Herring <robh+dt@...nel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@...aro.org>,
Conor Dooley <conor+dt@...nel.org>
Cc: David Airlie <airlied@...il.com>,
Daniel Vetter <daniel@...ll.ch>,
dri-devel@...ts.freedesktop.org,
devicetree@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org,
linux-rockchip@...ts.infradead.org,
linux-kernel@...r.kernel.org,
Alex Bee <knaerzche@...il.com>
Subject: [PATCH v4 20/29] drm/rockchip: inno_hdmi: Correctly setup HDMI quantization range
The display controller will always give full range RGB regardless of the
mode set, but HDMI requires certain modes to be transmitted in limited
range RGB. This is especially required for HDMI sinks which do not support
non-standard quantization ranges.
This enables color space conversion for those modes and sets the
quantization range accordingly in the AVI infoframe.
Signed-off-by: Alex Bee <knaerzche@...il.com>
---
changes in v2:
- made rgb_limited_range part of the new custom connector state
changes in v3:
- moved assignment of rgb_limited_range to atomic check
changes in v4:
- none
drivers/gpu/drm/rockchip/inno_hdmi.c | 60 +++++++++++++++++++---------
1 file changed, 42 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
index e43fce968310..f3b90b479ab9 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -53,6 +53,7 @@ struct inno_hdmi_connector_state {
struct drm_connector_state base;
unsigned int enc_out_format;
unsigned int colorimetry;
+ bool rgb_limited_range;
};
static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder)
@@ -270,6 +271,18 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
else
frame.avi.colorspace = HDMI_COLORSPACE_RGB;
+ if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) {
+ drm_hdmi_avi_infoframe_quant_range(&frame.avi,
+ connector, mode,
+ inno_conn_state->rgb_limited_range ?
+ HDMI_QUANTIZATION_RANGE_LIMITED :
+ HDMI_QUANTIZATION_RANGE_FULL);
+ } else {
+ frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
+ frame.avi.ycc_quantization_range =
+ HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
+ }
+
return inno_hdmi_upload_frame(hdmi, &frame, HDMI_INFOFRAME_TYPE_AVI);
}
@@ -297,29 +310,37 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) {
- value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
- hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
-
- hdmi_modb(hdmi, HDMI_VIDEO_CONTRL,
- m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
- v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
- v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
- return 0;
- }
-
- if (inno_conn_state->colorimetry == HDMI_COLORIMETRY_ITU_601) {
- if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) {
- csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
+ if (inno_conn_state->rgb_limited_range) {
+ csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
auto_csc = AUTO_CSC_DISABLE;
c0_c2_change = C0_C2_CHANGE_DISABLE;
csc_enable = v_CSC_ENABLE;
+
+ } else {
+ value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
+ hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
+
+ hdmi_modb(hdmi, HDMI_VIDEO_CONTRL,
+ m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
+ v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
+ v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
+ return 0;
}
} else {
- if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) {
- csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
- auto_csc = AUTO_CSC_DISABLE;
- c0_c2_change = C0_C2_CHANGE_DISABLE;
- csc_enable = v_CSC_ENABLE;
+ if (inno_conn_state->colorimetry == HDMI_COLORIMETRY_ITU_601) {
+ if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) {
+ csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
+ auto_csc = AUTO_CSC_DISABLE;
+ c0_c2_change = C0_C2_CHANGE_DISABLE;
+ csc_enable = v_CSC_ENABLE;
+ }
+ } else {
+ if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) {
+ csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
+ auto_csc = AUTO_CSC_DISABLE;
+ c0_c2_change = C0_C2_CHANGE_DISABLE;
+ csc_enable = v_CSC_ENABLE;
+ }
}
}
@@ -473,6 +494,8 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_709;
inno_conn_state->enc_out_format = HDMI_COLORSPACE_RGB;
+ inno_conn_state->rgb_limited_range =
+ drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED;
return 0;
}
@@ -559,6 +582,7 @@ static void inno_hdmi_connector_reset(struct drm_connector *connector)
inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_709;
inno_conn_state->enc_out_format = HDMI_COLORSPACE_RGB;
+ inno_conn_state->rgb_limited_range = false;
}
static struct drm_connector_state *
--
2.43.0
Powered by blists - more mailing lists