2020-03-04 23:26:10

by Jernej Skrabec

[permalink] [raw]
Subject: [PATCH v2 0/4] drm/bridge: dw-hdmi: Various updates

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(-)

--
2.25.1


2020-03-04 23:26:14

by Jernej Skrabec

[permalink] [raw]
Subject: [PATCH v2 2/4] drm/bridge: dw-hdmi: do not force "none" scan mode

From: Jonas Karlman <[email protected]>

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 <[email protected]>
Acked-by: Laurent Pinchart <[email protected]>
Signed-off-by: Jonas Karlman <[email protected]>
[updated commit message]
Signed-off-by: Jernej Skrabec <[email protected]>
---
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
--
2.25.1

2020-03-04 23:26:18

by Jernej Skrabec

[permalink] [raw]
Subject: [PATCH v2 1/4] drm/bridge: dw-hdmi: fix AVI frame colorimetry

CTA-861-F explicitly states that for RGB colorspace colorimetry should
be set to "none". Fix that.

Acked-by: Laurent Pinchart <[email protected]>
Fixes: def23aa7e982 ("drm: bridge: dw-hdmi: Switch to V4L bus format and encodings")
Signed-off-by: Jernej Skrabec <[email protected]>
---
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;
--
2.25.1

2020-03-04 23:26:25

by Jernej Skrabec

[permalink] [raw]
Subject: [PATCH v2 4/4] drm/bridge: dw-hdmi: rework csc related functions

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 <[email protected]>
---
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 */
--
2.25.1

2020-03-04 23:27:11

by Jernej Skrabec

[permalink] [raw]
Subject: [PATCH v2 3/4] drm/bridge: dw-hdmi: Add support for RGB limited range

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 <[email protected]>
---
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;
--
2.25.1

2020-03-04 23:48:36

by Laurent Pinchart

[permalink] [raw]
Subject: Re: [PATCH v2 3/4] drm/bridge: dw-hdmi: Add support for RGB limited range

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 <[email protected]>

Reviewed-by: Laurent Pinchart <[email protected]>

> ---
> 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;

--
Regards,

Laurent Pinchart

2020-03-04 23:52:27

by Laurent Pinchart

[permalink] [raw]
Subject: Re: [PATCH v2 4/4] drm/bridge: dw-hdmi: rework csc related functions

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 <[email protected]>
> ---
> 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 <[email protected]>

> +{
> + 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 */

--
Regards,

Laurent Pinchart

2020-03-05 16:55:03

by Jernej Skrabec

[permalink] [raw]
Subject: Re: [PATCH v2 4/4] drm/bridge: dw-hdmi: rework csc related functions

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 <[email protected]>
> > ---
> >
> > 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 <[email protected]>

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 */




2020-03-05 17:23:04

by Jernej Skrabec

[permalink] [raw]
Subject: Re: [PATCH v2 1/4] drm/bridge: dw-hdmi: fix AVI frame colorimetry

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 <[email protected]>
> Fixes: def23aa7e982 ("drm: bridge: dw-hdmi: Switch to V4L bus format and
> encodings") Signed-off-by: Jernej Skrabec <[email protected]>

Applied to drm-next-fixes.

Best regards,
Jernej