MTL onwards Degamma LUT/PRE-CSC LUT precision has been increased from 16 bit to 24 bits. Currently, drm framework only supports LUTs upto 16 bit precision. There is a new uapi in discussion which would support 32.32 bit precision. Until theni, upscale the values sent from userland to 24 bit before writing into the HW to continue supporting degamma on MTL. Signed-off-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@xxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_color.c | 42 ++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index d57631b0bb9a..04b941cbc083 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1104,6 +1104,38 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), 0); } +static void mtl_load_degamma_lut(const struct intel_crtc_state *crtc_state, + const struct drm_property_blob *blob) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct drm_color_lut *degamma_lut = blob->data; + enum pipe pipe = crtc->pipe; + int i, lut_size = drm_color_lut_size(blob); + + /* + * When setting the auto-increment bit, the hardware seems to + * ignore the index bits, so we need to reset it to index 0 + * separately. + */ + intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), 0); + intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), + PRE_CSC_GAMC_AUTO_INCREMENT); + + for (i = 0; i < lut_size; i++) { + u64 word = mul_u32_u32(degamma_lut[i].green, (1 << 24)) / (1 << 16); + u32 lut_val = (word & 0xffffff); + + intel_de_write_fw(i915, PRE_CSC_GAMC_DATA(pipe), + lut_val); + } + /* Clamp values > 1.0. */ + while (i++ < glk_degamma_lut_size(i915)) + intel_de_write_fw(i915, PRE_CSC_GAMC_DATA(pipe), 1 << 24); + + intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), 0); +} + static void glk_load_luts(const struct intel_crtc_state *crtc_state) { const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; @@ -1241,11 +1273,17 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) static void icl_load_luts(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); const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut; const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut; - if (pre_csc_lut) - glk_load_degamma_lut(crtc_state, pre_csc_lut); + if (pre_csc_lut) { + if (DISPLAY_VER(i915) >= 14) + mtl_load_degamma_lut(crtc_state, pre_csc_lut); + else + glk_load_degamma_lut(crtc_state, pre_csc_lut); + } switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) { case GAMMA_MODE_MODE_8BIT: -- 2.25.1