drm/i915: Expose full 1024 LUT entries on ivb+
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Wed, 3 Apr 2019 19:16:33 +0000 (22:16 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Wed, 3 Apr 2019 19:26:13 +0000 (22:26 +0300)
On ivb+ we can select between the regular 10bit LUT mode with
1024 entries, and the split mode where the LUT is split into
seprate degamma and gamma halves (each with 512 entries). Currently
we expose the split gamma size of 512 as the GAMMA/DEGAMMA_LUT_SIZE.

When using only degamma or gamma (not both) we are wasting half of
the hardware LUT entries. Let's flip that around so that we expose
the full 1024 entries and just throw away half of the user provided
entries when using the split gamma mode.

Cc: Matt Roper <matthew.d.roper@intel.com>
Suggested-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190401200231.2333-8-ville.syrjala@linux.intel.com
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/intel_color.c

index 81d14dc2fa61274b24250585c309f85062ae4b2c..6ffb85ddac53ef0e2e371be92c930156317ae045 100644 (file)
 #define ILK_COLORS \
        .color = { .gamma_lut_size = 1024 }
 #define IVB_COLORS \
-       .color = { .degamma_lut_size = 512, .gamma_lut_size = 512 }
+       .color = { .degamma_lut_size = 1024, .gamma_lut_size = 1024 }
 #define CHV_COLORS \
        .color = { .degamma_lut_size = 65, .gamma_lut_size = 257, \
                   .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \
index efcf9e2d0b565719b84a3c9d65fd983f48a7e4cb..60f21a1fdbbefbbd4c18e44d977e77613bfe044e 100644 (file)
@@ -538,6 +538,14 @@ static void ilk_load_luts(const struct intel_crtc_state *crtc_state)
                ilk_load_lut_10(crtc, gamma_lut);
 }
 
+static int ivb_lut_10_size(u32 prec_index)
+{
+       if (prec_index & PAL_PREC_SPLIT_MODE)
+               return 512;
+       else
+               return 1024;
+}
+
 /*
  * IVB/HSW Bspec / PAL_PREC_INDEX:
  * "Restriction : Index auto increment mode is not
@@ -545,31 +553,21 @@ static void ilk_load_luts(const struct intel_crtc_state *crtc_state)
  */
 static void ivb_load_lut_10(struct intel_crtc *crtc,
                            const struct drm_property_blob *blob,
-                           u32 prec_index, bool duplicate)
+                           u32 prec_index)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       int hw_lut_size = ivb_lut_10_size(prec_index);
        const struct drm_color_lut *lut = blob->data;
        int i, lut_size = drm_color_lut_size(blob);
        enum pipe pipe = crtc->pipe;
 
-       /*
-        * We advertise the split gamma sizes. When not using split
-        * gamma we just duplicate each entry.
-        *
-        * TODO: expose the full LUT to userspace
-        */
-       if (duplicate) {
-               for (i = 0; i < lut_size; i++) {
-                       I915_WRITE(PREC_PAL_INDEX(pipe), prec_index++);
-                       I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_10(&lut[i]));
-                       I915_WRITE(PREC_PAL_INDEX(pipe), prec_index++);
-                       I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_10(&lut[i]));
-               }
-       } else {
-               for (i = 0; i < lut_size; i++) {
-                       I915_WRITE(PREC_PAL_INDEX(pipe), prec_index++);
-                       I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_10(&lut[i]));
-               }
+       for (i = 0; i < hw_lut_size; i++) {
+               /* We discard half the user entries in split gamma mode */
+               const struct drm_color_lut *entry =
+                       &lut[i * (lut_size - 1) / (hw_lut_size - 1)];
+
+               I915_WRITE(PREC_PAL_INDEX(pipe), prec_index++);
+               I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_10(entry));
        }
 
        /*
@@ -582,9 +580,10 @@ static void ivb_load_lut_10(struct intel_crtc *crtc,
 /* On BDW+ the index auto increment mode actually works */
 static void bdw_load_lut_10(struct intel_crtc *crtc,
                            const struct drm_property_blob *blob,
-                           u32 prec_index, bool duplicate)
+                           u32 prec_index)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       int hw_lut_size = ivb_lut_10_size(prec_index);
        const struct drm_color_lut *lut = blob->data;
        int i, lut_size = drm_color_lut_size(blob);
        enum pipe pipe = crtc->pipe;
@@ -592,20 +591,12 @@ static void bdw_load_lut_10(struct intel_crtc *crtc,
        I915_WRITE(PREC_PAL_INDEX(pipe), prec_index |
                   PAL_PREC_AUTO_INCREMENT);
 
-       /*
-        * We advertise the split gamma sizes. When not using split
-        * gamma we just duplicate each entry.
-        *
-        * TODO: expose the full LUT to userspace
-        */
-       if (duplicate) {
-               for (i = 0; i < lut_size; i++) {
-                       I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_10(&lut[i]));
-                       I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_10(&lut[i]));
-               }
-       } else {
-               for (i = 0; i < lut_size; i++)
-                       I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_10(&lut[i]));
+       for (i = 0; i < hw_lut_size; i++) {
+               /* We discard half the user entries in split gamma mode */
+               const struct drm_color_lut *entry =
+                       &lut[i * (lut_size - 1) / (hw_lut_size - 1)];
+
+               I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_10(entry));
        }
 
        /*
@@ -647,15 +638,15 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state)
                i9xx_load_luts(crtc_state);
        } else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) {
                ivb_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
-                               PAL_PREC_INDEX_VALUE(0), false);
+                               PAL_PREC_INDEX_VALUE(0));
                ivb_load_lut_10_max(crtc);
                ivb_load_lut_10(crtc, gamma_lut, PAL_PREC_SPLIT_MODE |
-                               PAL_PREC_INDEX_VALUE(512),  false);
+                               PAL_PREC_INDEX_VALUE(512));
        } else {
                const struct drm_property_blob *blob = gamma_lut ?: degamma_lut;
 
                ivb_load_lut_10(crtc, blob,
-                               PAL_PREC_INDEX_VALUE(0), true);
+                               PAL_PREC_INDEX_VALUE(0));
                ivb_load_lut_10_max(crtc);
        }
 }
@@ -670,15 +661,15 @@ static void bdw_load_luts(const struct intel_crtc_state *crtc_state)
                i9xx_load_luts(crtc_state);
        } else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) {
                bdw_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
-                               PAL_PREC_INDEX_VALUE(0), false);
+                               PAL_PREC_INDEX_VALUE(0));
                ivb_load_lut_10_max(crtc);
                bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_SPLIT_MODE |
-                               PAL_PREC_INDEX_VALUE(512),  false);
+                               PAL_PREC_INDEX_VALUE(512));
        } else {
                const struct drm_property_blob *blob = gamma_lut ?: degamma_lut;
 
                bdw_load_lut_10(crtc, blob,
-                               PAL_PREC_INDEX_VALUE(0), true);
+                               PAL_PREC_INDEX_VALUE(0));
                ivb_load_lut_10_max(crtc);
        }
 }
@@ -770,7 +761,7 @@ static void glk_load_luts(const struct intel_crtc_state *crtc_state)
        if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) {
                i9xx_load_luts(crtc_state);
        } else {
-               bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0), false);
+               bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0));
                ivb_load_lut_10_max(crtc);
        }
 }
@@ -787,7 +778,7 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state)
            GAMMA_MODE_MODE_8BIT) {
                i9xx_load_luts(crtc_state);
        } else {
-               bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0), false);
+               bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0));
                ivb_load_lut_10_max(crtc);
        }
 }