[RFC v1 6/7] drm/i915/icl: Add support for multi segmented gamma mode

Uma Shankar uma.shankar at intel.com
Tue Mar 19 07:17:22 UTC 2019


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

Signed-off-by: Uma Shankar <uma.shankar at 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



More information about the Intel-gfx-trybot mailing list