[PATCH] State checker for CSC

Bhanuprakash Modem bhanuprakash.modem at intel.com
Thu Mar 18 12:49:27 UTC 2021


Signed-off-by: Bhanuprakash Modem <bhanuprakash.modem at intel.com>
---
 drivers/gpu/drm/i915/display/intel_color.c   | 217 ++++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_color.h   |   3 +
 drivers/gpu/drm/i915/display/intel_display.c |  29 +++
 drivers/gpu/drm/i915/i915_drv.h              |   2 +
 4 files changed, 245 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index ff7dcb7088bf..94ac5fc5b945 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -321,6 +321,54 @@ static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
 		       crtc_state->csc_mode);
 }
 
+static struct drm_property_blob *ilk_read_csc_matrix(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	enum pipe pipe = crtc->pipe;
+	struct drm_property_blob *blob;
+	struct drm_color_ctm *ctm;
+	u32 temp;
+
+	blob = drm_property_create_blob(&dev_priv->drm,
+					sizeof(struct drm_color_ctm),
+					NULL);
+	if (IS_ERR(blob))
+		return NULL;
+
+	ctm = blob->data;
+
+	temp = intel_de_read(dev_priv, PIPE_CSC_COEFF_RY_GY(pipe));
+	ctm->matrix[0] = temp & 0xffff;
+	ctm->matrix[1] = temp >> 16;
+
+	temp = intel_de_read(dev_priv, PIPE_CSC_COEFF_BY(pipe));
+	ctm->matrix[2] = temp & 0xffff;
+
+	temp = intel_de_read(dev_priv, PIPE_CSC_COEFF_RU_GU(pipe));
+	ctm->matrix[3] = temp & 0xffff;
+	ctm->matrix[4] = temp >> 16;
+
+	temp = intel_de_read(dev_priv, PIPE_CSC_COEFF_BU(pipe));
+	ctm->matrix[5] = temp & 0xffff;
+
+	temp = intel_de_read(dev_priv, PIPE_CSC_COEFF_RV_GV(pipe));
+	ctm->matrix[6] = temp & 0xffff;
+	ctm->matrix[7] = temp >> 16;
+
+	temp = intel_de_read(dev_priv, PIPE_CSC_COEFF_BV(pipe));
+	ctm->matrix[8] = temp & 0xffff;
+
+	return blob;
+}
+
+static void ilk_read_csc(struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	if (crtc_state->csc_enable && crtc_state->csc_mode)
+		crtc_state->hw.ctm = ilk_read_csc_matrix(crtc);
+}
+
 static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -348,16 +396,61 @@ static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
 		       crtc_state->csc_mode);
 }
 
-static void chv_load_cgm_csc(struct intel_crtc *crtc,
-			     const struct drm_property_blob *blob)
+static struct drm_property_blob *icl_read_csc_matrix(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	const struct drm_color_ctm *ctm = blob->data;
 	enum pipe pipe = crtc->pipe;
-	u16 coeffs[9];
-	int i;
+	struct drm_property_blob *blob;
+	struct drm_color_ctm *ctm;
+	u32 temp;
 
-	for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
+	blob = drm_property_create_blob(&dev_priv->drm,
+					sizeof(struct drm_color_ctm),
+					NULL);
+	if (IS_ERR(blob))
+		return NULL;
+
+	ctm = blob->data;
+
+	temp = intel_de_read(dev_priv, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe));
+	ctm->matrix[0] = temp & 0xffff;
+	ctm->matrix[1] = temp >> 16;
+
+	temp = intel_de_read(dev_priv, PIPE_CSC_OUTPUT_COEFF_BY(pipe));
+	ctm->matrix[2] = temp & 0xffff;
+
+	temp = intel_de_read(dev_priv, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe));
+	ctm->matrix[3] = temp & 0xffff;
+	ctm->matrix[4] = temp >> 16;
+
+	temp = intel_de_read(dev_priv, PIPE_CSC_OUTPUT_COEFF_BU(pipe));
+	ctm->matrix[5] = temp & 0xffff;
+
+	temp = intel_de_read(dev_priv, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe));
+	ctm->matrix[6] = temp & 0xffff;
+	ctm->matrix[7] = temp >> 16;
+
+	temp = intel_de_read(dev_priv, PIPE_CSC_OUTPUT_COEFF_BV(pipe));
+	ctm->matrix[8] = temp & 0xffff;
+
+	return blob;
+}
+
+static void icl_read_csc(struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	if (crtc_state->csc_mode & ICL_CSC_ENABLE)
+		crtc_state->hw.ctm = ilk_read_csc_matrix(crtc);
+
+	if (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE)
+		crtc_state->hw.ctm = icl_read_csc_matrix(crtc);
+}
+
+static void chv_csc_convert_ctm(const struct drm_color_ctm *ctm, u16 coeffs[9])
+{
+	int i;
+	for (i = 0; i < 9; i++) {
 		u64 abs_coeff = ((1ULL << 63) - 1) & ctm->matrix[i];
 
 		/* Round coefficient. */
@@ -374,6 +467,17 @@ static void chv_load_cgm_csc(struct intel_crtc *crtc,
 		coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
 		coeffs[i] |= (abs_coeff >> 20) & 0xfff;
 	}
+}
+
+static void chv_load_cgm_csc(struct intel_crtc *crtc,
+			     const struct drm_property_blob *blob)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	const struct drm_color_ctm *ctm = blob->data;
+	enum pipe pipe = crtc->pipe;
+	u16 coeffs[9];
+
+	chv_csc_convert_ctm(ctm, coeffs);
 
 	intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF01(pipe),
 		       coeffs[1] << 16 | coeffs[0]);
