diff mbox series

[3/4] Restructure output format computation for better expandability

Message ID 20210503182148.851790-4-wse@tuxedocomputers.com (mailing list archive)
State New, archived
Headers show
Series drm/i915/display Try YCbCr420 color when RGB fails | expand

Commit Message

Werner Sembach May 3, 2021, 6:21 p.m. UTC
Couples the decission between RGB and YCbCr420 mode and the check if the port
clock can archive the required frequency. Other checks and configuration steps
that where previously done in between can also be done before or after.

This allows for are cleaner implementation of retrying different color
encodings.

Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
---

From 57e42ec6e34ac32da29eb7bc3c691cbeb2534396 Mon Sep 17 00:00:00 2001
From: Werner Sembach <wse@tuxedocomputers.com>
Date: Mon, 3 May 2021 15:30:40 +0200
Subject: [PATCH 3/4] Restructure output format computation for better
 expandability

---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 57 +++++++++++------------
 1 file changed, 26 insertions(+), 31 deletions(-)

Comments

kernel test robot May 3, 2021, 9:03 p.m. UTC | #1
Hi Werner,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20210503]
[cannot apply to v5.12]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Werner-Sembach/drm-i915-display-Try-YCbCr420-color-when-RGB-fails/20210504-022344
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-randconfig-m021-20210503 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/8ff372234cbfe66eb5a59c2cda6a44961f5a9266
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Werner-Sembach/drm-i915-display-Try-YCbCr420-color-when-RGB-fails/20210504-022344
        git checkout 8ff372234cbfe66eb5a59c2cda6a44961f5a9266
        # save the attached .config to linux build tree
        make W=1 W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/gpu/drm/i915/display/intel_hdmi.c:2108:5: error: no previous prototype for 'intel_hdmi_compute_output_format' [-Werror=missing-prototypes]
    2108 | int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
         |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: all warnings being treated as errors


vim +/intel_hdmi_compute_output_format +2108 drivers/gpu/drm/i915/display/intel_hdmi.c

  2107	
> 2108	int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
  2109					     struct intel_crtc_state *crtc_state,
  2110					     const struct drm_connector_state *conn_state)
  2111	{
  2112		const struct drm_connector *connector = conn_state->connector;
  2113		const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
  2114		int ret;
  2115	
  2116		if (connector->ycbcr_420_allowed && drm_mode_is_420_only(&connector->display_info, adjusted_mode))
  2117			crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
  2118		else
  2119			crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
  2120	
  2121		ret = intel_hdmi_compute_clock(encoder, crtc_state);
  2122	
  2123		return ret;
  2124	}
  2125	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot May 3, 2021, 10:55 p.m. UTC | #2
Hi Werner,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20210503]
[cannot apply to v5.12]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Werner-Sembach/drm-i915-display-Try-YCbCr420-color-when-RGB-fails/20210504-022344
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-randconfig-r025-20210503 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 8f5a2a5836cc8e4c1def2bdeb022e7b496623439)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/8ff372234cbfe66eb5a59c2cda6a44961f5a9266
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Werner-Sembach/drm-i915-display-Try-YCbCr420-color-when-RGB-fails/20210504-022344
        git checkout 8ff372234cbfe66eb5a59c2cda6a44961f5a9266
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/gpu/drm/i915/display/intel_hdmi.c:2108:5: error: no previous prototype for function 'intel_hdmi_compute_output_format' [-Werror,-Wmissing-prototypes]
   int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
       ^
   drivers/gpu/drm/i915/display/intel_hdmi.c:2108:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
   ^
   static 
   1 error generated.


vim +/intel_hdmi_compute_output_format +2108 drivers/gpu/drm/i915/display/intel_hdmi.c

  2107	
> 2108	int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
  2109					     struct intel_crtc_state *crtc_state,
  2110					     const struct drm_connector_state *conn_state)
  2111	{
  2112		const struct drm_connector *connector = conn_state->connector;
  2113		const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
  2114		int ret;
  2115	
  2116		if (connector->ycbcr_420_allowed && drm_mode_is_420_only(&connector->display_info, adjusted_mode))
  2117			crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
  2118		else
  2119			crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
  2120	
  2121		ret = intel_hdmi_compute_clock(encoder, crtc_state);
  2122	
  2123		return ret;
  2124	}
  2125	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Ville Syrjala May 4, 2021, 9:54 a.m. UTC | #3
