diff mbox

[05/11] drm/i915: Add color manager gamma correction

Message ID 1406138705-17334-6-git-send-email-shashank.sharma@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sharma, Shashank July 23, 2014, 6:04 p.m. UTC
From: Shashank Sharma <shashank.sharma@intel.com>

This patch adds support for pipe gamma correction color property
for intel color manager framework. It adds two functions:
1. intel_clrmgr_set_gamma: This is a wrapper function
   which checks the platform type, and calls the valleyview
   specific set_gamma function. As different platforms have different
   methods of setting pipe gamma, this function is required.The support for
   other platfroms can be plugged-in here in the wrapper function.
   Adding this function as .set_property of gamma-correction color property.
2. vlv_set_10_bit_gamma: Core function to program gamma coefficients as per
   vlv specs, and then enable gamma on pipe. This function uses 10-bit gamma
   programming method of VLV (10.6 method), which is more accurate, and can
   support fraction values also. Userspace encodes 16 bit per channel gamma
   correction value in 64bit value in <None><R16><G16><B16> format, and sends
   128 such gamma correction values. The 129th value is GCMAX register value.

Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h     |   5 ++
 drivers/gpu/drm/i915/intel_clrmgr.c | 125 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_clrmgr.h |  29 +++++++++
 3 files changed, 159 insertions(+)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 3199f96..9501ad8 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -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)
diff --git a/drivers/gpu/drm/i915/intel_clrmgr.c b/drivers/gpu/drm/i915/intel_clrmgr.c
index 601076b..38ba878 100644
--- a/drivers/gpu/drm/i915/intel_clrmgr.c
+++ b/drivers/gpu/drm/i915/intel_clrmgr.c
@@ -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
diff --git a/drivers/gpu/drm/i915/intel_clrmgr.h b/drivers/gpu/drm/i915/intel_clrmgr.h
index e1279f6..fd8b98e 100644
--- a/drivers/gpu/drm/i915/intel_clrmgr.h
+++ b/drivers/gpu/drm/i915/intel_clrmgr.h
@@ -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