diff mbox series

[v3,15/20] drm/i915: Finish the LUT state checker

Message ID 20221114153732.11773-16-ville.syrjala@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915: Finish (de)gamma readout | expand

Commit Message

Ville Syrjälä Nov. 14, 2022, 3:37 p.m. UTC
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We have full readout now for all platforms (sans the icl+
multi-segment readout hw fail), so hook up the LUT state
checker for everyone.

We add a new vfunc for this since different platforms need
to handle the details a bit differently.

The implementation is rather repetitive in places. Probably
we want to think of a more declarative approach for the
LUT precision/etc. stuff in the future...

Note that we're currently missing readout for c8_planes, so
we'll have to skip the state check in that case.

v2: Fix readout for C8 use cases
v3: Skip C8 entirely due to lack of c8_planes readout
    Add ilk_has_pre_csc_lut() helper and use other such helpers

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_color.c   | 275 ++++++++++++++-----
 drivers/gpu/drm/i915/display/intel_color.h   |   8 +-
 drivers/gpu/drm/i915/display/intel_display.c |  29 +-
 3 files changed, 225 insertions(+), 87 deletions(-)

Comments

Shankar, Uma Nov. 18, 2022, 6:11 p.m. UTC | #1
> -----Original Message-----
> From: Intel-gfx <intel-gfx-bounces@lists.freedesktop.org> On Behalf Of Ville Syrjala
> Sent: Monday, November 14, 2022 9:07 PM
> To: intel-gfx@lists.freedesktop.org
> Subject: [Intel-gfx] [PATCH v3 15/20] drm/i915: Finish the LUT state checker
> 
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> We have full readout now for all platforms (sans the icl+ multi-segment readout hw
> fail), so hook up the LUT state checker for everyone.
> 
> We add a new vfunc for this since different platforms need to handle the details a bit
> differently.
> 
> The implementation is rather repetitive in places. Probably we want to think of a
> more declarative approach for the LUT precision/etc. stuff in the future...

Yeah some places do look as if can be optimized as you already mentioned.
But no major concerns on this one.

Looks Good to me.
Reviewed-by: Uma Shankar <uma.shankar@intel.com>

