From: Ville Syrjälä <[email protected]>

A quick prototype at using the pipe CSC unit to perform the
full->limited range RGB output conversion.

The CSC pre offset are set to 0, since the incoming data is full
[0:255] range RGB, the coefficients are programmed to compress the
data into [0:219] range, and then we use either the CSC_MODE black
screen offset bit, or the CSC post offsets to shift the data to
the correct [16:235] range.

Also have to change the confiuration of all planes so that the
data is always sent through the pipe CSC unit.

TODO:
 - Find out if we really need someting like this on HSW?
 - Power cost of always sending plane data through the pipe CSC unit?
 - Clean it up and limit it to just the platforms that need it

Signed-off-by: Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/i915_reg.h      |   52 +++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_display.c |   80 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_sprite.c  |    8 +++
 3 files changed, 139 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index a653b64..a2cc95e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2942,6 +2942,7 @@
 #define   CURSOR_ENABLE                0x80000000
 #define   CURSOR_GAMMA_ENABLE  0x40000000
 #define   CURSOR_STRIDE_MASK   0x30000000
+#define   CURSOR_PIPE_CSC_ENABLE (1<<24)
 #define   CURSOR_FORMAT_SHIFT  24
 #define   CURSOR_FORMAT_MASK   (0x07 << CURSOR_FORMAT_SHIFT)
 #define   CURSOR_FORMAT_2C     (0x00 << CURSOR_FORMAT_SHIFT)
@@ -3003,6 +3004,7 @@
 #define   DISPPLANE_RGBA888                    (0xf<<26)
 #define   DISPPLANE_STEREO_ENABLE              (1<<25)
 #define   DISPPLANE_STEREO_DISABLE             0
+#define   DISPPLANE_PIPE_CSC_ENABLE            (1<<24)
 #define   DISPPLANE_SEL_PIPE_SHIFT             24
 #define   DISPPLANE_SEL_PIPE_MASK              (3<<DISPPLANE_SEL_PIPE_SHIFT)
 #define   DISPPLANE_SEL_PIPE_A                 0
@@ -3091,6 +3093,7 @@
 #define   DVS_FORMAT_RGBX101010        (1<<25)
 #define   DVS_FORMAT_RGBX888   (2<<25)
 #define   DVS_FORMAT_RGBX161616        (3<<25)
+#define   DVS_PIPE_CSC_ENABLE   (1<<24)
 #define   DVS_SOURCE_KEY       (1<<22)
 #define   DVS_RGB_ORDER_XBGR   (1<<20)
 #define   DVS_YUV_BYTE_ORDER_MASK (3<<16)
@@ -3158,7 +3161,7 @@
 #define   SPRITE_FORMAT_RGBX161616     (3<<25)
 #define   SPRITE_FORMAT_YUV444         (4<<25)
 #define   SPRITE_FORMAT_XR_BGR101010   (5<<25) /* Extended range */
-#define   SPRITE_CSC_ENABLE            (1<<24)
+#define   SPRITE_PIPE_CSC_ENABLE       (1<<24)
 #define   SPRITE_SOURCE_KEY            (1<<22)
 #define   SPRITE_RGB_ORDER_RGBX                (1<<20) /* only for 888 and 
161616 */
 #define   SPRITE_YUV_TO_RGB_CSC_DISABLE        (1<<19)
@@ -4633,4 +4636,51 @@
 #define  WM_DBG_DISALLOW_MAXFIFO       (1<<1)
 #define  WM_DBG_DISALLOW_SPRITE                (1<<2)
 
