[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