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.bo...@intel.com>
---
 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

Reply via email to