@@ -1209,6 +1313,9 @@ void intel_color_get_config(struct intel_crtc_state *crtc_state)
 
 	if (dev_priv->display.read_luts)
 		dev_priv->display.read_luts(crtc_state);
+
+	if (dev_priv->display.read_csc)
+		dev_priv->display.read_csc(crtc_state);
 }
 
 static bool need_plane_update(struct intel_plane *plane,
@@ -1789,6 +1896,42 @@ bool intel_color_lut_equal(struct drm_property_blob *blob1,
 	return true;
 }
 
+bool intel_csc_equal(const struct intel_crtc_state *current_config,
+		     struct drm_property_blob *blob1,
+		     struct drm_property_blob *blob2)
+{
+	struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev);
+	struct drm_color_ctm *ctm1, *ctm2;
+	u16 coeffs[9];
+	int i;
+
+	DRM_DEBUG_KMS("Bhanu debug--> sw_ctm[%s] hw_ctm[%s]", yesno(!!blob1), yesno(!!blob2));
+
+	if (!blob1 != !blob2)
+		return false;
+
+	if (!blob1)
+		return true;
+
+	ctm1 = blob1->data;
+	ctm2 = blob2->data;
+
+	if (IS_CHERRYVIEW(dev_priv))
+		chv_csc_convert_ctm(ctm1, coeffs);
+	else
+		ilk_csc_convert_ctm(current_config, coeffs);
+
+	for (i = 0; i < 9; i++)
+		DRM_DEBUG_KMS("Bhanu debug--> sw_ctm[%d]=0x%x hw_ctm[%d]=0x%llx", i, coeffs[i], i, ctm2->matrix[i]);
+
+	for (i = 0; i < 9; i++) {
+		if (abs(coeffs[i] - ctm2->matrix[i]))
+			return false;
+	}
+
+	return true;
+}
+
 static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
@@ -1893,6 +2036,52 @@ static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc)
 	return blob;
 }
 
+static struct drm_property_blob *chv_read_cgm_ctm(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	enum pipe pipe = crtc->pipe;
+	struct drm_property_blob *blob;
+	struct drm_color_ctm *ctm;
+	u32 temp;
+
+	blob = drm_property_create_blob(&dev_priv->drm,
+					sizeof(struct drm_color_ctm),
+					NULL);
+	if (IS_ERR(blob))
+		return NULL;
+
+	ctm = blob->data;
+
+	temp = intel_de_read(dev_priv, CGM_PIPE_CSC_COEFF01(pipe));
+	ctm->matrix[0] = temp & 0xffff;
+	ctm->matrix[1] = temp >> 16;
+
+	temp = intel_de_read(dev_priv, CGM_PIPE_CSC_COEFF23(pipe));
+	ctm->matrix[2] = temp & 0xffff;
+	ctm->matrix[3] = temp >> 16;
+
+	temp = intel_de_read(dev_priv, CGM_PIPE_CSC_COEFF45(pipe));
+	ctm->matrix[4] = temp & 0xffff;
+	ctm->matrix[5] = temp >> 16;
+
+	temp = intel_de_read(dev_priv, CGM_PIPE_CSC_COEFF67(pipe));
+	ctm->matrix[6] = temp & 0xffff;
+	ctm->matrix[7] = temp >> 16;
+
+	temp = intel_de_read(dev_priv, CGM_PIPE_CSC_COEFF8(pipe));
+	ctm->matrix[8] = temp & 0xffff;
+
+	return blob;
+}
+
+static void chv_read_csc(struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	if (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC)
+		crtc_state->hw.ctm = chv_read_cgm_ctm(crtc);
+}
+
 static void chv_read_luts(struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -2031,6 +2220,14 @@ static void glk_read_luts(struct intel_crtc_state *crtc_state)
 	}
 }
 