+/* pipe CSC */
+#define _PIPE_A_CSC_COEFF_RY_GY        0x49010
+#define _PIPE_A_CSC_COEFF_BY   0x49014
+#define _PIPE_A_CSC_COEFF_RU_GU        0x49018
+#define _PIPE_A_CSC_COEFF_BU   0x4901c
+#define _PIPE_A_CSC_COEFF_RV_GV        0x49020
+#define _PIPE_A_CSC_COEFF_BV   0x49024
+#define _PIPE_A_CSC_MODE       0x49028
+#define _PIPE_A_CSC_PREOFF_HI  0x49030
+#define _PIPE_A_CSC_PREOFF_ME  0x49034
+#define _PIPE_A_CSC_PREOFF_LO  0x49038
+#define _PIPE_A_CSC_POSTOFF_HI 0x49040
+#define _PIPE_A_CSC_POSTOFF_ME 0x49044
+#define _PIPE_A_CSC_POSTOFF_LO 0x49048
+
+#define _PIPE_B_CSC_COEFF_RY_GY        0x49110
+#define _PIPE_B_CSC_COEFF_BY   0x49114
+#define _PIPE_B_CSC_COEFF_RU_GU        0x49118
+#define _PIPE_B_CSC_COEFF_BU   0x4911c
+#define _PIPE_B_CSC_COEFF_RV_GV        0x49120
+#define _PIPE_B_CSC_COEFF_BV   0x49124
+#define _PIPE_B_CSC_MODE       0x49128
+#define _PIPE_B_CSC_PREOFF_HI  0x49130
+#define _PIPE_B_CSC_PREOFF_ME  0x49134
+#define _PIPE_B_CSC_PREOFF_LO  0x49138
+#define _PIPE_B_CSC_POSTOFF_HI 0x49140
+#define _PIPE_B_CSC_POSTOFF_ME 0x49144
+#define _PIPE_B_CSC_POSTOFF_LO 0x49148
+
+#define CSC_BLACK_SCREEN_OFFSET (1 << 2)
+#define CSC_POSITION_BEFORE_GAMMA (1 << 1)
+#define CSC_MODE_YUV_TO_RGB (1 << 0)
+
+#define PIPE_CSC_COEFF_RY_GY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RY_GY, 
_PIPE_B_CSC_COEFF_RY_GY)
+#define PIPE_CSC_COEFF_BY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BY, 
_PIPE_B_CSC_COEFF_BY)
+#define PIPE_CSC_COEFF_RU_GU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RU_GU, 
_PIPE_B_CSC_COEFF_RU_GU)
+#define PIPE_CSC_COEFF_BU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BU, 
_PIPE_B_CSC_COEFF_BU)
+#define PIPE_CSC_COEFF_RV_GV(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RV_GV, 
_PIPE_B_CSC_COEFF_RV_GV)
+#define PIPE_CSC_COEFF_BV(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BV, 
_PIPE_B_CSC_COEFF_BV)
+#define PIPE_CSC_MODE(pipe) _PIPE(pipe, _PIPE_A_CSC_MODE, _PIPE_B_CSC_MODE)
+#define PIPE_CSC_PREOFF_HI(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_HI, 
_PIPE_B_CSC_PREOFF_HI)
+#define PIPE_CSC_PREOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_ME, 
_PIPE_B_CSC_PREOFF_ME)
+#define PIPE_CSC_PREOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_LO, 
_PIPE_B_CSC_PREOFF_LO)
+#define PIPE_CSC_POSTOFF_HI(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_HI, 
_PIPE_B_CSC_POSTOFF_HI)
+#define PIPE_CSC_POSTOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, 
_PIPE_B_CSC_POSTOFF_ME)
+#define PIPE_CSC_POSTOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, 
_PIPE_B_CSC_POSTOFF_LO)
+
 #endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index a409a51..9821e9b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5093,15 +5093,72 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
        else
                val |= PIPECONF_PROGRESSIVE;
 
+#if 1
+       val &= ~PIPECONF_COLOR_RANGE_SELECT;
+#else
        if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
                val |= PIPECONF_COLOR_RANGE_SELECT;
        else
                val &= ~PIPECONF_COLOR_RANGE_SELECT;
+#endif
 
        I915_WRITE(PIPECONF(pipe), val);
        POSTING_READ(PIPECONF(pipe));
 }
 