On Mon, May 03, 2021 at 08:21:47PM +0200, Werner Sembach wrote:
> Couples the decission between RGB and YCbCr420 mode and the check if the port
> clock can archive the required frequency. Other checks and configuration steps
> that where previously done in between can also be done before or after.
> 
> This allows for are cleaner implementation of retrying different color
> encodings.
> 
> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> ---
> 
> >From 57e42ec6e34ac32da29eb7bc3c691cbeb2534396 Mon Sep 17 00:00:00 2001
> From: Werner Sembach <wse@tuxedocomputers.com>
> Date: Mon, 3 May 2021 15:30:40 +0200
> Subject: [PATCH 3/4] Restructure output format computation for better
>  expandability
> 
> ---
>  drivers/gpu/drm/i915/display/intel_hdmi.c | 57 +++++++++++------------
>  1 file changed, 26 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
> index ce165ef28e88..e2553ac6fd13 100644
> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
> @@ -1999,29 +1999,6 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
>  					      INTEL_OUTPUT_FORMAT_YCBCR420);
>  }
>  
> -static int
> -intel_hdmi_ycbcr420_config(struct intel_crtc_state *crtc_state,
> -			   const struct drm_connector_state *conn_state)
> -{
> -	struct drm_connector *connector = conn_state->connector;
> -	struct drm_i915_private *i915 = to_i915(connector->dev);
> -	const struct drm_display_mode *adjusted_mode =
> -		&crtc_state->hw.adjusted_mode;
> -
> -	if (!drm_mode_is_420_only(&connector->display_info, adjusted_mode))
> -		return 0;
> -
> -	if (!connector->ycbcr_420_allowed) {
> -		drm_err(&i915->drm,
> -			"Platform doesn't support YCBCR420 output\n");
> -		return -EINVAL;
> -	}
> -
> -	crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
> -
> -	return intel_pch_panel_fitting(crtc_state, conn_state);
> -}
> -
>  static int intel_hdmi_compute_bpc(struct intel_encoder *encoder,
>  				  struct intel_crtc_state *crtc_state,
>  				  int clock)
> @@ -2128,6 +2105,24 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
>  		return intel_conn_state->force_audio == HDMI_AUDIO_ON;
>  }
>  
> +int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
> +				     struct intel_crtc_state *crtc_state,
> +				     const struct drm_connector_state *conn_state)
> +{
> +	const struct drm_connector *connector = conn_state->connector;
> +	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
> +	int ret;
> +
> +	if (connector->ycbcr_420_allowed && drm_mode_is_420_only(&connector->display_info, adjusted_mode))
> +		crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
> +	else
> +		crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;

Slight change in behaviour here since we used to reject 420_only modes
if ycbcr_420_allowed wasn't set. But I think this should be OK, and in
fact I believe the DP counterpart code always used an RGB fallback
rather than failing. So this lines up better with that.

Needs at least a note in the commit message to indicate that
there is a functional change buried within. Though it would be
better to split this functional change into a separate prep patch.

> +
> +	ret = intel_hdmi_compute_clock(encoder, crtc_state);
> +
> +	return ret;
> +}
> +
>  int intel_hdmi_compute_config(struct intel_encoder *encoder,
>  			      struct intel_crtc_state *pipe_config,
>  			      struct drm_connector_state *conn_state)
> @@ -2152,23 +2147,23 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
>  	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
>  		pipe_config->pixel_multiplier = 2;
>  
> -	ret = intel_hdmi_ycbcr420_config(pipe_config, conn_state);
> -	if (ret)
> -		return ret;
> -
> -	pipe_config->limited_color_range =
> -		intel_hdmi_limited_color_range(pipe_config, conn_state);
> -
>  	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
>  		pipe_config->has_pch_encoder = true;
>  
>  	pipe_config->has_audio =
>  		intel_hdmi_has_audio(encoder, pipe_config, conn_state);
>  
> -	ret = intel_hdmi_compute_clock(encoder, pipe_config);
> +	ret = intel_hdmi_compute_output_format(encoder, pipe_config, conn_state);
>  	if (ret)
>  		return ret;
>  
> +	ret = intel_pch_panel_fitting(pipe_config, conn_state);
> +	if (ret)
> +		return ret;

