aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2013-01-18 12:11:38 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-02-19 18:21:49 -0500
commit86d3efce2c37d3fb98f75f56f21e6ab75c745bb6 (patch)
tree3af18f73d13ca0a380dd4c9b71f58f447a4d14da
parentac4199e0f047546aa40172785e26c82b54bbe811 (diff)
drm/i915: Implement pipe CSC based limited range RGB output
HSW no longer has the PIPECONF bit for limited range RGB output. Instead the pipe CSC unit must be used to perform that task. 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 sent through the pipe CSC unit. For simplicity send the plane data through the pipe CSC unit always, and in case full range output is requested, the pipe CSC unit is set up with an identity transform to pass the plane data through unchanged. I've been told by some hardware people that the use of the pipe CSC unit shouldn't result in any measurable increase in power consumption numbers. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h52
-rw-r--r--drivers/gpu/drm/i915/intel_display.c71
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c3
3 files changed, 124 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7e77396a154e..527b664d3434 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2949,6 +2949,7 @@
2949#define CURSOR_ENABLE 0x80000000 2949#define CURSOR_ENABLE 0x80000000
2950#define CURSOR_GAMMA_ENABLE 0x40000000 2950#define CURSOR_GAMMA_ENABLE 0x40000000
2951#define CURSOR_STRIDE_MASK 0x30000000 2951#define CURSOR_STRIDE_MASK 0x30000000
2952#define CURSOR_PIPE_CSC_ENABLE (1<<24)
2952#define CURSOR_FORMAT_SHIFT 24 2953#define CURSOR_FORMAT_SHIFT 24
2953#define CURSOR_FORMAT_MASK (0x07 << CURSOR_FORMAT_SHIFT) 2954#define CURSOR_FORMAT_MASK (0x07 << CURSOR_FORMAT_SHIFT)
2954#define CURSOR_FORMAT_2C (0x00 << CURSOR_FORMAT_SHIFT) 2955#define CURSOR_FORMAT_2C (0x00 << CURSOR_FORMAT_SHIFT)
@@ -3010,6 +3011,7 @@
3010#define DISPPLANE_RGBA888 (0xf<<26) 3011#define DISPPLANE_RGBA888 (0xf<<26)
3011#define DISPPLANE_STEREO_ENABLE (1<<25) 3012#define DISPPLANE_STEREO_ENABLE (1<<25)
3012#define DISPPLANE_STEREO_DISABLE 0 3013#define DISPPLANE_STEREO_DISABLE 0
3014#define DISPPLANE_PIPE_CSC_ENABLE (1<<24)
3013#define DISPPLANE_SEL_PIPE_SHIFT 24 3015#define DISPPLANE_SEL_PIPE_SHIFT 24
3014#define DISPPLANE_SEL_PIPE_MASK (3<<DISPPLANE_SEL_PIPE_SHIFT) 3016#define DISPPLANE_SEL_PIPE_MASK (3<<DISPPLANE_SEL_PIPE_SHIFT)
3015#define DISPPLANE_SEL_PIPE_A 0 3017#define DISPPLANE_SEL_PIPE_A 0
@@ -3098,6 +3100,7 @@
3098#define DVS_FORMAT_RGBX101010 (1<<25) 3100#define DVS_FORMAT_RGBX101010 (1<<25)
3099#define DVS_FORMAT_RGBX888 (2<<25) 3101#define DVS_FORMAT_RGBX888 (2<<25)
3100#define DVS_FORMAT_RGBX161616 (3<<25) 3102#define DVS_FORMAT_RGBX161616 (3<<25)
3103#define DVS_PIPE_CSC_ENABLE (1<<24)
3101#define DVS_SOURCE_KEY (1<<22) 3104#define DVS_SOURCE_KEY (1<<22)
3102#define DVS_RGB_ORDER_XBGR (1<<20) 3105#define DVS_RGB_ORDER_XBGR (1<<20)
3103#define DVS_YUV_BYTE_ORDER_MASK (3<<16) 3106#define DVS_YUV_BYTE_ORDER_MASK (3<<16)
@@ -3165,7 +3168,7 @@
3165#define SPRITE_FORMAT_RGBX161616 (3<<25) 3168#define SPRITE_FORMAT_RGBX161616 (3<<25)
3166#define SPRITE_FORMAT_YUV444 (4<<25) 3169#define SPRITE_FORMAT_YUV444 (4<<25)
3167#define SPRITE_FORMAT_XR_BGR101010 (5<<25) /* Extended range */ 3170#define SPRITE_FORMAT_XR_BGR101010 (5<<25) /* Extended range */
3168#define SPRITE_CSC_ENABLE (1<<24) 3171#define SPRITE_PIPE_CSC_ENABLE (1<<24)
3169#define SPRITE_SOURCE_KEY (1<<22) 3172#define SPRITE_SOURCE_KEY (1<<22)
3170#define SPRITE_RGB_ORDER_RGBX (1<<20) /* only for 888 and 161616 */ 3173#define SPRITE_RGB_ORDER_RGBX (1<<20) /* only for 888 and 161616 */
3171#define SPRITE_YUV_TO_RGB_CSC_DISABLE (1<<19) 3174#define SPRITE_YUV_TO_RGB_CSC_DISABLE (1<<19)
@@ -4645,4 +4648,51 @@
4645#define WM_DBG_DISALLOW_MAXFIFO (1<<1) 4648#define WM_DBG_DISALLOW_MAXFIFO (1<<1)
4646#define WM_DBG_DISALLOW_SPRITE (1<<2) 4649#define WM_DBG_DISALLOW_SPRITE (1<<2)
4647 4650
4651/* pipe CSC */
4652#define _PIPE_A_CSC_COEFF_RY_GY 0x49010
4653#define _PIPE_A_CSC_COEFF_BY 0x49014
4654#define _PIPE_A_CSC_COEFF_RU_GU 0x49018
4655#define _PIPE_A_CSC_COEFF_BU 0x4901c
4656#define _PIPE_A_CSC_COEFF_RV_GV 0x49020
4657#define _PIPE_A_CSC_COEFF_BV 0x49024
4658#define _PIPE_A_CSC_MODE 0x49028
4659#define _PIPE_A_CSC_PREOFF_HI 0x49030
4660#define _PIPE_A_CSC_PREOFF_ME 0x49034
4661#define _PIPE_A_CSC_PREOFF_LO 0x49038
4662#define _PIPE_A_CSC_POSTOFF_HI 0x49040
4663#define _PIPE_A_CSC_POSTOFF_ME 0x49044
4664#define _PIPE_A_CSC_POSTOFF_LO 0x49048
4665
4666#define _PIPE_B_CSC_COEFF_RY_GY 0x49110
4667#define _PIPE_B_CSC_COEFF_BY 0x49114
4668#define _PIPE_B_CSC_COEFF_RU_GU 0x49118
4669#define _PIPE_B_CSC_COEFF_BU 0x4911c
4670#define _PIPE_B_CSC_COEFF_RV_GV 0x49120
4671#define _PIPE_B_CSC_COEFF_BV 0x49124
4672#define _PIPE_B_CSC_MODE 0x49128
4673#define _PIPE_B_CSC_PREOFF_HI 0x49130
4674#define _PIPE_B_CSC_PREOFF_ME 0x49134
4675#define _PIPE_B_CSC_PREOFF_LO 0x49138
4676#define _PIPE_B_CSC_POSTOFF_HI 0x49140
4677#define _PIPE_B_CSC_POSTOFF_ME 0x49144
4678#define _PIPE_B_CSC_POSTOFF_LO 0x49148
4679
4680#define CSC_BLACK_SCREEN_OFFSET (1 << 2)
4681#define CSC_POSITION_BEFORE_GAMMA (1 << 1)
4682#define CSC_MODE_YUV_TO_RGB (1 << 0)
4683
4684#define PIPE_CSC_COEFF_RY_GY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RY_GY, _PIPE_B_CSC_COEFF_RY_GY)
4685#define PIPE_CSC_COEFF_BY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BY, _PIPE_B_CSC_COEFF_BY)
4686#define PIPE_CSC_COEFF_RU_GU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RU_GU, _PIPE_B_CSC_COEFF_RU_GU)
4687#define PIPE_CSC_COEFF_BU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BU, _PIPE_B_CSC_COEFF_BU)
4688#define PIPE_CSC_COEFF_RV_GV(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RV_GV, _PIPE_B_CSC_COEFF_RV_GV)
4689#define PIPE_CSC_COEFF_BV(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BV, _PIPE_B_CSC_COEFF_BV)
4690#define PIPE_CSC_MODE(pipe) _PIPE(pipe, _PIPE_A_CSC_MODE, _PIPE_B_CSC_MODE)
4691#define PIPE_CSC_PREOFF_HI(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_HI, _PIPE_B_CSC_PREOFF_HI)
4692#define PIPE_CSC_PREOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_ME, _PIPE_B_CSC_PREOFF_ME)
4693#define PIPE_CSC_PREOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_LO, _PIPE_B_CSC_PREOFF_LO)
4694#define PIPE_CSC_POSTOFF_HI(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_HI, _PIPE_B_CSC_POSTOFF_HI)
4695#define PIPE_CSC_POSTOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME)
4696#define PIPE_CSC_POSTOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO)
4697
4648#endif /* _I915_REG_H_ */ 4698#endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ba1d9131a5d6..6eb3882ba9bf 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5126,6 +5126,71 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
5126 POSTING_READ(PIPECONF(pipe)); 5126 POSTING_READ(PIPECONF(pipe));
5127} 5127}
5128 5128
5129/*
5130 * Set up the pipe CSC unit.
5131 *
5132 * Currently only full range RGB to limited range RGB conversion
5133 * is supported, but eventually this should handle various
5134 * RGB<->YCbCr scenarios as well.
5135 */
5136static void intel_set_pipe_csc(struct drm_crtc *crtc,
5137 const struct drm_display_mode *adjusted_mode)
5138{
5139 struct drm_device *dev = crtc->dev;
5140 struct drm_i915_private *dev_priv = dev->dev_private;
5141 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
5142 int pipe = intel_crtc->pipe;
5143 uint16_t coeff = 0x7800; /* 1.0 */
5144
5145 /*
5146 * TODO: Check what kind of values actually come out of the pipe
5147 * with these coeff/postoff values and adjust to get the best
5148 * accuracy. Perhaps we even need to take the bpc value into
5149 * consideration.
5150 */
5151
5152 if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
5153 coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
5154
5155 /*
5156 * GY/GU and RY/RU should be the other way around according
5157 * to BSpec, but reality doesn't agree. Just set them up in
5158 * a way that results in the correct picture.
5159 */
5160 I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16);
5161 I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0);
5162
5163 I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff);
5164 I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0);
5165
5166 I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0);
5167 I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16);
5168
5169 I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
5170 I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
5171 I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
5172
5173 if (INTEL_INFO(dev)->gen > 6) {
5174 uint16_t postoff = 0;
5175
5176 if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
5177 postoff = (16 * (1 << 13) / 255) & 0x1fff;
5178
5179 I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
5180 I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
5181 I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff);
5182
5183 I915_WRITE(PIPE_CSC_MODE(pipe), 0);
5184 } else {
5185 uint32_t mode = CSC_MODE_YUV_TO_RGB;
5186
5187 if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
5188 mode |= CSC_BLACK_SCREEN_OFFSET;
5189
5190 I915_WRITE(PIPE_CSC_MODE(pipe), mode);
5191 }
5192}
5193
5129static void haswell_set_pipeconf(struct drm_crtc *crtc, 5194static void haswell_set_pipeconf(struct drm_crtc *crtc,
5130 struct drm_display_mode *adjusted_mode, 5195 struct drm_display_mode *adjusted_mode,
5131 bool dither) 5196 bool dither)
@@ -5714,8 +5779,10 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
5714 5779
5715 haswell_set_pipeconf(crtc, adjusted_mode, dither); 5780 haswell_set_pipeconf(crtc, adjusted_mode, dither);
5716 5781
5782 intel_set_pipe_csc(crtc, adjusted_mode);
5783
5717 /* Set up the display plane register */ 5784 /* Set up the display plane register */
5718 I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE); 5785 I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | DISPPLANE_PIPE_CSC_ENABLE);
5719 POSTING_READ(DSPCNTR(plane)); 5786 POSTING_READ(DSPCNTR(plane));
5720 5787
5721 ret = intel_pipe_set_base(crtc, x, y, fb); 5788 ret = intel_pipe_set_base(crtc, x, y, fb);
@@ -6120,6 +6187,8 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
6120 cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); 6187 cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
6121 cntl |= CURSOR_MODE_DISABLE; 6188 cntl |= CURSOR_MODE_DISABLE;
6122 } 6189 }
6190 if (IS_HASWELL(dev))
6191 cntl |= CURSOR_PIPE_CSC_ENABLE;
6123 I915_WRITE(CURCNTR_IVB(pipe), cntl); 6192 I915_WRITE(CURCNTR_IVB(pipe), cntl);
6124 6193
6125 intel_crtc->cursor_visible = visible; 6194 intel_crtc->cursor_visible = visible;
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 03cfd62d17e2..d086e48a831a 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -90,6 +90,9 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
90 sprctl |= SPRITE_TRICKLE_FEED_DISABLE; 90 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
91 sprctl |= SPRITE_ENABLE; 91 sprctl |= SPRITE_ENABLE;
92 92
93 if (IS_HASWELL(dev))
94 sprctl |= SPRITE_PIPE_CSC_ENABLE;
95
93 /* Sizes are 0 based */ 96 /* Sizes are 0 based */
94 src_w--; 97 src_w--;
95 src_h--; 98 src_h--;