+static void intel_set_pipe_csc(struct drm_crtc *crtc,
+                              const struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       uint16_t coeff = 0x7800; /* 1.0 */
+
+       if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
+               /* FIXME round up perhaps? */
+               coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
+
+       /*
+        * GY/GU and RY/RU should be the other way around according
+        * to BSpec, but reality doesn't agree. Just set them up in
+        * a way that results in the correct picture.
+        */
+       I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16);
+       I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0);
+
+       I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff);
+       I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0);
+
+       I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0);
+       I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16);
+
+       I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
+       I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
+       I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
+
+       if (INTEL_INFO(dev)->gen > 6) {
+               uint16_t postoff = 0;
+
+               if (adjusted_mode->private_flags & 
INTEL_MODE_LIMITED_COLOR_RANGE)
+                       /* FIXME round up perhaps? */
+                       postoff = (16 * (1 << 13) / 255) & 0x1fff;
+
+               I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
+               I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
+               I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff);
+
+               I915_WRITE(PIPE_CSC_MODE(pipe), 0);
+       } else {
+               uint32_t mode = CSC_MODE_YUV_TO_RGB;
+
+               if (adjusted_mode->private_flags & 
INTEL_MODE_LIMITED_COLOR_RANGE)
+                       mode |= CSC_BLACK_SCREEN_OFFSET;
+
+               I915_WRITE(PIPE_CSC_MODE(pipe), mode);
+       }
+}
+
 static void haswell_set_pipeconf(struct drm_crtc *crtc,
                                 struct drm_display_mode *adjusted_mode,
                                 bool dither)
@@ -5577,10 +5634,18 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 
        ironlake_set_pipeconf(crtc, adjusted_mode, dither);
 
+#if 1
+       intel_set_pipe_csc(crtc, adjusted_mode);
+#endif
+
        intel_wait_for_vblank(dev, pipe);
 
        /* Set up the display plane register */
+#if 1
+       I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | 
DISPPLANE_PIPE_CSC_ENABLE);
+#else
        I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
+#endif
        POSTING_READ(DSPCNTR(plane));
 
        ret = intel_pipe_set_base(crtc, x, y, fb);
@@ -5666,8 +5731,16 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 
        haswell_set_pipeconf(crtc, adjusted_mode, dither);
 
+#if 1
+       intel_set_pipe_csc(crtc, adjusted_mode);
+#endif
+
        /* Set up the display plane register */
+#if 1
+       I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | 
DISPPLANE_PIPE_CSC_ENABLE);
+#else
        I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
+#endif
        POSTING_READ(DSPCNTR(plane));
 
        ret = intel_pipe_set_base(crtc, x, y, fb);
@@ -6040,6 +6113,10 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, 
u32 base)
                        cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
                        cntl |= CURSOR_MODE_DISABLE;
                }
+#if 1
+               if (INTEL_INFO(dev)->gen >= 5)
+                       cntl |= CURSOR_PIPE_CSC_ENABLE;
+#endif
                I915_WRITE(CURCNTR(pipe), cntl);
 
                intel_crtc->cursor_visible = visible;
@@ -6065,6 +6142,9 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 
base)
                        cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
                        cntl |= CURSOR_MODE_DISABLE;
                }
+#if 1
+               cntl |= CURSOR_PIPE_CSC_ENABLE;
+#endif
                I915_WRITE(CURCNTR_IVB(pipe), cntl);
 
                intel_crtc->cursor_visible = visible;
diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
b/drivers/gpu/drm/i915/intel_sprite.c
index a5ab0f1..da34bbf 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -89,6 +89,10 @@ ivb_update_plane(struct drm_plane *plane, struct 
drm_framebuffer *fb,
        sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
        sprctl |= SPRITE_ENABLE;
 
+#if 1
+       sprctl |= SPRITE_PIPE_CSC_ENABLE;
+#endif
+
        /* Sizes are 0 based */
        src_w--;
        src_h--;
@@ -271,6 +275,10 @@ ilk_update_plane(struct drm_plane *plane, struct 
drm_framebuffer *fb,
                dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
        dvscntr |= DVS_ENABLE;
 
+#if 1
+       dvscntr |= DVS_PIPE_CSC_ENABLE;
+#endif
+
        /* Sizes are 0 based */
        src_w--;
        src_h--;
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to