[PATCH 2/2] drm/i915: Add module parameter to en-/disable hw color correction.

Mario Kleiner mario.kleiner.de at gmail.com
Fri Sep 15 15:48:25 UTC 2017


The new module parameter enable_hw_color_correction defaults to
true, to retain the current behaviour. If set to false, it will
disable all hardware color correction, like gamma/degamma and
csc.

This is useful for debugging gamma table / csc precision problems,
and to ensure unmodified pixel passthrough from framebuffer to
outputs, e.g., for scientific applications which critically depend
on perfect pixel passthrough. While i hope this switch generally
won't be needed, it provides extra peace-of-mind - an "airbag" for
color correction trouble.

Tested on Ironlake, IvyBridge, Haswell, Skylake.

One unexpected result during testing was that while this works on
all tested gpu's with a 8 bpc XR24 framebuffer as primary plane,
if a 10 bpc XR30 fb is active, then hw gamma tables seem to get
automatically bypassed on at least the tested IvyBridge and later
(but not on the tested Ironlake), regardless of hw programming,
at least for the legacy 256->8 bit luts and the 1024->10 bit
precision luts. However, the type of selected - but bypassed -
hw gamma table still determines output precision, ie. even an
auto-bypassed legacy 256 slot 8 bit lut in XR30 fb mode still
restricts the effective output precision to 8 bit, while an
auto-bypassed precision lut doesn't restrict precision.

Iow. this patch is needed even with XR30 fb's for actual 10
bit precision output, even though the hw seems to sort of ignore
the tested gamma tables for XR30 fb's.

Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
---
 drivers/gpu/drm/i915/i915_params.c   |  5 +++++
 drivers/gpu/drm/i915/i915_params.h   |  3 ++-
 drivers/gpu/drm/i915/intel_display.c | 26 +++++++++++++++++---------
 drivers/gpu/drm/i915/intel_sprite.c  | 21 ++++++++++++++++-----
 4 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 07ec3a96457c..8f6a176a97e1 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -66,6 +66,7 @@ struct i915_params i915 __read_mostly = {
 	.enable_dpcd_backlight = false,
 	.enable_gvt = false,
 	.enable_dithering = -1,
+	.enable_hw_color_correction = true,
 };
 
 module_param_named(modeset, i915.modeset, int, 0400);
