@@ -6095,6 +6095,11 @@ enum punit_power_well {
#define CSC_OFFSET (_PIPEBCSC - _PIPEACSC)
#define PIPECSC(pipe) (_PIPEACSC + (pipe * CSC_OFFSET))
+/* Gamma GCMAX */
+#define VLV_PIPEA_GCMAX (dev_priv->info.display_mmio_offset + 0x70010)
+#define VLV_PIPEB_GCMAX (dev_priv->info.display_mmio_offset + 0x71010)
+#define VLV_PIPE_GCMAX(pipe) _PIPE(pipe, VLV_PIPEA_GCMAX, VLV_PIPEB_GCMAX)
+
/* VLV MIPI registers */
#define _MIPIA_PORT_CTRL (VLV_DISPLAY_BASE + 0x61190)
@@ -51,6 +51,7 @@ struct clrmgr_property gen6_pipe_color_corrections[] = {
.type = DRM_MODE_PROP_BLOB,
.len = VLV_10BIT_GAMMA_MAX_VALS,
.name = "gamma-correction",
+ .set_property = intel_clrmgr_set_gamma,
},
};
@@ -89,6 +90,130 @@ struct clrmgr_property gen6_plane_color_corrections[] = {
};
/*
+* vlv_set_10bit_gamma
+* Valleyview specific gamma correction method.
+* Programs the palette registers in 10bit method
+* with 128 correction values, sampled across 1024
+* gamma correction values at sampling rate of 8.
+* inputs:
+* - intel_crtc*
+* - color manager registered property for gamma correction
+* - data: pointer to correction values to be applied
+*/
+static bool vlv_set_10bit_gamma(struct intel_crtc *intel_crtc,
+ struct clrmgr_regd_prop *gamma, u64 *data)
+{
+ u16 red, green, blue;
+ u64 correct_rgb;
+ u32 val, even, odd;
+ u32 count = 0;
+ u32 reg = 0;
+ struct drm_property *property = gamma->property;
+ struct drm_device *dev = intel_crtc->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 palette = PALETTE(intel_crtc->pipe);
+
+ /* Validate input */
+ if (property->num_values != VLV_10BIT_GAMMA_MAX_VALS) {
+ DRM_ERROR("Unexpected value count for GAMMA LUT");
+ return false;
+ }
+
+ /* 128, 64 bit values, coming in <0><R16><G16><B16> format containing
+ only 10 integer and 6fraction correction values */
+ while (count < (property->num_values - CLRMGR_GAMMA_GCMAX_VAL)) {
+ correct_rgb = data[count];
+ property->values[count] = correct_rgb;
+
+ blue = correct_rgb >> CLRMGR_GAMMA_PARSER_SHIFT_BLUE;
+ green = correct_rgb >> CLRMGR_GAMMA_PARSER_SHIFT_GREEN;
+ red = correct_rgb >> CLRMGR_GAMMA_PARSER_SHIFT_RED;
+
+ /* Prepare even and odd regs. Even register contains 6
+ fractional and 2 integer base bits, so lower 8 bits */
+ even = ((blue & VLV_GAMMA_EVEN_MASK) <<
+ VLV_GAMMA_SHIFT_BLUE_REG) |
+ ((green & VLV_GAMMA_EVEN_MASK) <<
+ VLV_GAMMA_SHIFT_GREEN_REG) |
+ ((red & VLV_GAMMA_EVEN_MASK) <<
+ VLV_GAMMA_SHIFT_RED_REG);
+
+ /* Odd register contains upper 8 (integer) bits */
+ odd = ((blue >> VLV_GAMMA_ODD_SHIFT) <<
+ VLV_GAMMA_SHIFT_BLUE_REG) |
+ ((green >> VLV_GAMMA_ODD_SHIFT) <<
+ VLV_GAMMA_SHIFT_GREEN_REG) |
+ ((red >> VLV_GAMMA_ODD_SHIFT) <<
+ VLV_GAMMA_SHIFT_RED_REG);
+
+ /* Writing fraction part first, then integer part */
+ I915_WRITE(palette, even);
+ palette += 4;
+ I915_WRITE(palette, odd);
+ palette += 4;
+ count++;
+ }
+
+ /* Last 64bit values is in 11.6 format for GCmax, RGB sequence */
+ correct_rgb = data[count];
+ property->values[count] = correct_rgb;
+
+ count = CLRMGR_GAMMA_TOTAL_GCMAX_REGS;
+ reg = VLV_PIPE_GCMAX(intel_crtc->pipe);
+ while (count--) {
+ val = (correct_rgb >> (count * VLV_CLRMGR_GAMMA_GCMAX_SHIFT)) &
+ VLV_GAMMA_GCMAX_MASK;
+ /* GCMAX value must be <= 1024 */
+ if (val > VLV_CLRMGR_GAMMA_GCMAX_MAX)
+ val = VLV_CLRMGR_GAMMA_GCMAX_MAX;
+
+ /* Write in 11.6 format */
+ I915_WRITE(reg, (val << 6));
+ reg += 4;
+ }
+
+ /* Enable gamma for PIPE */
+ reg = PIPECONF(intel_crtc->pipe);
+ val = I915_READ(reg) | PIPECONF_GAMMA;
+ I915_WRITE(reg, val);
+
+ /* Enable gamma for sprites */
+ for_each_sprite(intel_crtc->pipe, count) {
+ reg = SPCNTR(intel_crtc->pipe, count);
+ val = I915_READ(reg) | SPRITE_GAMMA_ENABLE;
+ I915_WRITE(reg, val);
+ }
+
+ DRM_DEBUG_DRIVER("10bit gamma correction successfully applied");
+ return true;
+}
+
+bool intel_clrmgr_set_gamma(void *crtc,
+ struct clrmgr_regd_prop *gamma, u64 *data)
+{
+ struct intel_crtc *intel_crtc = crtc;
+ struct drm_device *dev = intel_crtc->base.dev;
+
+ /* Validate input */
+ if (!data || !gamma || !gamma->property) {
+ DRM_ERROR("Invalid input to set_gamma\n");
+ return false;
+ }
+
+ DRM_DEBUG_DRIVER("Setting gamma correction, len=%d\n",
+ gamma->property->num_values);
+
+ /* VLV has legacy palette gamma correction */
+ if (IS_VALLEYVIEW(dev))
+ return vlv_set_10bit_gamma(intel_crtc, gamma, data);
+
+ /* Todo: Support other gen devices */
+ DRM_ERROR("Color correction is supported only on VLV for now\n");
+ return false;
+}
+
+
+/*
* vlv_set_csc
* Valleyview specific csc correction method.
* Programs the 6 csc registers with 3x3 correction matrix
@@ -40,6 +40,12 @@
#define CLRMGR_PROP_NAME_MAX 128
#define CLRMGR_PROP_RANGE_MAX 0xFFFFFFFFFFFFFFFF
+/* Gamma correcttion */
+#define CLRMGR_GAMMA_PARSER_SHIFT_BLUE 0
+#define CLRMGR_GAMMA_PARSER_SHIFT_GREEN 16
+#define CLRMGR_GAMMA_PARSER_SHIFT_RED 32
+#define CLRMGR_GAMMA_TOTAL_GCMAX_REGS 3
+#define CLRMGR_GAMMA_MAX_SAMPLES 1024
/* CSC / Wide gamut */
#define VLV_CSC_MATRIX_MAX_VALS 9
@@ -52,6 +58,16 @@
#define CLRMGR_GAMMA_GCMAX_VAL 1
#define VLV_10BIT_GAMMA_MAX_VALS (VLV_10BIT_GAMMA_MAX_INDEX + \
CLRMGR_GAMMA_GCMAX_VAL)
+#define VLV_GAMMA_EVEN_MASK 0xFF
+#define VLV_GAMMA_SHIFT_BLUE_REG 0
+#define VLV_GAMMA_SHIFT_GREEN_REG 8
+#define VLV_GAMMA_SHIFT_RED_REG 16
+#define VLV_GAMMA_ODD_SHIFT 8
+#define VLV_CLRMGR_GAMMA_GCMAX_SHIFT 17
+#define VLV_GAMMA_GCMAX_MASK 0x1FFFF
+#define VLV_CLRMGR_GAMMA_GCMAX_MAX 0x400
+
+
/* Sprite Contrast and Brightness Registers */
#define VLV_CB_MAX_VALS 1
@@ -119,6 +135,19 @@ struct clrmgr_reg_request {
};
/*
+* intel_clrmgr_set_gamma
+* Gamma correction method is different across various
+* gen devices. This is a wrapper function which will call
+* the platform specific gamma set function
+* inputs:
+* - crtc : void *, which can be typecasted to intel_crtc*
+* - gamma: registered color property for gamma correction
+* - data: pointer to correction values to be applied
+*/
+bool intel_clrmgr_set_gamma(void *crtc,
+ struct clrmgr_regd_prop *gamma, u64 *data);
+
+/*
* intel_clrmgr_set_csc
* CSC correction method is different across various
* gen devices. This wrapper function calls the respective