+static void glk_read_csc(struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	if (crtc_state->csc_enable && !crtc_state->csc_mode)
+		crtc_state->hw.ctm = ilk_read_csc_matrix(crtc);
+}
+
 static struct drm_property_blob *
 icl_read_lut_multi_segment(struct intel_crtc *crtc)
 {
@@ -2105,6 +2302,7 @@ void intel_color_init(struct intel_crtc *crtc)
 			dev_priv->display.color_commit = i9xx_color_commit;
 			dev_priv->display.load_luts = chv_load_luts;
 			dev_priv->display.read_luts = chv_read_luts;
+			dev_priv->display.read_csc = chv_read_csc;
 		} else if (INTEL_GEN(dev_priv) >= 4) {
 			dev_priv->display.color_check = i9xx_color_check;
 			dev_priv->display.color_commit = i9xx_color_commit;
@@ -2147,6 +2345,13 @@ void intel_color_init(struct intel_crtc *crtc)
 			dev_priv->display.load_luts = ilk_load_luts;
 			dev_priv->display.read_luts = ilk_read_luts;
 		}
+
+		if (INTEL_GEN(dev_priv) >= 11)
+			dev_priv->display.read_csc = icl_read_csc;
+		else if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv))
+			dev_priv->display.read_csc = glk_read_csc;
+		else
+			dev_priv->display.read_csc = ilk_read_csc;
 	}
 
 	drm_crtc_enable_color_mgmt(&crtc->base,
diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h
index 173727aaa24d..e6bd9aa0c04a 100644
--- a/drivers/gpu/drm/i915/display/intel_color.h
+++ b/drivers/gpu/drm/i915/display/intel_color.h
@@ -21,5 +21,8 @@ int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_stat
 bool intel_color_lut_equal(struct drm_property_blob *blob1,
 			   struct drm_property_blob *blob2,
 			   u32 gamma_mode, u32 bit_precision);
+bool intel_csc_equal(const struct intel_crtc_state *crtc_state,
+			   struct drm_property_blob *blob1,
+			   struct drm_property_blob *blob2);
 
 #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 c0a400926fc7..5bb48b3a477a 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -8923,6 +8923,29 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 	} \
 } while (0)
 
+#define PIPE_CONF_CHECK_CSC(name1, name2, name3) do { \
+	if (current_config->name1 != pipe_config->name1) { \
+		pipe_config_mismatch(fastset, crtc, __stringify(name1), \
+				"(expected %s, found %s, won't compare csc coeffs)", \
+				yesno(current_config->name1), \
+				yesno(pipe_config->name1)); \
+		ret = false;\
+	} else if (current_config->name2 != pipe_config->name2) { \
+		pipe_config_mismatch(fastset, crtc, __stringify(name2), \
+				"(expected %i, found %i, won't compare csc coeffs)", \
+				current_config->name2, \
+				pipe_config->name2); \
+		ret = false;\
+	} else { \
+		if (!intel_csc_equal(current_config, current_config->name3, \
+				pipe_config->name3)) { \
+			pipe_config_mismatch(fastset, crtc, __stringify(name3), \
+					"hw_state doesn't match sw_state"); \
+			ret = false; \
+		} \
+	} \
+} while (0)
+
 #define PIPE_CONF_QUIRK(quirk) \
 	((current_config->quirks | pipe_config->quirks) & (quirk))
 
@@ -9050,6 +9073,11 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 		bp_gamma = intel_color_get_gamma_bit_precision(pipe_config);
 		if (bp_gamma)
 			PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, hw.gamma_lut, bp_gamma);
+
+		if (IS_CHERRYVIEW(dev_priv))
+			PIPE_CONF_CHECK_CSC(csc_enable, cgm_mode, hw.ctm);
+		else
+			PIPE_CONF_CHECK_CSC(csc_enable, csc_mode, hw.ctm);
 	}
 
 	PIPE_CONF_CHECK_BOOL(double_wide);
@@ -9141,6 +9169,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 #undef PIPE_CONF_CHECK_FLAGS
 #undef PIPE_CONF_CHECK_CLOCK_FUZZY
 #undef PIPE_CONF_CHECK_COLOR_LUT
+#undef PIPE_CONF_CHECK_CSC
 #undef PIPE_CONF_QUIRK
 
 	return ret;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 2f511bf2bd82..83c8e0b29acb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -327,6 +327,8 @@ struct drm_i915_display_funcs {
 	 */
 	void (*load_luts)(const struct intel_crtc_state *crtc_state);
 	void (*read_luts)(struct intel_crtc_state *crtc_state);
+	void (*load_csc)(const struct intel_crtc_state *crtc_state);
+	void (*read_csc)(struct intel_crtc_state *crtc_state);
 };
 
 struct intel_csr {
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list