@@ -262,3 +263,7 @@ MODULE_PARM_DESC(enable_gvt,
 module_param_named(enable_dithering, i915.enable_dithering, int, 0644);
 MODULE_PARM_DESC(enable_dithering,
 	"Enable dithering (-1=auto [default], 0=force off on all outputs, 1=force on on all outputs)");
+
+module_param_named(enable_hw_color_correction, i915.enable_hw_color_correction, bool, 0644);
+MODULE_PARM_DESC(enable_hw_color_correction,
+	"Enable hardware color correction like gamma luts and csc (default: true)");
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
index 7e365cd4fc91..f5c9163d2675 100644
--- a/drivers/gpu/drm/i915/i915_params.h
+++ b/drivers/gpu/drm/i915/i915_params.h
@@ -69,7 +69,8 @@
 	func(bool, nuclear_pageflip); \
 	func(bool, enable_dp_mst); \
 	func(bool, enable_dpcd_backlight); \
-	func(bool, enable_gvt)
+	func(bool, enable_gvt); \
+	func(bool, enable_hw_color_correction)
 
 #define MEMBER(T, member) T member
 struct i915_params {
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bea471a96820..1e1b157353a9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3184,13 +3184,17 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
 	unsigned int rotation = plane_state->base.rotation;
 	u32 dspcntr;
 
-	dspcntr = DISPLAY_PLANE_ENABLE | DISPPLANE_GAMMA_ENABLE;
+	dspcntr = DISPLAY_PLANE_ENABLE;
+
+	if (i915.enable_hw_color_correction)
+		dspcntr |= DISPPLANE_GAMMA_ENABLE;
 
 	if (IS_G4X(dev_priv) || IS_GEN5(dev_priv) ||
 	    IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
 		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
-	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+	if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
+	    i915.enable_hw_color_correction)
 		dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
 
 	if (INTEL_GEN(dev_priv) < 4)
@@ -3514,7 +3518,8 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
 
 	plane_ctl = PLANE_CTL_ENABLE;
 
-	if (!IS_GEMINILAKE(dev_priv) && !IS_CANNONLAKE(dev_priv)) {
+	if (!IS_GEMINILAKE(dev_priv) && !IS_CANNONLAKE(dev_priv) &&
+	    i915.enable_hw_color_correction) {
 		plane_ctl |=
 			PLANE_CTL_PIPE_GAMMA_ENABLE |
 			PLANE_CTL_PIPE_CSC_ENABLE |
@@ -3571,7 +3576,8 @@ static void skylake_update_primary_plane(struct intel_plane *plane,
 
 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
-	if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) {
+	if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
+	    i915.enable_hw_color_correction) {
 		I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id),
 			      PLANE_COLOR_PIPE_GAMMA_ENABLE |
 			      PLANE_COLOR_PIPE_CSC_ENABLE |
@@ -9431,7 +9437,7 @@ static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
 	const struct drm_framebuffer *fb = plane_state->base.fb;
 
 	return CURSOR_ENABLE |
-		CURSOR_GAMMA_ENABLE |
+		(i915.enable_hw_color_correction ? CURSOR_GAMMA_ENABLE : 0) |
 		CURSOR_FORMAT_ARGB |
 		CURSOR_STRIDE(fb->pitches[0]);
 }
@@ -9544,12 +9550,14 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
 	struct drm_i915_private *dev_priv =
 		to_i915(plane_state->base.plane->dev);
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
-	u32 cntl;
+	u32 cntl = 0;
 
-	cntl = MCURSOR_GAMMA_ENABLE;
+	if (i915.enable_hw_color_correction) {
+		cntl = MCURSOR_GAMMA_ENABLE;
 
-	if (HAS_DDI(dev_priv))
-		cntl |= CURSOR_PIPE_CSC_ENABLE;
+		if (HAS_DDI(dev_priv))
+			cntl |= CURSOR_PIPE_CSC_ENABLE;
+	}
 
 	cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
 
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 524933b01483..6e6a7377a7bc 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -258,7 +258,8 @@ skl_update_plane(struct intel_plane *plane,
 
 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
-	if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) {
+	if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
+	    i915.enable_hw_color_correction) {
 		I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id),
 			      PLANE_COLOR_PIPE_GAMMA_ENABLE |
 			      PLANE_COLOR_PIPE_CSC_ENABLE |
@@ -371,7 +372,10 @@ static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 	u32 sprctl;
 
-	sprctl = SP_ENABLE | SP_GAMMA_ENABLE;
+	sprctl = SP_ENABLE;
+
+	if (i915.enable_hw_color_correction)
+		sprctl |= SP_GAMMA_ENABLE;
 
 	switch (fb->format->format) {
 	case DRM_FORMAT_YUYV:
@@ -511,12 +515,16 @@ static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 	u32 sprctl;
 
-	sprctl = SPRITE_ENABLE | SPRITE_GAMMA_ENABLE;
+	sprctl = SPRITE_ENABLE;
+
+	if (i915.enable_hw_color_correction)
+		sprctl |= SPRITE_GAMMA_ENABLE;
 
 	if (IS_IVYBRIDGE(dev_priv))
 		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
 
-	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+	if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
+	    i915.enable_hw_color_correction)
 		sprctl |= SPRITE_PIPE_CSC_ENABLE;
 
 	switch (fb->format->format) {
@@ -651,7 +659,10 @@ static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 	u32 dvscntr;
 
-	dvscntr = DVS_ENABLE | DVS_GAMMA_ENABLE;
+	dvscntr = DVS_ENABLE;
+
+	if (i915.enable_hw_color_correction)
+		dvscntr |= DVS_GAMMA_ENABLE;
 
 	if (IS_GEN6(dev_priv))
 		dvscntr |= DVS_TRICKLE_FEED_DISABLE;
-- 
2.13.0.rc1.294.g07d810a77f



More information about the dri-devel mailing list