MTL onwards Degamma LUT/PRE-CSC LUT precision has been increased from 16 bits to 24 bits. Currently, drm framework only supports LUTs up to 16 bit precision. Until a new uapi comes along to support higher bitdepth, 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 8966e6560516..25c73e2e6fa3 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1498,6 +1498,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; @@ -1635,11 +1667,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