Add callback for programming Pre-CSC LUT for TGL and beyond Signed-off-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@xxxxxxxxx> Signed-off-by: Uma Shankar <uma.shankar@xxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_color.c | 88 ++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 0d68f8303502..6dd9b8e43352 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3779,9 +3779,97 @@ void intel_color_load_plane_csc_matrix(const struct drm_plane_state *plane_state i915->display.funcs.color->load_plane_csc_matrix(plane_state, blob); } +static void xelpd_program_plane_pre_csc_lut(const struct drm_plane_state *state, + const struct drm_color_lut_ext *pre_csc_lut, + u32 offset) +{ + struct drm_i915_private *dev_priv = to_i915(state->plane->dev); + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + u32 i, lut_size; + + if (icl_is_hdr_plane(dev_priv, plane)) { + lut_size = 128; + + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + + if (pre_csc_lut) { + for (i = 0; i < lut_size; i++) { + u64 word = drm_color_lut_extract_ext(pre_csc_lut[i].green, 24); + u32 lut_val = (word & 0xffffff); + + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + lut_val); + } + + /* Program the max register to clamp values > 1.0. */ + while (i < 131) + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + pre_csc_lut[i++].green); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1); + + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), v); + } + + do { + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), + 1 << 24); + } while (i++ < 130); + } + + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); + } else { + lut_size = 32; + + /* + * First 3 planes are HDR, so reduce by 3 to get to the right + * SDR plane offset + */ + plane = plane - 3; + + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, 0), + offset | PLANE_PAL_PREC_AUTO_INCREMENT); + + if (pre_csc_lut) { + for (i = 0; i < lut_size; i++) + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + pre_csc_lut[i].green); + /* Program the max register to clamp values > 1.0. */ + while (i < 35) + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + pre_csc_lut[i++].green); + } else { + for (i = 0; i < lut_size; i++) { + u32 v = (i * ((1 << 16) - 1)) / (lut_size - 1); + + intel_de_write_fw(dev_priv, + PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), v); + } + + do { + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_DATA(pipe, plane, 0), + 1 << 16); + } while (i++ < 34); + } + + intel_de_write_fw(dev_priv, PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, 0), 0); + } +} + static void xelpd_plane_load_luts(const struct drm_plane_state *plane_state, const struct drm_property_blob *blob, bool is_pre_csc) { + struct drm_color_lut_ext *lut = blob->data; + + if (is_pre_csc) + xelpd_program_plane_pre_csc_lut(plane_state, lut, 0); } void intel_color_load_plane_luts(const struct drm_plane_state *plane_state, -- 2.42.0