This series fixes multiple issues I found out. Patch 1 fixes reporting colorimetry in AVI frame. Patch 2 sets scan mode to underscan which is in line with most other hdmi drivers. Patch 3 aligns RGB quantization to CEA 861 standard. Patch 4 reworks is_color_space_conversion(). Now it checks only if color space conversion is required. Patch adds separate function for checking if any kind of conversion is required.
Please take a look.
Best regards, Jernej
Changes from v2: - added tags - replaced patch 2 with patch 4 - renamed rgb conversion matrix and make hex lowercase - move logic for checking if rgb full to limited range conversion is needed to is_color_space_conversion() - reworked logic for csc matrix selection
Jernej Skrabec (3): drm/bridge: dw-hdmi: fix AVI frame colorimetry drm/bridge: dw-hdmi: Add support for RGB limited range drm/bridge: dw-hdmi: rework csc related functions
Jonas Karlman (1): drm/bridge: dw-hdmi: do not force "none" scan mode
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 132 ++++++++++++++-------- 1 file changed, 88 insertions(+), 44 deletions(-)
CTA-861-F explicitly states that for RGB colorspace colorimetry should be set to "none". Fix that.
Acked-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Fixes: def23aa7e982 ("drm: bridge: dw-hdmi: Switch to V4L bus format and encodings") Signed-off-by: Jernej Skrabec jernej.skrabec@siol.net --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 46 +++++++++++++---------- 1 file changed, 26 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 67fca439bbfb..24965e53d351 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1624,28 +1624,34 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) frame.colorspace = HDMI_COLORSPACE_RGB;
/* Set up colorimetry */ - switch (hdmi->hdmi_data.enc_out_encoding) { - case V4L2_YCBCR_ENC_601: - if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601) - frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; - else + if (!hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { + switch (hdmi->hdmi_data.enc_out_encoding) { + case V4L2_YCBCR_ENC_601: + if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601) + frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; + else + frame.colorimetry = HDMI_COLORIMETRY_ITU_601; + frame.extended_colorimetry = + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; + break; + case V4L2_YCBCR_ENC_709: + if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709) + frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; + else + frame.colorimetry = HDMI_COLORIMETRY_ITU_709; + frame.extended_colorimetry = + HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; + break; + default: /* Carries no data */ frame.colorimetry = HDMI_COLORIMETRY_ITU_601; + frame.extended_colorimetry = + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; + break; + } + } else { + frame.colorimetry = HDMI_COLORIMETRY_NONE; frame.extended_colorimetry = - HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; - break; - case V4L2_YCBCR_ENC_709: - if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709) - frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; - else - frame.colorimetry = HDMI_COLORIMETRY_ITU_709; - frame.extended_colorimetry = - HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; - break; - default: /* Carries no data */ - frame.colorimetry = HDMI_COLORIMETRY_ITU_601; - frame.extended_colorimetry = - HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; - break; + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; }
frame.scan_mode = HDMI_SCAN_MODE_NONE;
Dne četrtek, 05. marec 2020 ob 00:25:09 CET je Jernej Skrabec napisal(a):
CTA-861-F explicitly states that for RGB colorspace colorimetry should be set to "none". Fix that.
Acked-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Fixes: def23aa7e982 ("drm: bridge: dw-hdmi: Switch to V4L bus format and encodings") Signed-off-by: Jernej Skrabec jernej.skrabec@siol.net
Applied to drm-next-fixes.
Best regards, Jernej
From: Jonas Karlman jonas@kwiboo.se
Setting scan mode to "none" confuses some TVs like LG B8, which randomly change overscan percentage over time. Digital outputs like HDMI and DVI, handled by this controller, don't really need overscan, so we can always set scan mode to underscan. Actually, this is exactly what drm_hdmi_avi_infoframe_from_display_mode() already does, so we can just remove offending line.
Reviewed-by: Neil Armstrong narmstrong@baylibre.com Acked-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Jonas Karlman jonas@kwiboo.se [updated commit message] Signed-off-by: Jernej Skrabec jernej.skrabec@siol.net --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 24965e53d351..de2c7ec887c8 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1654,8 +1654,6 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; }
- frame.scan_mode = HDMI_SCAN_MODE_NONE; - /* * The Designware IP uses a different byte format from standard * AVI info frames, though generally the bits are in the correct
CEA 861 standard requestis that RGB quantization range is "limited" for CEA modes. Support that by adding CSC matrix which downscales values.
This allows proper color reproduction on TV and PC monitor at the same time. In future, override property can be added, like "Broadcast RGB" in i915 driver.
Signed-off-by: Jernej Skrabec jernej.skrabec@siol.net --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 63 +++++++++++++++++------ 1 file changed, 46 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index de2c7ec887c8..c8a02e5b5e1b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -92,6 +92,12 @@ static const u16 csc_coeff_rgb_in_eitu709[3][4] = { { 0x6756, 0x78ab, 0x2000, 0x0200 } };
+static const u16 csc_coeff_rgb_full_to_rgb_limited[3][4] = { + { 0x1b7c, 0x0000, 0x0000, 0x0020 }, + { 0x0000, 0x1b7c, 0x0000, 0x0020 }, + { 0x0000, 0x0000, 0x1b7c, 0x0020 } +}; + struct hdmi_vmode { bool mdataenablepolarity;
@@ -109,6 +115,7 @@ struct hdmi_data_info { unsigned int pix_repet_factor; unsigned int hdcp_enable; struct hdmi_vmode video_mode; + bool rgb_limited_range; };
struct dw_hdmi_i2c { @@ -956,7 +963,11 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
static int is_color_space_conversion(struct dw_hdmi *hdmi) { - return hdmi->hdmi_data.enc_in_bus_format != hdmi->hdmi_data.enc_out_bus_format; + return (hdmi->hdmi_data.enc_in_bus_format != + hdmi->hdmi_data.enc_out_bus_format) || + (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) && + hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) && + hdmi->hdmi_data.rgb_limited_range); }
static int is_color_space_decimation(struct dw_hdmi *hdmi) @@ -986,25 +997,27 @@ static int is_color_space_interpolation(struct dw_hdmi *hdmi) static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi) { const u16 (*csc_coeff)[3][4] = &csc_coeff_default; + bool is_input_rgb, is_output_rgb; unsigned i; u32 csc_scale = 1;
- if (is_color_space_conversion(hdmi)) { - if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { - if (hdmi->hdmi_data.enc_out_encoding == - V4L2_YCBCR_ENC_601) - csc_coeff = &csc_coeff_rgb_out_eitu601; - else - csc_coeff = &csc_coeff_rgb_out_eitu709; - } else if (hdmi_bus_fmt_is_rgb( - hdmi->hdmi_data.enc_in_bus_format)) { - if (hdmi->hdmi_data.enc_out_encoding == - V4L2_YCBCR_ENC_601) - csc_coeff = &csc_coeff_rgb_in_eitu601; - else - csc_coeff = &csc_coeff_rgb_in_eitu709; - csc_scale = 0; - } + is_input_rgb = hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format); + is_output_rgb = hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format); + + if (!is_input_rgb && is_output_rgb) { + if (hdmi->hdmi_data.enc_out_encoding == V4L2_YCBCR_ENC_601) + csc_coeff = &csc_coeff_rgb_out_eitu601; + else + csc_coeff = &csc_coeff_rgb_out_eitu709; + } else if (is_input_rgb && !is_output_rgb) { + if (hdmi->hdmi_data.enc_out_encoding == V4L2_YCBCR_ENC_601) + csc_coeff = &csc_coeff_rgb_in_eitu601; + else + csc_coeff = &csc_coeff_rgb_in_eitu709; + csc_scale = 0; + } else if (is_input_rgb && is_output_rgb && + hdmi->hdmi_data.rgb_limited_range) { + csc_coeff = &csc_coeff_rgb_full_to_rgb_limited; }
/* The CSC registers are sequential, alternating MSB then LSB */ @@ -1614,6 +1627,18 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) drm_hdmi_avi_infoframe_from_display_mode(&frame, &hdmi->connector, mode);
+ if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { + drm_hdmi_avi_infoframe_quant_range(&frame, &hdmi->connector, + mode, + hdmi->hdmi_data.rgb_limited_range ? + HDMI_QUANTIZATION_RANGE_LIMITED : + HDMI_QUANTIZATION_RANGE_FULL); + } else { + frame.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT; + frame.ycc_quantization_range = + HDMI_YCC_QUANTIZATION_RANGE_LIMITED; + } + if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) frame.colorspace = HDMI_COLORSPACE_YUV444; else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) @@ -2099,6 +2124,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) /* TOFIX: Default to RGB888 output format */ hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+ hdmi->hdmi_data.rgb_limited_range = hdmi->sink_is_hdmi && + drm_default_rgb_quant_range(mode) == + HDMI_QUANTIZATION_RANGE_LIMITED; + hdmi->hdmi_data.pix_repet_factor = 0; hdmi->hdmi_data.hdcp_enable = 0; hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
Hi Jernej,
Thank you for the patch.
On Thu, Mar 05, 2020 at 12:25:11AM +0100, Jernej Skrabec wrote:
CEA 861 standard requestis that RGB quantization range is "limited" for CEA modes. Support that by adding CSC matrix which downscales values.
This allows proper color reproduction on TV and PC monitor at the same time. In future, override property can be added, like "Broadcast RGB" in i915 driver.
Signed-off-by: Jernej Skrabec jernej.skrabec@siol.net
Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 63 +++++++++++++++++------ 1 file changed, 46 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index de2c7ec887c8..c8a02e5b5e1b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -92,6 +92,12 @@ static const u16 csc_coeff_rgb_in_eitu709[3][4] = { { 0x6756, 0x78ab, 0x2000, 0x0200 } };
+static const u16 csc_coeff_rgb_full_to_rgb_limited[3][4] = {
- { 0x1b7c, 0x0000, 0x0000, 0x0020 },
- { 0x0000, 0x1b7c, 0x0000, 0x0020 },
- { 0x0000, 0x0000, 0x1b7c, 0x0020 }
+};
struct hdmi_vmode { bool mdataenablepolarity;
@@ -109,6 +115,7 @@ struct hdmi_data_info { unsigned int pix_repet_factor; unsigned int hdcp_enable; struct hdmi_vmode video_mode;
- bool rgb_limited_range;
};
struct dw_hdmi_i2c { @@ -956,7 +963,11 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
static int is_color_space_conversion(struct dw_hdmi *hdmi) {
- return hdmi->hdmi_data.enc_in_bus_format != hdmi->hdmi_data.enc_out_bus_format;
- return (hdmi->hdmi_data.enc_in_bus_format !=
hdmi->hdmi_data.enc_out_bus_format) ||
(hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) &&
hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) &&
hdmi->hdmi_data.rgb_limited_range);
}
static int is_color_space_decimation(struct dw_hdmi *hdmi) @@ -986,25 +997,27 @@ static int is_color_space_interpolation(struct dw_hdmi *hdmi) static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi) { const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
- bool is_input_rgb, is_output_rgb; unsigned i; u32 csc_scale = 1;
- if (is_color_space_conversion(hdmi)) {
if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
if (hdmi->hdmi_data.enc_out_encoding ==
V4L2_YCBCR_ENC_601)
csc_coeff = &csc_coeff_rgb_out_eitu601;
else
csc_coeff = &csc_coeff_rgb_out_eitu709;
} else if (hdmi_bus_fmt_is_rgb(
hdmi->hdmi_data.enc_in_bus_format)) {
if (hdmi->hdmi_data.enc_out_encoding ==
V4L2_YCBCR_ENC_601)
csc_coeff = &csc_coeff_rgb_in_eitu601;
else
csc_coeff = &csc_coeff_rgb_in_eitu709;
csc_scale = 0;
}
is_input_rgb = hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format);
is_output_rgb = hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format);
if (!is_input_rgb && is_output_rgb) {
if (hdmi->hdmi_data.enc_out_encoding == V4L2_YCBCR_ENC_601)
csc_coeff = &csc_coeff_rgb_out_eitu601;
else
csc_coeff = &csc_coeff_rgb_out_eitu709;
} else if (is_input_rgb && !is_output_rgb) {
if (hdmi->hdmi_data.enc_out_encoding == V4L2_YCBCR_ENC_601)
csc_coeff = &csc_coeff_rgb_in_eitu601;
else
csc_coeff = &csc_coeff_rgb_in_eitu709;
csc_scale = 0;
} else if (is_input_rgb && is_output_rgb &&
hdmi->hdmi_data.rgb_limited_range) {
csc_coeff = &csc_coeff_rgb_full_to_rgb_limited;
}
/* The CSC registers are sequential, alternating MSB then LSB */
@@ -1614,6 +1627,18 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) drm_hdmi_avi_infoframe_from_display_mode(&frame, &hdmi->connector, mode);
- if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
drm_hdmi_avi_infoframe_quant_range(&frame, &hdmi->connector,
mode,
hdmi->hdmi_data.rgb_limited_range ?
HDMI_QUANTIZATION_RANGE_LIMITED :
HDMI_QUANTIZATION_RANGE_FULL);
- } else {
frame.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
frame.ycc_quantization_range =
HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
- }
- if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) frame.colorspace = HDMI_COLORSPACE_YUV444; else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
@@ -2099,6 +2124,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) /* TOFIX: Default to RGB888 output format */ hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
- hdmi->hdmi_data.rgb_limited_range = hdmi->sink_is_hdmi &&
drm_default_rgb_quant_range(mode) ==
HDMI_QUANTIZATION_RANGE_LIMITED;
- hdmi->hdmi_data.pix_repet_factor = 0; hdmi->hdmi_data.hdcp_enable = 0; hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
is_color_space_conversion() is a misnomer. It checks not only if color space conversion is needed, but also if format conversion is needed. This is actually desired behaviour because result of this function determines if CSC block should be enabled or not (CSC block can also do format conversion).
In order to clear misunderstandings, let's rework is_color_space_conversion() to do exactly what is supposed to do and add another function which will determine if CSC block must be enabled or not.
Signed-off-by: Jernej Skrabec jernej.skrabec@siol.net --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 31 +++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index c8a02e5b5e1b..7724191e0a8b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -963,11 +963,14 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
static int is_color_space_conversion(struct dw_hdmi *hdmi) { - return (hdmi->hdmi_data.enc_in_bus_format != - hdmi->hdmi_data.enc_out_bus_format) || - (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) && - hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) && - hdmi->hdmi_data.rgb_limited_range); + struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data; + bool is_input_rgb, is_output_rgb; + + is_input_rgb = hdmi_bus_fmt_is_rgb(hdmi_data->enc_in_bus_format); + is_output_rgb = hdmi_bus_fmt_is_rgb(hdmi_data->enc_out_bus_format); + + return (is_input_rgb != is_output_rgb) || + (is_input_rgb && is_output_rgb && hdmi_data->rgb_limited_range); }
static int is_color_space_decimation(struct dw_hdmi *hdmi) @@ -994,6 +997,13 @@ static int is_color_space_interpolation(struct dw_hdmi *hdmi) return 0; }
+static bool is_conversion_needed(struct dw_hdmi *hdmi) +{ + return is_color_space_conversion(hdmi) || + is_color_space_decimation(hdmi) || + is_color_space_interpolation(hdmi); +} + static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi) { const u16 (*csc_coeff)[3][4] = &csc_coeff_default; @@ -2014,18 +2024,19 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
/* Enable csc path */ - if (is_color_space_conversion(hdmi)) { + if (is_conversion_needed(hdmi)) { hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE; hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); - }
- /* Enable color space conversion if needed */ - if (is_color_space_conversion(hdmi)) hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH, HDMI_MC_FLOWCTRL); - else + } else { + hdmi->mc_clkdis |= HDMI_MC_CLKDIS_CSCCLK_DISABLE; + hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); + hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS, HDMI_MC_FLOWCTRL); + } }
/* Workaround to clear the overflow condition */
Hi Jernej,
Thank you for the patch.
On Thu, Mar 05, 2020 at 12:25:12AM +0100, Jernej Skrabec wrote:
is_color_space_conversion() is a misnomer. It checks not only if color space conversion is needed, but also if format conversion is needed. This is actually desired behaviour because result of this function determines if CSC block should be enabled or not (CSC block can also do format conversion).
In order to clear misunderstandings, let's rework is_color_space_conversion() to do exactly what is supposed to do and add another function which will determine if CSC block must be enabled or not.
Signed-off-by: Jernej Skrabec jernej.skrabec@siol.net
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 31 +++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index c8a02e5b5e1b..7724191e0a8b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -963,11 +963,14 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
static int is_color_space_conversion(struct dw_hdmi *hdmi) {
- return (hdmi->hdmi_data.enc_in_bus_format !=
hdmi->hdmi_data.enc_out_bus_format) ||
(hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) &&
hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) &&
hdmi->hdmi_data.rgb_limited_range);
- struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
- bool is_input_rgb, is_output_rgb;
- is_input_rgb = hdmi_bus_fmt_is_rgb(hdmi_data->enc_in_bus_format);
- is_output_rgb = hdmi_bus_fmt_is_rgb(hdmi_data->enc_out_bus_format);
- return (is_input_rgb != is_output_rgb) ||
(is_input_rgb && is_output_rgb && hdmi_data->rgb_limited_range);
}
static int is_color_space_decimation(struct dw_hdmi *hdmi) @@ -994,6 +997,13 @@ static int is_color_space_interpolation(struct dw_hdmi *hdmi) return 0; }
+static bool is_conversion_needed(struct dw_hdmi *hdmi)
Maybe is_csc_needed ?
Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
+{
- return is_color_space_conversion(hdmi) ||
is_color_space_decimation(hdmi) ||
is_color_space_interpolation(hdmi);
+}
static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi) { const u16 (*csc_coeff)[3][4] = &csc_coeff_default; @@ -2014,18 +2024,19 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
/* Enable csc path */
- if (is_color_space_conversion(hdmi)) {
- if (is_conversion_needed(hdmi)) { hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE; hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
}
/* Enable color space conversion if needed */
if (is_color_space_conversion(hdmi)) hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH, HDMI_MC_FLOWCTRL);
else
- } else {
hdmi->mc_clkdis |= HDMI_MC_CLKDIS_CSCCLK_DISABLE;
hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
- hdmi_writeb(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS, HDMI_MC_FLOWCTRL);
- }
}
/* Workaround to clear the overflow condition */
Hi Laurent,
Dne četrtek, 05. marec 2020 ob 00:51:49 CET je Laurent Pinchart napisal(a):
Hi Jernej,
Thank you for the patch.
On Thu, Mar 05, 2020 at 12:25:12AM +0100, Jernej Skrabec wrote:
is_color_space_conversion() is a misnomer. It checks not only if color space conversion is needed, but also if format conversion is needed. This is actually desired behaviour because result of this function determines if CSC block should be enabled or not (CSC block can also do format conversion).
In order to clear misunderstandings, let's rework is_color_space_conversion() to do exactly what is supposed to do and add another function which will determine if CSC block must be enabled or not.
Signed-off-by: Jernej Skrabec jernej.skrabec@siol.net
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 31 +++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index c8a02e5b5e1b..7724191e0a8b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -963,11 +963,14 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
static int is_color_space_conversion(struct dw_hdmi *hdmi) {
- return (hdmi->hdmi_data.enc_in_bus_format !=
hdmi->hdmi_data.enc_out_bus_format) ||
(hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) &&
hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)
&&
hdmi->hdmi_data.rgb_limited_range);
- struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
- bool is_input_rgb, is_output_rgb;
- is_input_rgb = hdmi_bus_fmt_is_rgb(hdmi_data->enc_in_bus_format);
- is_output_rgb = hdmi_bus_fmt_is_rgb(hdmi_data-
enc_out_bus_format);
- return (is_input_rgb != is_output_rgb) ||
(is_input_rgb && is_output_rgb && hdmi_data-
rgb_limited_range);
}
static int is_color_space_decimation(struct dw_hdmi *hdmi)
@@ -994,6 +997,13 @@ static int is_color_space_interpolation(struct dw_hdmi *hdmi)> return 0;
}
+static bool is_conversion_needed(struct dw_hdmi *hdmi)
Maybe is_csc_needed ?
Ok, I'll fix during applying.
Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
Thanks!
Best regards, Jernej
+{
- return is_color_space_conversion(hdmi) ||
is_color_space_decimation(hdmi) ||
is_color_space_interpolation(hdmi);
+}
static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi) {
const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
@@ -2014,18 +2024,19 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)> hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
/* Enable csc path */
- if (is_color_space_conversion(hdmi)) {
if (is_conversion_needed(hdmi)) {
hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE; hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
}
/* Enable color space conversion if needed */
if (is_color_space_conversion(hdmi))
hdmi_writeb(hdmi,
HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
HDMI_MC_FLOWCTRL);
- else
} else {
hdmi->mc_clkdis |= HDMI_MC_CLKDIS_CSCCLK_DISABLE;
hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
hdmi_writeb(hdmi,
HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
HDMI_MC_FLOWCTRL);
- }
}
/* Workaround to clear the overflow condition */
dri-devel@lists.freedesktop.org