Gen11 introduced a new gamma mode i.e, multi segmented
gamma mode. Added support for the same.

Signed-off-by: Uma Shankar <uma.shan...@intel.com>
---
 drivers/gpu/drm/i915/intel_color.c | 105 +++++++++++++++++++++++++++++++------
 1 file changed, 90 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_color.c 
b/drivers/gpu/drm/i915/intel_color.c
index 399d63d..7733c256 100644
--- a/drivers/gpu/drm/i915/intel_color.c
+++ b/drivers/gpu/drm/i915/intel_color.c
@@ -105,6 +105,9 @@
                MULTI_SEGMENTED_GAMMA_MODE_12BIT | \
                BIT_SPLIT_GAMMA_MODE_12BIT)
 
+#define GEN11_GET_MS10BITS_OF_LUT(lut) (((lut) >> 6) & 0x3FF)
+#define GEN11_GET_LS6BITS_OF_LUT(lut)  ((lut) & 0x3F)
+
 static bool lut_is_legacy(const struct drm_property_blob *lut)
 {
        return drm_color_lut_size(lut) == LEGACY_LUT_LENGTH;
@@ -538,6 +541,10 @@ static void bdw_load_degamma_lut(const struct 
intel_crtc_state *crtc_state)
        if (degamma_lut) {
                const struct drm_color_lut *lut = degamma_lut->data;
 
+               if (crtc_state->gamma_mode_type ==
+                               MULTI_SEGMENTED_GAMMA_MODE_12BIT)
+                       lut += 9;
+
                for (i = 0; i < lut_size; i++) {
                        u32 word =
                        drm_color_lut_extract(lut[i].red, 10) << 20 |
@@ -563,6 +570,7 @@ static void bdw_load_gamma_lut(const struct 
intel_crtc_state *crtc_state, u32 of
        const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
        u32 i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
        enum pipe pipe = crtc->pipe;
+       u32 word;
 
        WARN_ON(offset & ~PAL_PREC_INDEX_VALUE_MASK);
 
@@ -574,13 +582,32 @@ static void bdw_load_gamma_lut(const struct 
intel_crtc_state *crtc_state, u32 of
        if (gamma_lut) {
                const struct drm_color_lut *lut = gamma_lut->data;
 
-               for (i = 0; i < lut_size; i++) {
-                       u32 word =
-                       (drm_color_lut_extract(lut[i].red, 10) << 20) |
-                       (drm_color_lut_extract(lut[i].green, 10) << 10) |
-                       drm_color_lut_extract(lut[i].blue, 10);
-
-                       I915_WRITE(PREC_PAL_DATA(pipe), word);
+               if (crtc_state->gamma_mode_type ==
+                               MULTI_SEGMENTED_GAMMA_MODE_12BIT) {
+                       lut_size = 9 + 512;
+                       for (i = 9; i < lut_size; i++) {
+                               /* For Even Index */
+                               word = (GEN11_GET_LS6BITS_OF_LUT(lut[i].red) << 
20) |
+                                       (GEN11_GET_LS6BITS_OF_LUT(lut[i].green) 
<< 10)|
+                                       GEN11_GET_LS6BITS_OF_LUT(lut[i].blue);
+
+                                        
I915_WRITE(PREC_PAL_MULTI_SEG_DATA(pipe), word);
+
+                                        /* For ODD index */
+                                        word = 
(GEN11_GET_MS10BITS_OF_LUT(lut[i].red) << 20) |
+                                               
(GEN11_GET_MS10BITS_OF_LUT(lut[i].green) << 10) |
+                                               
GEN11_GET_MS10BITS_OF_LUT(lut[i].blue);
+
+                                       
I915_WRITE(PREC_PAL_MULTI_SEG_DATA(pipe), word);
+                       }
+               } else {
+                       for (i = 0; i < lut_size; i++) {
+                               word = (drm_color_lut_extract(lut[i].red, 10) 
<< 20) |
+                                       (drm_color_lut_extract(lut[i].green, 
10) << 10) |
+                                       drm_color_lut_extract(lut[i].blue, 10);
+
+                               I915_WRITE(PREC_PAL_DATA(pipe), word);
+                       }
                }
 
                /* Program the max register to clamp values > 1.0. */
@@ -685,15 +712,57 @@ static void glk_load_luts(const struct intel_crtc_state 
*crtc_state)
                bdw_load_gamma_lut(crtc_state, 0);
 }
 
+static void icl_load_gamma_multi_segmented_lut(const struct intel_crtc_state
+                                              *crtc_state, u32 offset)
+{
+       struct drm_crtc *crtc = crtc_state->base.crtc;
+       struct drm_device *dev = crtc_state->base.crtc->dev;
+       struct drm_i915_private *dev_priv = to_i915(dev);
+       enum pipe pipe = to_intel_crtc(crtc)->pipe;
+       u32 i, lut_size = 9;
+
+       WARN_ON(offset & ~PAL_PREC_MULTI_SEGMENT_INDEX_VALUE_MASK);
+
+       I915_WRITE(PREC_PAL_MULTI_SEG_INDEX(pipe),
+                  (PAL_PREC_AUTO_INCREMENT | offset));
+
+       if (crtc_state->base.gamma_lut) {
+               struct drm_color_lut *lut =
+                       (struct drm_color_lut 
*)crtc_state->base.gamma_lut->data;
+
+               for (i = 0; i < lut_size; i++) {
+                       u32 word;
+
+                       /* For Even Index */
+                       word = (GEN11_GET_LS6BITS_OF_LUT(lut[i].red) << 20) |
+                              (GEN11_GET_LS6BITS_OF_LUT(lut[i].green) << 10) |
+                              GEN11_GET_LS6BITS_OF_LUT(lut[i].blue);
+                       I915_WRITE(PREC_PAL_MULTI_SEG_DATA(pipe), word);
+
+                       /* For ODD index */
+                       word = (GEN11_GET_MS10BITS_OF_LUT(lut[i].red) << 20) |
+                              (GEN11_GET_MS10BITS_OF_LUT(lut[i].green) << 10) |
+                              GEN11_GET_MS10BITS_OF_LUT(lut[i].blue);
+                       I915_WRITE(PREC_PAL_MULTI_SEG_DATA(pipe), word);
+               }
+       }
+
+       bdw_load_gamma_lut(crtc_state, 0);
+}
+
 static void icl_load_luts(const struct intel_crtc_state *crtc_state)
 {
        glk_load_degamma_lut(crtc_state);
 
-       if (crtc_state_is_legacy_gamma(crtc_state))
+       if (crtc_state_is_legacy_gamma(crtc_state)) {
                i9xx_load_luts(crtc_state);
-       else
+       } else if (crtc_state->gamma_mode_type ==
+                  MULTI_SEGMENTED_GAMMA_MODE_12BIT) {
+               icl_load_gamma_multi_segmented_lut(crtc_state, 0);
+       } else {
                /* ToDo: Add support for multi segment gamma LUT */
                bdw_load_gamma_lut(crtc_state, 0);
+       }
 }
 
 static void cherryview_load_luts(const struct intel_crtc_state *crtc_state)
@@ -910,16 +979,22 @@ int intel_color_check(struct intel_crtc_state *crtc_state)
            drm_color_lut_check(gamma_lut, gamma_tests))
                return -EINVAL;
 
-       if (INTEL_GEN(dev_priv) >= 11)
-               crtc_state->gamma_mode = GAMMA_MODE_MODE_10BIT |
-                                        PRE_CSC_GAMMA_ENABLE |
+       if (INTEL_GEN(dev_priv) >= 11) {
+               crtc_state->gamma_mode = PRE_CSC_GAMMA_ENABLE |
                                         POST_CSC_GAMMA_ENABLE;
-       else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+               if (crtc_state->gamma_mode_type ==
+                               MULTI_SEGMENTED_GAMMA_MODE_12BIT)
+                       crtc_state->gamma_mode |=
+                               GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED;
+               else
+                       crtc_state->gamma_mode |= GAMMA_MODE_MODE_10BIT;
+       } else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
                crtc_state->gamma_mode = GAMMA_MODE_MODE_10BIT;
-       else if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
+       } else if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) {
                crtc_state->gamma_mode = GAMMA_MODE_MODE_SPLIT;
-       else
+       } else {
                crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
+       }
 
        if (INTEL_GEN(dev_priv) >= 11) {
                if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
-- 
1.9.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to