> Note that we're currently missing readout for c8_planes, so we'll have to skip the
> state check in that case.
> 
> v2: Fix readout for C8 use cases
> v3: Skip C8 entirely due to lack of c8_planes readout
>     Add ilk_has_pre_csc_lut() helper and use other such helpers
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_color.c   | 275 ++++++++++++++-----
>  drivers/gpu/drm/i915/display/intel_color.h   |   8 +-
>  drivers/gpu/drm/i915/display/intel_display.c |  29 +-
>  3 files changed, 225 insertions(+), 87 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_color.c
> b/drivers/gpu/drm/i915/display/intel_color.c
> index f0bb4227338c..e2bcfbffb298 100644
> --- a/drivers/gpu/drm/i915/display/intel_color.c
> +++ b/drivers/gpu/drm/i915/display/intel_color.c
> @@ -53,7 +53,18 @@ struct intel_color_funcs {
>  	 * involved with the same commit.
>  	 */
>  	void (*load_luts)(const struct intel_crtc_state *crtc_state);
> +	/*
> +	 * Read out the LUTs from the hardware into the software state.
> +	 * Used by eg. the hardware state checker.
> +	 */
>  	void (*read_luts)(struct intel_crtc_state *crtc_state);
> +	/*
> +	 * Compare the LUTs
> +	 */
> +	bool (*lut_equal)(const struct intel_crtc_state *crtc_state,
> +			  const struct drm_property_blob *blob1,
> +			  const struct drm_property_blob *blob2,
> +			  bool is_pre_csc_lut);
>  };
> 
>  #define CTM_COEFF_SIGN	(1ULL << 63)
> @@ -1234,6 +1245,24 @@ void intel_color_get_config(struct intel_crtc_state
> *crtc_state)
>  	i915->display.funcs.color->read_luts(crtc_state);
>  }
> 
> +bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
> +			   const struct drm_property_blob *blob1,
> +			   const struct drm_property_blob *blob2,
> +			   bool is_pre_csc_lut)
> +{
> +	struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
> +
> +	/*
> +	 * FIXME c8_planes readout missing thus
> +	 * .read_luts() doesn't read out post_csc_lut.
> +	 */
> +	if (!is_pre_csc_lut && crtc_state->c8_planes)
> +		return true;
> +
> +	return i915->display.funcs.color->lut_equal(crtc_state, blob1, blob2,
> +						    is_pre_csc_lut);
> +}
> +
>  static bool need_plane_update(struct intel_plane *plane,
>  			      const struct intel_crtc_state *crtc_state)  { @@ -1814,6
> +1843,24 @@ static int i9xx_post_csc_lut_precision(const struct intel_crtc_state
> *crtc_state
>  	}
>  }
> 
> +static int i9xx_pre_csc_lut_precision(const struct intel_crtc_state
> +*crtc_state) {
> +	return 0;
> +}
> +
> +static int ilk_gamma_mode_precision(u32 gamma_mode) {
> +	switch (gamma_mode) {
> +	case GAMMA_MODE_MODE_8BIT:
> +		return 8;
> +	case GAMMA_MODE_MODE_10BIT:
> +		return 10;
> +	default:
> +		MISSING_CASE(gamma_mode);
> +		return 0;
> +	}
> +}
> +
>  static bool ilk_has_post_csc_lut(const struct intel_crtc_state *crtc_state)  {
>  	if (crtc_state->c8_planes)
> @@ -1823,28 +1870,60 @@ static bool ilk_has_post_csc_lut(const struct
> intel_crtc_state *crtc_state)
>  		(crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) != 0;  }
> 
> +static bool ilk_has_pre_csc_lut(const struct intel_crtc_state
> +*crtc_state) {
> +	return crtc_state->gamma_enable &&
> +		(crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) == 0; }
> +
>  static int ilk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)  {
>  	if (!ilk_has_post_csc_lut(crtc_state))
>  		return 0;
> 
> -	switch (crtc_state->gamma_mode) {
> -	case GAMMA_MODE_MODE_8BIT:
> -		return 8;
> -	case GAMMA_MODE_MODE_10BIT:
> -		return 10;
> -	default:
> -		MISSING_CASE(crtc_state->gamma_mode);
> +	return ilk_gamma_mode_precision(crtc_state->gamma_mode);
> +}
> +
> +static int ilk_pre_csc_lut_precision(const struct intel_crtc_state
> +*crtc_state) {
> +	if (!ilk_has_pre_csc_lut(crtc_state))
>  		return 0;
> -	}
> +
> +	return ilk_gamma_mode_precision(crtc_state->gamma_mode);
> +}
> +
> +static int ivb_post_csc_lut_precision(const struct intel_crtc_state
> +*crtc_state) {
> +	if (crtc_state->gamma_enable &&
> +	    crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
> +		return 10;
> +
> +	return ilk_post_csc_lut_precision(crtc_state);
> +}
> +
> +static int ivb_pre_csc_lut_precision(const struct intel_crtc_state
> +*crtc_state) {
> +	if (crtc_state->gamma_enable &&
> +	    crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
> +		return 10;
> +
> +	return ilk_pre_csc_lut_precision(crtc_state);
>  }
> 
>  static int chv_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)  {
>  	if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA)
>  		return 10;
> -	else
> -		return i9xx_post_csc_lut_precision(crtc_state);
> +
> +	return i9xx_post_csc_lut_precision(crtc_state);
> +}
> +
> +static int chv_pre_csc_lut_precision(const struct intel_crtc_state
> +*crtc_state) {
> +	if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA)
> +		return 14;
> +
> +	return 0;
>  }
> 
>  static int glk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state) @@ -
> 1852,15 +1931,15 @@ static int glk_post_csc_lut_precision(const struct
> intel_crtc_state *crtc_state)
>  	if (!crtc_state->gamma_enable && !crtc_state->c8_planes)
>  		return 0;
> 
> -	switch (crtc_state->gamma_mode) {
> -	case GAMMA_MODE_MODE_8BIT:
> -		return 8;
> -	case GAMMA_MODE_MODE_10BIT:
> -		return 10;
> -	default:
> -		MISSING_CASE(crtc_state->gamma_mode);
> +	return ilk_gamma_mode_precision(crtc_state->gamma_mode);
> +}
> +
> +static int glk_pre_csc_lut_precision(const struct intel_crtc_state
> +*crtc_state) {
> +	if (!crtc_state->csc_enable)
>  		return 0;
> -	}
> +
> +	return 16;
>  }
> 
>  static bool icl_has_post_csc_lut(const struct intel_crtc_state *crtc_state) @@ -
> 1894,26 +1973,12 @@ static int icl_post_csc_lut_precision(const struct
> intel_crtc_state *crtc_state)
>  	}
>  }
> 
> -int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state)
> +static int icl_pre_csc_lut_precision(const struct intel_crtc_state
> +*crtc_state)
>  {
> -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
> +	if (!icl_has_pre_csc_lut(crtc_state))
> +		return 0;
> 
> -	if (HAS_GMCH(i915)) {
> -		if (IS_CHERRYVIEW(i915))
> -			return chv_post_csc_lut_precision(crtc_state);
> -		else
> -			return i9xx_post_csc_lut_precision(crtc_state);
> -	} else {
> -		if (DISPLAY_VER(i915) >= 11)
> -			return icl_post_csc_lut_precision(crtc_state);
> -		else if (DISPLAY_VER(i915) == 10)
> -			return glk_post_csc_lut_precision(crtc_state);
> -		else if (IS_IRONLAKE(i915))
> -			return ilk_post_csc_lut_precision(crtc_state);
> -	}
> -
> -	return 0;
> +	return 16;
>  }
> 
>  static bool err_check(struct drm_color_lut *lut1, @@ -1924,9 +1989,9 @@ static
> bool err_check(struct drm_color_lut *lut1,
>  		((abs((long)lut2->green - lut1->green)) <= err);  }
> 
> -static bool intel_color_lut_entries_equal(struct drm_color_lut *lut1,
> -					  struct drm_color_lut *lut2,
> -					  int lut_size, u32 err)
> +static bool intel_lut_entries_equal(struct drm_color_lut *lut1,
> +				    struct drm_color_lut *lut2,
> +				    int lut_size, u32 err)
>  {
>  	int i;
> 
> @@ -1938,9 +2003,9 @@ static bool intel_color_lut_entries_equal(struct
> drm_color_lut *lut1,
>  	return true;
>  }
> 
> -bool intel_color_lut_equal(struct drm_property_blob *blob1,
> -			   struct drm_property_blob *blob2,
> -			   u32 gamma_mode, u32 bit_precision)
> +static bool intel_lut_equal(const struct drm_property_blob *blob1,
> +			    const struct drm_property_blob *blob2,
> +			    int check_size, int precision)
>  {
>  	struct drm_color_lut *lut1, *lut2;
>  	int lut_size1, lut_size2;
> @@ -1949,40 +2014,112 @@ bool intel_color_lut_equal(struct drm_property_blob
> *blob1,
>  	if (!blob1 != !blob2)
>  		return false;
> 
> +	if (!blob1 != !precision)
> +		return false;
> +
>  	if (!blob1)
>  		return true;
> 
>  	lut_size1 = drm_color_lut_size(blob1);
>  	lut_size2 = drm_color_lut_size(blob2);
> 
> -	/* check sw and hw lut size */
>  	if (lut_size1 != lut_size2)
>  		return false;
> 
>  	lut1 = blob1->data;
>  	lut2 = blob2->data;
> 
> -	err = 0xffff >> bit_precision;
> -
> -	/* check sw and hw lut entry to be equal */
> -	switch (gamma_mode & GAMMA_MODE_MODE_MASK) {
> -	case GAMMA_MODE_MODE_8BIT:
> -	case GAMMA_MODE_MODE_10BIT:
> -		if (!intel_color_lut_entries_equal(lut1, lut2,
> -						   lut_size2, err))
> -			return false;
> -		break;
> -	case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED:
> -		if (!intel_color_lut_entries_equal(lut1, lut2,
> -						   9, err))
> -			return false;
> -		break;
> -	default:
> -		MISSING_CASE(gamma_mode);
> -		return false;
> -	}
> -
> -	return true;
> +	err = 0xffff >> precision;
> +
> +	if (!check_size)
> +		check_size = lut_size1;
> +
> +	return intel_lut_entries_equal(lut1, lut2, check_size, err); }
> +
> +static bool i9xx_lut_equal(const struct intel_crtc_state *crtc_state,
> +			   const struct drm_property_blob *blob1,
> +			   const struct drm_property_blob *blob2,
> +			   bool is_pre_csc_lut)
> +{
> +	if (is_pre_csc_lut)
> +		return intel_lut_equal(blob1, blob2, 0,
> +				       i9xx_pre_csc_lut_precision(crtc_state));
> +	else
> +		return intel_lut_equal(blob1, blob2, 0,
> +				       i9xx_post_csc_lut_precision(crtc_state));
> +}
> +
> +static bool chv_lut_equal(const struct intel_crtc_state *crtc_state,
> +			  const struct drm_property_blob *blob1,
> +			  const struct drm_property_blob *blob2,
> +			  bool is_pre_csc_lut)
> +{
> +	if (is_pre_csc_lut)
> +		return intel_lut_equal(blob1, blob2, 0,
> +				       chv_pre_csc_lut_precision(crtc_state));
> +	else
> +		return intel_lut_equal(blob1, blob2, 0,
> +				       chv_post_csc_lut_precision(crtc_state));
> +}
> +
> +static bool ilk_lut_equal(const struct intel_crtc_state *crtc_state,
> +			  const struct drm_property_blob *blob1,
> +			  const struct drm_property_blob *blob2,
> +			  bool is_pre_csc_lut)
> +{
> +	if (is_pre_csc_lut)
> +		return intel_lut_equal(blob1, blob2, 0,
> +				       ilk_pre_csc_lut_precision(crtc_state));
> +	else
> +		return intel_lut_equal(blob1, blob2, 0,
> +				       ilk_post_csc_lut_precision(crtc_state));
> +}
> +
> +static bool ivb_lut_equal(const struct intel_crtc_state *crtc_state,
> +			  const struct drm_property_blob *blob1,
> +			  const struct drm_property_blob *blob2,
> +			  bool is_pre_csc_lut)
> +{
> +	if (is_pre_csc_lut)
> +		return intel_lut_equal(blob1, blob2, 0,
> +				       ivb_pre_csc_lut_precision(crtc_state));
> +	else
> +		return intel_lut_equal(blob1, blob2, 0,
> +				       ivb_post_csc_lut_precision(crtc_state));
> +}
> +
> +static bool glk_lut_equal(const struct intel_crtc_state *crtc_state,
> +			  const struct drm_property_blob *blob1,
> +			  const struct drm_property_blob *blob2,
> +			  bool is_pre_csc_lut)
> +{
> +	if (is_pre_csc_lut)
> +		return intel_lut_equal(blob1, blob2, 0,
> +				       glk_pre_csc_lut_precision(crtc_state));
> +	else
> +		return intel_lut_equal(blob1, blob2, 0,
> +				       glk_post_csc_lut_precision(crtc_state));
> +}
> +
> +static bool icl_lut_equal(const struct intel_crtc_state *crtc_state,
> +			  const struct drm_property_blob *blob1,
> +			  const struct drm_property_blob *blob2,
> +			  bool is_pre_csc_lut)
> +{
> +	int check_size = 0;
> +
> +	if (is_pre_csc_lut)
> +		return intel_lut_equal(blob1, blob2, 0,
> +				       icl_pre_csc_lut_precision(crtc_state));
> +
> +	/* hw readout broken except for the super fine segment :( */
> +	if ((crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) ==
> +	    GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED)
> +		check_size = 9;
> +
> +	return intel_lut_equal(blob1, blob2, check_size,
> +			       icl_post_csc_lut_precision(crtc_state));
>  }
> 
>  static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc) @@ -
> 2462,6 +2599,7 @@ static const struct intel_color_funcs chv_color_funcs = {
>  	.color_commit_arm = i9xx_color_commit_arm,
>  	.load_luts = chv_load_luts,
>  	.read_luts = chv_read_luts,
> +	.lut_equal = chv_lut_equal,
>  };
> 
>  static const struct intel_color_funcs i965_color_funcs = { @@ -2469,6 +2607,7 @@
> static const struct intel_color_funcs i965_color_funcs = {
>  	.color_commit_arm = i9xx_color_commit_arm,
>  	.load_luts = i965_load_luts,
>  	.read_luts = i965_read_luts,
> +	.lut_equal = i9xx_lut_equal,
>  };
> 
>  static const struct intel_color_funcs i9xx_color_funcs = { @@ -2476,6 +2615,7 @@
> static const struct intel_color_funcs i9xx_color_funcs = {
>  	.color_commit_arm = i9xx_color_commit_arm,
>  	.load_luts = i9xx_load_luts,
>  	.read_luts = i9xx_read_luts,
> +	.lut_equal = i9xx_lut_equal,
>  };
> 
>  static const struct intel_color_funcs icl_color_funcs = { @@ -2484,6 +2624,7 @@
> static const struct intel_color_funcs icl_color_funcs = {
>  	.color_commit_arm = skl_color_commit_arm,
>  	.load_luts = icl_load_luts,
>  	.read_luts = icl_read_luts,
> +	.lut_equal = icl_lut_equal,
>  };
> 
>  static const struct intel_color_funcs glk_color_funcs = { @@ -2492,6 +2633,7 @@
> static const struct intel_color_funcs glk_color_funcs = {
>  	.color_commit_arm = skl_color_commit_arm,
>  	.load_luts = glk_load_luts,
>  	.read_luts = glk_read_luts,
> +	.lut_equal = glk_lut_equal,
>  };
> 
>  static const struct intel_color_funcs skl_color_funcs = { @@ -2500,6 +2642,7 @@
> static const struct intel_color_funcs skl_color_funcs = {
>  	.color_commit_arm = skl_color_commit_arm,
>  	.load_luts = bdw_load_luts,
>  	.read_luts = bdw_read_luts,
> +	.lut_equal = ivb_lut_equal,
>  };
> 
>  static const struct intel_color_funcs bdw_color_funcs = { @@ -2508,6 +2651,7 @@
> static const struct intel_color_funcs bdw_color_funcs = {
>  	.color_commit_arm = hsw_color_commit_arm,
>  	.load_luts = bdw_load_luts,
>  	.read_luts = bdw_read_luts,
> +	.lut_equal = ivb_lut_equal,
>  };
> 
>  static const struct intel_color_funcs hsw_color_funcs = { @@ -2516,6 +2660,7 @@
> static const struct intel_color_funcs hsw_color_funcs = {
>  	.color_commit_arm = hsw_color_commit_arm,
>  	.load_luts = ivb_load_luts,
>  	.read_luts = ivb_read_luts,
> +	.lut_equal = ivb_lut_equal,
>  };
> 
>  static const struct intel_color_funcs ivb_color_funcs = { @@ -2524,6 +2669,7 @@
> static const struct intel_color_funcs ivb_color_funcs = {
>  	.color_commit_arm = ilk_color_commit_arm,
>  	.load_luts = ivb_load_luts,
>  	.read_luts = ivb_read_luts,
> +	.lut_equal = ivb_lut_equal,
>  };
> 
>  static const struct intel_color_funcs ilk_color_funcs = { @@ -2532,6 +2678,7 @@
> static const struct intel_color_funcs ilk_color_funcs = {
>  	.color_commit_arm = ilk_color_commit_arm,
>  	.load_luts = ilk_load_luts,
>  	.read_luts = ilk_read_luts,
> +	.lut_equal = ilk_lut_equal,
>  };
> 
>  void intel_color_crtc_init(struct intel_crtc *crtc) diff --git
> a/drivers/gpu/drm/i915/display/intel_color.h
> b/drivers/gpu/drm/i915/display/intel_color.h
> index 2a5ada67774d..1c6b1755f6d2 100644
> --- a/drivers/gpu/drm/i915/display/intel_color.h
> +++ b/drivers/gpu/drm/i915/display/intel_color.h
> @@ -21,10 +21,10 @@ void intel_color_commit_noarm(const struct
> intel_crtc_state *crtc_state);  void intel_color_commit_arm(const struct
> intel_crtc_state *crtc_state);  void intel_color_load_luts(const struct
> intel_crtc_state *crtc_state);  void intel_color_get_config(struct intel_crtc_state
> *crtc_state); -int intel_color_get_gamma_bit_precision(const struct intel_crtc_state
> *crtc_state); -bool intel_color_lut_equal(struct drm_property_blob *blob1,
> -			   struct drm_property_blob *blob2,
> -			   u32 gamma_mode, u32 bit_precision);
> +bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
> +			   const struct drm_property_blob *blob1,
> +			   const struct drm_property_blob *blob2,
> +			   bool is_pre_csc_lut);
>  void intel_color_assert_luts(const struct intel_crtc_state *crtc_state);
> 
>  #endif /* __INTEL_COLOR_H__ */
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> b/drivers/gpu/drm/i915/display/intel_display.c
> index c8422fef992a..7bfcc8ca0bac 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -5526,7 +5526,6 @@ intel_pipe_config_compare(const struct intel_crtc_state
> *current_config,
>  	struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc-
> >dev);
>  	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
>  	bool ret = true;
> -	u32 bp_gamma = 0;
>  	bool fixup_inherited = fastset &&
>  		current_config->inherited && !pipe_config->inherited;
> 
> @@ -5677,21 +5676,14 @@ intel_pipe_config_compare(const struct
> intel_crtc_state *current_config,
>  	} \
>  } while (0)
> 
> -#define PIPE_CONF_CHECK_COLOR_LUT(name1, name2, bit_precision) do { \
> -	if (current_config->name1 != pipe_config->name1) { \
> -		pipe_config_mismatch(fastset, crtc, __stringify(name1), \
> -				"(expected %i, found %i, won't compare lut
> values)", \
> -				current_config->name1, \
> -				pipe_config->name1); \
> -		ret = false;\
> -	} else { \
> -		if (!intel_color_lut_equal(current_config->name2, \
> -					pipe_config->name2, pipe_config->name1,
> \
> -					bit_precision)) { \
> -			pipe_config_mismatch(fastset, crtc, __stringify(name2), \
> -					"hw_state doesn't match sw_state"); \
> -			ret = false; \
> -		} \
> +#define PIPE_CONF_CHECK_COLOR_LUT(lut, is_pre_csc_lut) do { \
> +	if (current_config->gamma_mode == pipe_config->gamma_mode && \
> +	    !intel_color_lut_equal(current_config, \
> +				   current_config->lut, pipe_config->lut, \
> +				   is_pre_csc_lut)) {	\
> +		pipe_config_mismatch(fastset, crtc, __stringify(lut), \
> +				     "hw_state doesn't match sw_state"); \
> +		ret = false; \
>  	} \
>  } while (0)
> 
> @@ -5788,9 +5780,8 @@ intel_pipe_config_compare(const struct intel_crtc_state
> *current_config,
>  		PIPE_CONF_CHECK_I(linetime);
>  		PIPE_CONF_CHECK_I(ips_linetime);
> 
> -		bp_gamma = intel_color_get_gamma_bit_precision(pipe_config);
> -		if (bp_gamma)
> -			PIPE_CONF_CHECK_COLOR_LUT(gamma_mode,
> post_csc_lut, bp_gamma);
> +		PIPE_CONF_CHECK_COLOR_LUT(pre_csc_lut, true);
> +		PIPE_CONF_CHECK_COLOR_LUT(post_csc_lut, false);
> 
>  		if (current_config->active_planes) {
>  			PIPE_CONF_CHECK_BOOL(has_psr);
> --
> 2.37.4
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index f0bb4227338c..e2bcfbffb298 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -53,7 +53,18 @@  struct intel_color_funcs {
 	 * involved with the same commit.
 	 */
 	void (*load_luts)(const struct intel_crtc_state *crtc_state);
+	/*
+	 * Read out the LUTs from the hardware into the software state.
+	 * Used by eg. the hardware state checker.
+	 */
 	void (*read_luts)(struct intel_crtc_state *crtc_state);
+	/*
+	 * Compare the LUTs
+	 */
+	bool (*lut_equal)(const struct intel_crtc_state *crtc_state,
+			  const struct drm_property_blob *blob1,
+			  const struct drm_property_blob *blob2,
+			  bool is_pre_csc_lut);
 };
 
 #define CTM_COEFF_SIGN	(1ULL << 63)
@@ -1234,6 +1245,24 @@  void intel_color_get_config(struct intel_crtc_state *crtc_state)
 	i915->display.funcs.color->read_luts(crtc_state);
 }
 
+bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
+			   const struct drm_property_blob *blob1,
+			   const struct drm_property_blob *blob2,
+			   bool is_pre_csc_lut)
+{
+	struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
+	/*
+	 * FIXME c8_planes readout missing thus
+	 * .read_luts() doesn't read out post_csc_lut.
+	 */
+	if (!is_pre_csc_lut && crtc_state->c8_planes)
+		return true;
+
+	return i915->display.funcs.color->lut_equal(crtc_state, blob1, blob2,
+						    is_pre_csc_lut);
+}
+
 static bool need_plane_update(struct intel_plane *plane,
 			      const struct intel_crtc_state *crtc_state)
 {
@@ -1814,6 +1843,24 @@  static int i9xx_post_csc_lut_precision(const struct intel_crtc_state *crtc_state
 	}
 }
 
+static int i9xx_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
+{
+	return 0;
+}
+
+static int ilk_gamma_mode_precision(u32 gamma_mode)
+{
+	switch (gamma_mode) {
+	case GAMMA_MODE_MODE_8BIT:
+		return 8;
+	case GAMMA_MODE_MODE_10BIT:
+		return 10;
+	default:
+		MISSING_CASE(gamma_mode);
+		return 0;
+	}
+}
+
 static bool ilk_has_post_csc_lut(const struct intel_crtc_state *crtc_state)
 {
 	if (crtc_state->c8_planes)
@@ -1823,28 +1870,60 @@  static bool ilk_has_post_csc_lut(const struct intel_crtc_state *crtc_state)
 		(crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) != 0;
 }
 
+static bool ilk_has_pre_csc_lut(const struct intel_crtc_state *crtc_state)
+{
+	return crtc_state->gamma_enable &&
+		(crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) == 0;
+}
+
 static int ilk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
 {
 	if (!ilk_has_post_csc_lut(crtc_state))
 		return 0;
 
-	switch (crtc_state->gamma_mode) {
-	case GAMMA_MODE_MODE_8BIT:
-		return 8;
-	case GAMMA_MODE_MODE_10BIT:
-		return 10;
-	default:
-		MISSING_CASE(crtc_state->gamma_mode);
+	return ilk_gamma_mode_precision(crtc_state->gamma_mode);
+}
+
+static int ilk_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
+{
+	if (!ilk_has_pre_csc_lut(crtc_state))
 		return 0;
-	}
+
+	return ilk_gamma_mode_precision(crtc_state->gamma_mode);
+}
+
+static int ivb_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
+{
+	if (crtc_state->gamma_enable &&
+	    crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
+		return 10;
+
+	return ilk_post_csc_lut_precision(crtc_state);
+}
+
+static int ivb_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
+{
+	if (crtc_state->gamma_enable &&
+	    crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
+		return 10;
+
+	return ilk_pre_csc_lut_precision(crtc_state);
 }
 
 static int chv_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
 {
 	if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA)
 		return 10;
-	else
-		return i9xx_post_csc_lut_precision(crtc_state);
+
+	return i9xx_post_csc_lut_precision(crtc_state);
+}
+
+static int chv_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
+{
+	if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA)
+		return 14;
+
+	return 0;
 }
 
 static int glk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
@@ -1852,15 +1931,15 @@  static int glk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
 	if (!crtc_state->gamma_enable && !crtc_state->c8_planes)
 		return 0;
 
-	switch (crtc_state->gamma_mode) {
-	case GAMMA_MODE_MODE_8BIT:
-		return 8;
-	case GAMMA_MODE_MODE_10BIT:
-		return 10;
-	default:
-		MISSING_CASE(crtc_state->gamma_mode);
+	return ilk_gamma_mode_precision(crtc_state->gamma_mode);
+}
+
+static int glk_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
+{
+	if (!crtc_state->csc_enable)
 		return 0;
-	}
+
+	return 16;
 }
 
 static bool icl_has_post_csc_lut(const struct intel_crtc_state *crtc_state)
@@ -1894,26 +1973,12 @@  static int icl_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
 	}
 }
 
-int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state)
+static int icl_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
 {
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+	if (!icl_has_pre_csc_lut(crtc_state))
+		return 0;
 
-	if (HAS_GMCH(i915)) {
-		if (IS_CHERRYVIEW(i915))
-			return chv_post_csc_lut_precision(crtc_state);
-		else
-			return i9xx_post_csc_lut_precision(crtc_state);
-	} else {
-		if (DISPLAY_VER(i915) >= 11)
-			return icl_post_csc_lut_precision(crtc_state);
-		else if (DISPLAY_VER(i915) == 10)
-			return glk_post_csc_lut_precision(crtc_state);
-		else if (IS_IRONLAKE(i915))
-			return ilk_post_csc_lut_precision(crtc_state);
-	}
-
-	return 0;
+	return 16;
 }
 
 static bool err_check(struct drm_color_lut *lut1,
@@ -1924,9 +1989,9 @@  static bool err_check(struct drm_color_lut *lut1,
 		((abs((long)lut2->green - lut1->green)) <= err);
 }
 
-static bool intel_color_lut_entries_equal(struct drm_color_lut *lut1,
-					  struct drm_color_lut *lut2,
-					  int lut_size, u32 err)
+static bool intel_lut_entries_equal(struct drm_color_lut *lut1,
+				    struct drm_color_lut *lut2,
+				    int lut_size, u32 err)
 {
 	int i;
 
@@ -1938,9 +2003,9 @@  static bool intel_color_lut_entries_equal(struct drm_color_lut *lut1,
 	return true;
 }
 
-bool intel_color_lut_equal(struct drm_property_blob *blob1,
-			   struct drm_property_blob *blob2,
-			   u32 gamma_mode, u32 bit_precision)
+static bool intel_lut_equal(const struct drm_property_blob *blob1,
+			    const struct drm_property_blob *blob2,
+			    int check_size, int precision)
 {
 	struct drm_color_lut *lut1, *lut2;
 	int lut_size1, lut_size2;
@@ -1949,40 +2014,112 @@  bool intel_color_lut_equal(struct drm_property_blob *blob1,
 	if (!blob1 != !blob2)
 		return false;
 
+	if (!blob1 != !precision)
+		return false;
+
 	if (!blob1)
 		return true;
 
 	lut_size1 = drm_color_lut_size(blob1);
 	lut_size2 = drm_color_lut_size(blob2);
 
-	/* check sw and hw lut size */
 	if (lut_size1 != lut_size2)
 		return false;
 
 	lut1 = blob1->data;
 	lut2 = blob2->data;
 
-	err = 0xffff >> bit_precision;
-
-	/* check sw and hw lut entry to be equal */
-	switch (gamma_mode & GAMMA_MODE_MODE_MASK) {
-	case GAMMA_MODE_MODE_8BIT:
-	case GAMMA_MODE_MODE_10BIT:
-		if (!intel_color_lut_entries_equal(lut1, lut2,
-						   lut_size2, err))
-			return false;
-		break;
-	case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED:
-		if (!intel_color_lut_entries_equal(lut1, lut2,
-						   9, err))
-			return false;
-		break;
-	default:
-		MISSING_CASE(gamma_mode);
-		return false;
-	}
-
-	return true;
+	err = 0xffff >> precision;
+
+	if (!check_size)
+		check_size = lut_size1;
+
+	return intel_lut_entries_equal(lut1, lut2, check_size, err);
+}
+
+static bool i9xx_lut_equal(const struct intel_crtc_state *crtc_state,
+			   const struct drm_property_blob *blob1,
+			   const struct drm_property_blob *blob2,
+			   bool is_pre_csc_lut)
+{
+	if (is_pre_csc_lut)
+		return intel_lut_equal(blob1, blob2, 0,
+				       i9xx_pre_csc_lut_precision(crtc_state));
+	else
+		return intel_lut_equal(blob1, blob2, 0,
+				       i9xx_post_csc_lut_precision(crtc_state));
+}
+
+static bool chv_lut_equal(const struct intel_crtc_state *crtc_state,
+			  const struct drm_property_blob *blob1,
+			  const struct drm_property_blob *blob2,
+			  bool is_pre_csc_lut)
+{
+	if (is_pre_csc_lut)
+		return intel_lut_equal(blob1, blob2, 0,
+				       chv_pre_csc_lut_precision(crtc_state));
+	else
+		return intel_lut_equal(blob1, blob2, 0,
+				       chv_post_csc_lut_precision(crtc_state));
+}
+
+static bool ilk_lut_equal(const struct intel_crtc_state *crtc_state,
+			  const struct drm_property_blob *blob1,
+			  const struct drm_property_blob *blob2,
+			  bool is_pre_csc_lut)
+{
+	if (is_pre_csc_lut)
+		return intel_lut_equal(blob1, blob2, 0,
+				       ilk_pre_csc_lut_precision(crtc_state));
+	else
+		return intel_lut_equal(blob1, blob2, 0,
+				       ilk_post_csc_lut_precision(crtc_state));
+}
+
+static bool ivb_lut_equal(const struct intel_crtc_state *crtc_state,
+			  const struct drm_property_blob *blob1,
+			  const struct drm_property_blob *blob2,
+			  bool is_pre_csc_lut)
+{
+	if (is_pre_csc_lut)
+		return intel_lut_equal(blob1, blob2, 0,
+				       ivb_pre_csc_lut_precision(crtc_state));
+	else
+		return intel_lut_equal(blob1, blob2, 0,
+				       ivb_post_csc_lut_precision(crtc_state));
+}
+
+static bool glk_lut_equal(const struct intel_crtc_state *crtc_state,
+			  const struct drm_property_blob *blob1,
+			  const struct drm_property_blob *blob2,
+			  bool is_pre_csc_lut)
+{
+	if (is_pre_csc_lut)
+		return intel_lut_equal(blob1, blob2, 0,
+				       glk_pre_csc_lut_precision(crtc_state));
+	else
+		return intel_lut_equal(blob1, blob2, 0,
+				       glk_post_csc_lut_precision(crtc_state));
+}
+
+static bool icl_lut_equal(const struct intel_crtc_state *crtc_state,
+			  const struct drm_property_blob *blob1,
+			  const struct drm_property_blob *blob2,
+			  bool is_pre_csc_lut)
+{
+	int check_size = 0;
+
+	if (is_pre_csc_lut)
+		return intel_lut_equal(blob1, blob2, 0,
+				       icl_pre_csc_lut_precision(crtc_state));
+
+	/* hw readout broken except for the super fine segment :( */
+	if ((crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) ==
+	    GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED)
+		check_size = 9;
+
+	return intel_lut_equal(blob1, blob2, check_size,
+			       icl_post_csc_lut_precision(crtc_state));
 }
 
 static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc)
@@ -2462,6 +2599,7 @@  static const struct intel_color_funcs chv_color_funcs = {
 	.color_commit_arm = i9xx_color_commit_arm,
 	.load_luts = chv_load_luts,
 	.read_luts = chv_read_luts,
+	.lut_equal = chv_lut_equal,
 };
 
 static const struct intel_color_funcs i965_color_funcs = {
@@ -2469,6 +2607,7 @@  static const struct intel_color_funcs i965_color_funcs = {
 	.color_commit_arm = i9xx_color_commit_arm,
 	.load_luts = i965_load_luts,
 	.read_luts = i965_read_luts,
+	.lut_equal = i9xx_lut_equal,
 };
 
 static const struct intel_color_funcs i9xx_color_funcs = {
@@ -2476,6 +2615,7 @@  static const struct intel_color_funcs i9xx_color_funcs = {
 	.color_commit_arm = i9xx_color_commit_arm,
 	.load_luts = i9xx_load_luts,
 	.read_luts = i9xx_read_luts,
+	.lut_equal = i9xx_lut_equal,
 };
 
 static const struct intel_color_funcs icl_color_funcs = {
@@ -2484,6 +2624,7 @@  static const struct intel_color_funcs icl_color_funcs = {
 	.color_commit_arm = skl_color_commit_arm,
 	.load_luts = icl_load_luts,
 	.read_luts = icl_read_luts,
+	.lut_equal = icl_lut_equal,
 };
 
 static const struct intel_color_funcs glk_color_funcs = {
@@ -2492,6 +2633,7 @@  static const struct intel_color_funcs glk_color_funcs = {
 	.color_commit_arm = skl_color_commit_arm,
 	.load_luts = glk_load_luts,
 	.read_luts = glk_read_luts,
+	.lut_equal = glk_lut_equal,
 };
 
 static const struct intel_color_funcs skl_color_funcs = {
@@ -2500,6 +2642,7 @@  static const struct intel_color_funcs skl_color_funcs = {
 	.color_commit_arm = skl_color_commit_arm,
 	.load_luts = bdw_load_luts,
 	.read_luts = bdw_read_luts,
+	.lut_equal = ivb_lut_equal,
 };
 
 static const struct intel_color_funcs bdw_color_funcs = {
@@ -2508,6 +2651,7 @@  static const struct intel_color_funcs bdw_color_funcs = {
 	.color_commit_arm = hsw_color_commit_arm,
 	.load_luts = bdw_load_luts,
 	.read_luts = bdw_read_luts,
+	.lut_equal = ivb_lut_equal,
 };
 
 static const struct intel_color_funcs hsw_color_funcs = {
@@ -2516,6 +2660,7 @@  static const struct intel_color_funcs hsw_color_funcs = {
 	.color_commit_arm = hsw_color_commit_arm,
 	.load_luts = ivb_load_luts,
 	.read_luts = ivb_read_luts,
+	.lut_equal = ivb_lut_equal,
 };
 
 static const struct intel_color_funcs ivb_color_funcs = {
@@ -2524,6 +2669,7 @@  static const struct intel_color_funcs ivb_color_funcs = {
 	.color_commit_arm = ilk_color_commit_arm,
 	.load_luts = ivb_load_luts,
 	.read_luts = ivb_read_luts,
+	.lut_equal = ivb_lut_equal,
 };
 
 static const struct intel_color_funcs ilk_color_funcs = {
@@ -2532,6 +2678,7 @@  static const struct intel_color_funcs ilk_color_funcs = {
 	.color_commit_arm = ilk_color_commit_arm,
 	.load_luts = ilk_load_luts,
 	.read_luts = ilk_read_luts,
+	.lut_equal = ilk_lut_equal,
 };
 
 void intel_color_crtc_init(struct intel_crtc *crtc)
diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h
index 2a5ada67774d..1c6b1755f6d2 100644
--- a/drivers/gpu/drm/i915/display/intel_color.h
+++ b/drivers/gpu/drm/i915/display/intel_color.h
@@ -21,10 +21,10 @@  void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state);
 void intel_color_commit_arm(const struct intel_crtc_state *crtc_state);
 void intel_color_load_luts(const struct intel_crtc_state *crtc_state);
 void intel_color_get_config(struct intel_crtc_state *crtc_state);
-int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state);
-bool intel_color_lut_equal(struct drm_property_blob *blob1,
-			   struct drm_property_blob *blob2,
-			   u32 gamma_mode, u32 bit_precision);
+bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
+			   const struct drm_property_blob *blob1,
+			   const struct drm_property_blob *blob2,
+			   bool is_pre_csc_lut);
 void intel_color_assert_luts(const struct intel_crtc_state *crtc_state);
 
 #endif /* __INTEL_COLOR_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index c8422fef992a..7bfcc8ca0bac 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -5526,7 +5526,6 @@  intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 	struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev);
 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
 	bool ret = true;
-	u32 bp_gamma = 0;
 	bool fixup_inherited = fastset &&
 		current_config->inherited && !pipe_config->inherited;
 
@@ -5677,21 +5676,14 @@  intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 	} \
 } while (0)
 
-#define PIPE_CONF_CHECK_COLOR_LUT(name1, name2, bit_precision) do { \
-	if (current_config->name1 != pipe_config->name1) { \
-		pipe_config_mismatch(fastset, crtc, __stringify(name1), \
-				"(expected %i, found %i, won't compare lut values)", \
-				current_config->name1, \
-				pipe_config->name1); \
-		ret = false;\
-	} else { \
-		if (!intel_color_lut_equal(current_config->name2, \
-					pipe_config->name2, pipe_config->name1, \
-					bit_precision)) { \
-			pipe_config_mismatch(fastset, crtc, __stringify(name2), \
-					"hw_state doesn't match sw_state"); \
-			ret = false; \
-		} \
+#define PIPE_CONF_CHECK_COLOR_LUT(lut, is_pre_csc_lut) do { \
+	if (current_config->gamma_mode == pipe_config->gamma_mode && \
+	    !intel_color_lut_equal(current_config, \
+				   current_config->lut, pipe_config->lut, \
+				   is_pre_csc_lut)) {	\
+		pipe_config_mismatch(fastset, crtc, __stringify(lut), \
+				     "hw_state doesn't match sw_state"); \
+		ret = false; \
 	} \
 } while (0)
 
@@ -5788,9 +5780,8 @@  intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 		PIPE_CONF_CHECK_I(linetime);
 		PIPE_CONF_CHECK_I(ips_linetime);
 
-		bp_gamma = intel_color_get_gamma_bit_precision(pipe_config);
-		if (bp_gamma)
-			PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, post_csc_lut, bp_gamma);
+		PIPE_CONF_CHECK_COLOR_LUT(pre_csc_lut, true);
+		PIPE_CONF_CHECK_COLOR_LUT(post_csc_lut, false);
 
 		if (current_config->active_planes) {
 			PIPE_CONF_CHECK_BOOL(has_psr);