We probably want to still wrap this call in a
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {...}

In theory calling intel_pch_panel_fitting() should be a nop for
the !420 case, but I think we have some issues there at least when
it comes to bigjoiner. So the 420 check is probably needed to avoid
mistakenly turning on the panel fitter when not needed.


> +
> +	pipe_config->limited_color_range =
> +		intel_hdmi_limited_color_range(pipe_config, conn_state);
> +
>  	if (conn_state->picture_aspect_ratio)
>  		adjusted_mode->picture_aspect_ratio =
>  			conn_state->picture_aspect_ratio;
> -- 
> 2.25.1
Werner Sembach May 5, 2021, 9:54 a.m. UTC | #4
Am 04.05.21 um 11:54 schrieb Ville Syrjälä:

> On Mon, May 03, 2021 at 08:21:47PM +0200, Werner Sembach wrote:
>> Couples the decission between RGB and YCbCr420 mode and the check if the port
>> clock can archive the required frequency. Other checks and configuration steps
>> that where previously done in between can also be done before or after.
>>
>> This allows for are cleaner implementation of retrying different color
>> encodings.
>>
>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>> ---
>>
>> >From 57e42ec6e34ac32da29eb7bc3c691cbeb2534396 Mon Sep 17 00:00:00 2001
>> From: Werner Sembach <wse@tuxedocomputers.com>
>> Date: Mon, 3 May 2021 15:30:40 +0200
>> Subject: [PATCH 3/4] Restructure output format computation for better
>>  expandability
>>
>> ---
>>  drivers/gpu/drm/i915/display/intel_hdmi.c | 57 +++++++++++------------
>>  1 file changed, 26 insertions(+), 31 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
>> index ce165ef28e88..e2553ac6fd13 100644
>> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
>> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
>> @@ -1999,29 +1999,6 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
>>  					      INTEL_OUTPUT_FORMAT_YCBCR420);
>>  }
>>  
>> -static int
>> -intel_hdmi_ycbcr420_config(struct intel_crtc_state *crtc_state,
>> -			   const struct drm_connector_state *conn_state)
>> -{
>> -	struct drm_connector *connector = conn_state->connector;
>> -	struct drm_i915_private *i915 = to_i915(connector->dev);
>> -	const struct drm_display_mode *adjusted_mode =
>> -		&crtc_state->hw.adjusted_mode;
>> -
>> -	if (!drm_mode_is_420_only(&connector->display_info, adjusted_mode))
>> -		return 0;
>> -
>> -	if (!connector->ycbcr_420_allowed) {
>> -		drm_err(&i915->drm,
>> -			"Platform doesn't support YCBCR420 output\n");
>> -		return -EINVAL;
>> -	}
>> -
>> -	crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
>> -
>> -	return intel_pch_panel_fitting(crtc_state, conn_state);
>> -}
>> -
>>  static int intel_hdmi_compute_bpc(struct intel_encoder *encoder,
>>  				  struct intel_crtc_state *crtc_state,
>>  				  int clock)
>> @@ -2128,6 +2105,24 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
>>  		return intel_conn_state->force_audio == HDMI_AUDIO_ON;
>>  }
>>  
>> +int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
>> +				     struct intel_crtc_state *crtc_state,
>> +				     const struct drm_connector_state *conn_state)
>> +{
>> +	const struct drm_connector *connector = conn_state->connector;
>> +	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
>> +	int ret;
>> +
>> +	if (connector->ycbcr_420_allowed && drm_mode_is_420_only(&connector->display_info, adjusted_mode))
>> +		crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
>> +	else
>> +		crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
> Slight change in behaviour here since we used to reject 420_only modes
> if ycbcr_420_allowed wasn't set. But I think this should be OK, and in
> fact I believe the DP counterpart code always used an RGB fallback
> rather than failing. So this lines up better with that.

That was actually an oversight on my side and not intended. Does a RGB fallback make sense?

Now that I think of it get to 2 scenarios:

- The screen is really 420_only, which causes a silent fail and a black screen I guess? Where before at least a log message was written.

- The screen falsely reports as 420_only and using RGB regardless makes it magically work

I think at least warning should be printed to the logs. Something along the lines of: "Display reports as 420 only, but port does not support 420, try forcing RGB, but this is likely to fail."
> Needs at least a note in the commit message to indicate that
> there is a functional change buried within. Though it would be
> better to split this functional change into a separate prep patch.
>
>> +
>> +	ret = intel_hdmi_compute_clock(encoder, crtc_state);
>> +
>> +	return ret;
>> +}
>> +
>>  int intel_hdmi_compute_config(struct intel_encoder *encoder,
>>  			      struct intel_crtc_state *pipe_config,
>>  			      struct drm_connector_state *conn_state)
>> @@ -2152,23 +2147,23 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
>>  	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
>>  		pipe_config->pixel_multiplier = 2;
>>  
>> -	ret = intel_hdmi_ycbcr420_config(pipe_config, conn_state);
>> -	if (ret)
>> -		return ret;
>> -
>> -	pipe_config->limited_color_range =
>> -		intel_hdmi_limited_color_range(pipe_config, conn_state);
>> -
>>  	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
>>  		pipe_config->has_pch_encoder = true;
>>  
>>  	pipe_config->has_audio =
>>  		intel_hdmi_has_audio(encoder, pipe_config, conn_state);
>>  
>> -	ret = intel_hdmi_compute_clock(encoder, pipe_config);
>> +	ret = intel_hdmi_compute_output_format(encoder, pipe_config, conn_state);
>>  	if (ret)
>>  		return ret;
>>  
>> +	ret = intel_pch_panel_fitting(pipe_config, conn_state);
>> +	if (ret)
>> +		return ret;
> We probably want to still wrap this call in a
> if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {...}
>
> In theory calling intel_pch_panel_fitting() should be a nop for
> the !420 case, but I think we have some issues there at least when
> it comes to bigjoiner. So the 420 check is probably needed to avoid
> mistakenly turning on the panel fitter when not needed.
>
>
>> +
>> +	pipe_config->limited_color_range =
>> +		intel_hdmi_limited_color_range(pipe_config, conn_state);
>> +
>>  	if (conn_state->picture_aspect_ratio)
>>  		adjusted_mode->picture_aspect_ratio =
>>  			conn_state->picture_aspect_ratio;
>> -- 
>> 2.25.1
Ville Syrjala May 5, 2021, 12:15 p.m. UTC | #5
On Wed, May 05, 2021 at 11:54:35AM +0200, Werner Sembach wrote:
> Am 04.05.21 um 11:54 schrieb Ville Syrjälä:
> 
> > On Mon, May 03, 2021 at 08:21:47PM +0200, Werner Sembach wrote:
> >> Couples the decission between RGB and YCbCr420 mode and the check if the port
> >> clock can archive the required frequency. Other checks and configuration steps
> >> that where previously done in between can also be done before or after.
> >>
> >> This allows for are cleaner implementation of retrying different color
> >> encodings.
> >>
> >> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> >> ---
> >>
> >> >From 57e42ec6e34ac32da29eb7bc3c691cbeb2534396 Mon Sep 17 00:00:00 2001
> >> From: Werner Sembach <wse@tuxedocomputers.com>
> >> Date: Mon, 3 May 2021 15:30:40 +0200
> >> Subject: [PATCH 3/4] Restructure output format computation for better
> >>  expandability
> >>
> >> ---
> >>  drivers/gpu/drm/i915/display/intel_hdmi.c | 57 +++++++++++------------
> >>  1 file changed, 26 insertions(+), 31 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
> >> index ce165ef28e88..e2553ac6fd13 100644
> >> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
> >> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
> >> @@ -1999,29 +1999,6 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
> >>  					      INTEL_OUTPUT_FORMAT_YCBCR420);
> >>  }
> >>  
> >> -static int
> >> -intel_hdmi_ycbcr420_config(struct intel_crtc_state *crtc_state,
> >> -			   const struct drm_connector_state *conn_state)
> >> -{
> >> -	struct drm_connector *connector = conn_state->connector;
> >> -	struct drm_i915_private *i915 = to_i915(connector->dev);
> >> -	const struct drm_display_mode *adjusted_mode =
> >> -		&crtc_state->hw.adjusted_mode;
> >> -
> >> -	if (!drm_mode_is_420_only(&connector->display_info, adjusted_mode))
> >> -		return 0;
> >> -
> >> -	if (!connector->ycbcr_420_allowed) {
> >> -		drm_err(&i915->drm,
> >> -			"Platform doesn't support YCBCR420 output\n");
> >> -		return -EINVAL;
> >> -	}
> >> -
> >> -	crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
> >> -
> >> -	return intel_pch_panel_fitting(crtc_state, conn_state);
> >> -}
> >> -
> >>  static int intel_hdmi_compute_bpc(struct intel_encoder *encoder,
> >>  				  struct intel_crtc_state *crtc_state,
> >>  				  int clock)
> >> @@ -2128,6 +2105,24 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
> >>  		return intel_conn_state->force_audio == HDMI_AUDIO_ON;
> >>  }
> >>  
> >> +int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
> >> +				     struct intel_crtc_state *crtc_state,
> >> +				     const struct drm_connector_state *conn_state)
> >> +{
> >> +	const struct drm_connector *connector = conn_state->connector;
> >> +	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
> >> +	int ret;
> >> +
> >> +	if (connector->ycbcr_420_allowed && drm_mode_is_420_only(&connector->display_info, adjusted_mode))
> >> +		crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
> >> +	else
> >> +		crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
> > Slight change in behaviour here since we used to reject 420_only modes
> > if ycbcr_420_allowed wasn't set. But I think this should be OK, and in
> > fact I believe the DP counterpart code always used an RGB fallback
> > rather than failing. So this lines up better with that.
> 
> That was actually an oversight on my side and not intended. Does a RGB fallback make sense?
> 
> Now that I think of it get to 2 scenarios:
> 
> - The screen is really 420_only, which causes a silent fail and a black screen I guess? Where before at least a log message was written.
> 
> - The screen falsely reports as 420_only and using RGB regardless makes it magically work
> 
> I think at least warning should be printed to the logs. Something along the lines of: "Display reports as 420 only, but port does not support 420, try forcing RGB, but this is likely to fail."

I would just put it into the "user has decided to override the mode and
gets to keep both pieces if it breaks". Typical users would not hit that
since they will only use modes reported by the connector as supported.

So I think the RGB fallback is totally in line with existing behaviour
of the driver. We have other cases where we just ignore the reported
limits of the display if the user overrides the mode manually.
Werner Sembach May 5, 2021, 1:02 p.m. UTC | #6
Am 05.05.21 um 14:15 schrieb Ville Syrjälä:
> On Wed, May 05, 2021 at 11:54:35AM +0200, Werner Sembach wrote:
>> Am 04.05.21 um 11:54 schrieb Ville Syrjälä:
>>
>>> On Mon, May 03, 2021 at 08:21:47PM +0200, Werner Sembach wrote:
>>>> Couples the decission between RGB and YCbCr420 mode and the check if the port
>>>> clock can archive the required frequency. Other checks and configuration steps
>>>> that where previously done in between can also be done before or after.
>>>>
>>>> This allows for are cleaner implementation of retrying different color
>>>> encodings.
>>>>
>>>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>>>> ---
>>>>
>>>> >From 57e42ec6e34ac32da29eb7bc3c691cbeb2534396 Mon Sep 17 00:00:00 2001
>>>> From: Werner Sembach <wse@tuxedocomputers.com>
>>>> Date: Mon, 3 May 2021 15:30:40 +0200
>>>> Subject: [PATCH 3/4] Restructure output format computation for better
>>>>  expandability
>>>>
>>>> ---
>>>>  drivers/gpu/drm/i915/display/intel_hdmi.c | 57 +++++++++++------------
>>>>  1 file changed, 26 insertions(+), 31 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
>>>> index ce165ef28e88..e2553ac6fd13 100644
>>>> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
>>>> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
>>>> @@ -1999,29 +1999,6 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
>>>>  					      INTEL_OUTPUT_FORMAT_YCBCR420);
>>>>  }
>>>>  
>>>> -static int
>>>> -intel_hdmi_ycbcr420_config(struct intel_crtc_state *crtc_state,
>>>> -			   const struct drm_connector_state *conn_state)
>>>> -{
>>>> -	struct drm_connector *connector = conn_state->connector;
>>>> -	struct drm_i915_private *i915 = to_i915(connector->dev);
>>>> -	const struct drm_display_mode *adjusted_mode =
>>>> -		&crtc_state->hw.adjusted_mode;
>>>> -
>>>> -	if (!drm_mode_is_420_only(&connector->display_info, adjusted_mode))
>>>> -		return 0;
>>>> -
>>>> -	if (!connector->ycbcr_420_allowed) {
>>>> -		drm_err(&i915->drm,
>>>> -			"Platform doesn't support YCBCR420 output\n");
>>>> -		return -EINVAL;
>>>> -	}
>>>> -
>>>> -	crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
>>>> -
>>>> -	return intel_pch_panel_fitting(crtc_state, conn_state);
>>>> -}
>>>> -
>>>>  static int intel_hdmi_compute_bpc(struct intel_encoder *encoder,
>>>>  				  struct intel_crtc_state *crtc_state,
>>>>  				  int clock)
>>>> @@ -2128,6 +2105,24 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
>>>>  		return intel_conn_state->force_audio == HDMI_AUDIO_ON;
>>>>  }
>>>>  
>>>> +int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
>>>> +				     struct intel_crtc_state *crtc_state,
>>>> +				     const struct drm_connector_state *conn_state)
>>>> +{
>>>> +	const struct drm_connector *connector = conn_state->connector;
>>>> +	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
>>>> +	int ret;
>>>> +
>>>> +	if (connector->ycbcr_420_allowed && drm_mode_is_420_only(&connector->display_info, adjusted_mode))
>>>> +		crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
>>>> +	else
>>>> +		crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
>>> Slight change in behaviour here since we used to reject 420_only modes
>>> if ycbcr_420_allowed wasn't set. But I think this should be OK, and in
>>> fact I believe the DP counterpart code always used an RGB fallback
>>> rather than failing. So this lines up better with that.
>> That was actually an oversight on my side and not intended. Does a RGB fallback make sense?
>>
>> Now that I think of it get to 2 scenarios:
>>
>> - The screen is really 420_only, which causes a silent fail and a black screen I guess? Where before at least a log message was written.
>>
>> - The screen falsely reports as 420_only and using RGB regardless makes it magically work
>>
>> I think at least warning should be printed to the logs. Something along the lines of: "Display reports as 420 only, but port does not support 420, try forcing RGB, but this is likely to fail."
> I would just put it into the "user has decided to override the mode and
> gets to keep both pieces if it breaks". Typical users would not hit that
> since they will only use modes reported by the connector as supported.
>
> So I think the RGB fallback is totally in line with existing behaviour
> of the driver. We have other cases where we just ignore the reported
> limits of the display if the user overrides the mode manually.
>
Did I get you right that "connector->ycbcr_420_allowed" is a user setting and not automatically filled configuration depending on hardware capabilities?
Ville Syrjala May 5, 2021, 1:59 p.m. UTC | #7
On Wed, May 05, 2021 at 03:02:53PM +0200, Werner Sembach wrote:
> 
> Am 05.05.21 um 14:15 schrieb Ville Syrjälä:
> > On Wed, May 05, 2021 at 11:54:35AM +0200, Werner Sembach wrote:
> >> Am 04.05.21 um 11:54 schrieb Ville Syrjälä:
> >>
> >>> On Mon, May 03, 2021 at 08:21:47PM +0200, Werner Sembach wrote:
> >>>> Couples the decission between RGB and YCbCr420 mode and the check if the port
> >>>> clock can archive the required frequency. Other checks and configuration steps
> >>>> that where previously done in between can also be done before or after.
> >>>>
> >>>> This allows for are cleaner implementation of retrying different color
> >>>> encodings.
> >>>>
> >>>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> >>>> ---
> >>>>
> >>>> >From 57e42ec6e34ac32da29eb7bc3c691cbeb2534396 Mon Sep 17 00:00:00 2001
> >>>> From: Werner Sembach <wse@tuxedocomputers.com>
> >>>> Date: Mon, 3 May 2021 15:30:40 +0200
> >>>> Subject: [PATCH 3/4] Restructure output format computation for better
> >>>>  expandability
> >>>>
> >>>> ---
> >>>>  drivers/gpu/drm/i915/display/intel_hdmi.c | 57 +++++++++++------------
> >>>>  1 file changed, 26 insertions(+), 31 deletions(-)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
> >>>> index ce165ef28e88..e2553ac6fd13 100644
> >>>> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
> >>>> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
> >>>> @@ -1999,29 +1999,6 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
> >>>>  					      INTEL_OUTPUT_FORMAT_YCBCR420);
> >>>>  }
> >>>>  
> >>>> -static int
> >>>> -intel_hdmi_ycbcr420_config(struct intel_crtc_state *crtc_state,
> >>>> -			   const struct drm_connector_state *conn_state)
> >>>> -{
> >>>> -	struct drm_connector *connector = conn_state->connector;
> >>>> -	struct drm_i915_private *i915 = to_i915(connector->dev);
> >>>> -	const struct drm_display_mode *adjusted_mode =
> >>>> -		&crtc_state->hw.adjusted_mode;
> >>>> -
> >>>> -	if (!drm_mode_is_420_only(&connector->display_info, adjusted_mode))
> >>>> -		return 0;
> >>>> -
> >>>> -	if (!connector->ycbcr_420_allowed) {
> >>>> -		drm_err(&i915->drm,
> >>>> -			"Platform doesn't support YCBCR420 output\n");
> >>>> -		return -EINVAL;
> >>>> -	}
> >>>> -
> >>>> -	crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
> >>>> -
> >>>> -	return intel_pch_panel_fitting(crtc_state, conn_state);
> >>>> -}
> >>>> -
> >>>>  static int intel_hdmi_compute_bpc(struct intel_encoder *encoder,
> >>>>  				  struct intel_crtc_state *crtc_state,
> >>>>  				  int clock)
> >>>> @@ -2128,6 +2105,24 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
> >>>>  		return intel_conn_state->force_audio == HDMI_AUDIO_ON;
> >>>>  }
> >>>>  
> >>>> +int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
> >>>> +				     struct intel_crtc_state *crtc_state,
> >>>> +				     const struct drm_connector_state *conn_state)
> >>>> +{
> >>>> +	const struct drm_connector *connector = conn_state->connector;
> >>>> +	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
> >>>> +	int ret;
> >>>> +
> >>>> +	if (connector->ycbcr_420_allowed && drm_mode_is_420_only(&connector->display_info, adjusted_mode))
> >>>> +		crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
> >>>> +	else
> >>>> +		crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
> >>> Slight change in behaviour here since we used to reject 420_only modes
> >>> if ycbcr_420_allowed wasn't set. But I think this should be OK, and in
> >>> fact I believe the DP counterpart code always used an RGB fallback
> >>> rather than failing. So this lines up better with that.
> >> That was actually an oversight on my side and not intended. Does a RGB fallback make sense?
> >>
> >> Now that I think of it get to 2 scenarios:
> >>
> >> - The screen is really 420_only, which causes a silent fail and a black screen I guess? Where before at least a log message was written.
> >>
> >> - The screen falsely reports as 420_only and using RGB regardless makes it magically work
> >>
> >> I think at least warning should be printed to the logs. Something along the lines of: "Display reports as 420 only, but port does not support 420, try forcing RGB, but this is likely to fail."
> > I would just put it into the "user has decided to override the mode and
> > gets to keep both pieces if it breaks". Typical users would not hit that
> > since they will only use modes reported by the connector as supported.
> >
> > So I think the RGB fallback is totally in line with existing behaviour
> > of the driver. We have other cases where we just ignore the reported
> > limits of the display if the user overrides the mode manually.
> >
> Did I get you right that "connector->ycbcr_420_allowed" is a user setting and not automatically filled configuration depending on hardware capabilities?

No, ycbcr_420_allowed is an automatic thing. But the user can
manually force the display mode to be whatever they want.

So we could have a case where the user forces a mode which the display
claims needs 4:2:0 but the GPU does not support 4:2:0 output. In that
case we could either reject it or just try to output it as RGB anyway.
The current policy for most things like this is "user knows best".
And sometimes they really do know best since some displays can in
fact do things they claim to not support.
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index ce165ef28e88..e2553ac6fd13 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -1999,29 +1999,6 @@  static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
 					      INTEL_OUTPUT_FORMAT_YCBCR420);
 }
 
-static int
-intel_hdmi_ycbcr420_config(struct intel_crtc_state *crtc_state,
-			   const struct drm_connector_state *conn_state)
-{
-	struct drm_connector *connector = conn_state->connector;
-	struct drm_i915_private *i915 = to_i915(connector->dev);
-	const struct drm_display_mode *adjusted_mode =
-		&crtc_state->hw.adjusted_mode;
-
-	if (!drm_mode_is_420_only(&connector->display_info, adjusted_mode))
-		return 0;
-
-	if (!connector->ycbcr_420_allowed) {
-		drm_err(&i915->drm,
-			"Platform doesn't support YCBCR420 output\n");
-		return -EINVAL;
-	}
-
-	crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
-
-	return intel_pch_panel_fitting(crtc_state, conn_state);
-}
-
 static int intel_hdmi_compute_bpc(struct intel_encoder *encoder,
 				  struct intel_crtc_state *crtc_state,
 				  int clock)
@@ -2128,6 +2105,24 @@  static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
 		return intel_conn_state->force_audio == HDMI_AUDIO_ON;
 }
 
+int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
+				     struct intel_crtc_state *crtc_state,
+				     const struct drm_connector_state *conn_state)
+{
+	const struct drm_connector *connector = conn_state->connector;
+	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+	int ret;
+
+	if (connector->ycbcr_420_allowed && drm_mode_is_420_only(&connector->display_info, adjusted_mode))
+		crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+	else
+		crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
+
+	ret = intel_hdmi_compute_clock(encoder, crtc_state);
+
+	return ret;
+}
+
 int intel_hdmi_compute_config(struct intel_encoder *encoder,
 			      struct intel_crtc_state *pipe_config,
 			      struct drm_connector_state *conn_state)
@@ -2152,23 +2147,23 @@  int intel_hdmi_compute_config(struct intel_encoder *encoder,
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
 		pipe_config->pixel_multiplier = 2;
 
-	ret = intel_hdmi_ycbcr420_config(pipe_config, conn_state);
-	if (ret)
-		return ret;
-
-	pipe_config->limited_color_range =
-		intel_hdmi_limited_color_range(pipe_config, conn_state);
-
 	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
 		pipe_config->has_pch_encoder = true;
 
 	pipe_config->has_audio =
 		intel_hdmi_has_audio(encoder, pipe_config, conn_state);
 
-	ret = intel_hdmi_compute_clock(encoder, pipe_config);
+	ret = intel_hdmi_compute_output_format(encoder, pipe_config, conn_state);
 	if (ret)
 		return ret;
 
+	ret = intel_pch_panel_fitting(pipe_config, conn_state);
+	if (ret)
+		return ret;
+
+	pipe_config->limited_color_range =
+		intel_hdmi_limited_color_range(pipe_config, conn_state);
+
 	if (conn_state->picture_aspect_ratio)
 		adjusted_mode->picture_aspect_ratio =
 			conn_state->picture_aspect_ratio;