@@ -5385,6 +5385,12 @@ enum {
#define _SPATILEOFF (VLV_DISPLAY_BASE + 0x721a4)
#define _SPACONSTALPHA (VLV_DISPLAY_BASE + 0x721a8)
#define SP_CONST_ALPHA_ENABLE (1<<31)
+#define _SPACLRC0 (VLV_DISPLAY_BASE + 0x721d0)
+#define SP_CONTRAST(x) ((x) << 18) /* u3.6 */
+#define SP_BRIGHTNESS(x) ((x) & 0xff) /* s8 */
+#define _SPACLRC1 (VLV_DISPLAY_BASE + 0x721d4)
+#define SP_SH_SIN(x) (((x) & 0x7ff) << 16) /* s4.7 */
+#define SP_SH_COS(x) (x) /* u3.7 */
#define _SPAGAMC (VLV_DISPLAY_BASE + 0x721f4)
#define _SPBCNTR (VLV_DISPLAY_BASE + 0x72280)
@@ -5398,6 +5404,8 @@ enum {
#define _SPBKEYMAXVAL (VLV_DISPLAY_BASE + 0x722a0)
#define _SPBTILEOFF (VLV_DISPLAY_BASE + 0x722a4)
#define _SPBCONSTALPHA (VLV_DISPLAY_BASE + 0x722a8)
+#define _SPBCLRC0 (VLV_DISPLAY_BASE + 0x722d0)
+#define _SPBCLRC1 (VLV_DISPLAY_BASE + 0x722d4)
#define _SPBGAMC (VLV_DISPLAY_BASE + 0x722f4)
#define SPCNTR(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPACNTR, _SPBCNTR)
@@ -5411,6 +5419,8 @@ enum {
#define SPKEYMAXVAL(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPAKEYMAXVAL, _SPBKEYMAXVAL)
#define SPTILEOFF(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPATILEOFF, _SPBTILEOFF)
#define SPCONSTALPHA(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPACONSTALPHA, _SPBCONSTALPHA)
+#define SPCLRC0(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPACLRC0, _SPBCLRC0)
+#define SPCLRC1(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPACLRC1, _SPBCLRC1)
#define SPGAMC(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPAGAMC, _SPBGAMC)
/*
@@ -325,28 +325,28 @@ chv_update_csc(struct intel_plane *intel_plane, uint32_t format)
return;
/*
- * BT.601 limited range YCbCr -> full range RGB
+ * BT.601 full range YCbCr -> full range RGB
*
- * |r| | 6537 4769 0| |cr |
- * |g| = |-3330 4769 -1605| x |y-64|
- * |b| | 0 4769 8263| |cb |
+ * |r| | 5743 4096 0| |cr|
+ * |g| = |-2925 4096 -1410| x |y |
+ * |b| | 0 4096 7258| |cb|
*
- * Cb and Cr apparently come in as signed already, so no
- * need for any offset. For Y we need to remove the offset.
+ * Cb and Cr apparently come in as signed already,
+ * and we get full range data in on account of CLRC0/1
*/
- I915_WRITE(SPCSCYGOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(-64));
+ I915_WRITE(SPCSCYGOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
I915_WRITE(SPCSCCBOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
I915_WRITE(SPCSCCROFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
- I915_WRITE(SPCSCC01(plane), SPCSC_C1(4769) | SPCSC_C0(6537));
- I915_WRITE(SPCSCC23(plane), SPCSC_C1(-3330) | SPCSC_C0(0));
- I915_WRITE(SPCSCC45(plane), SPCSC_C1(-1605) | SPCSC_C0(4769));
- I915_WRITE(SPCSCC67(plane), SPCSC_C1(4769) | SPCSC_C0(0));
- I915_WRITE(SPCSCC8(plane), SPCSC_C0(8263));
+ I915_WRITE(SPCSCC01(plane), SPCSC_C1(4096) | SPCSC_C0(5743));
+ I915_WRITE(SPCSCC23(plane), SPCSC_C1(-2925) | SPCSC_C0(0));
+ I915_WRITE(SPCSCC45(plane), SPCSC_C1(-1410) | SPCSC_C0(4096));
+ I915_WRITE(SPCSCC67(plane), SPCSC_C1(4096) | SPCSC_C0(0));
+ I915_WRITE(SPCSCC8(plane), SPCSC_C0(7258));
- I915_WRITE(SPCSCYGICLAMP(plane), SPCSC_IMAX(940) | SPCSC_IMIN(64));
- I915_WRITE(SPCSCCBICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
- I915_WRITE(SPCSCCRICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
+ I915_WRITE(SPCSCYGICLAMP(plane), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
+ I915_WRITE(SPCSCCBICLAMP(plane), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
+ I915_WRITE(SPCSCCRICLAMP(plane), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
I915_WRITE(SPCSCYGOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
I915_WRITE(SPCSCCBOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
@@ -354,6 +354,36 @@ chv_update_csc(struct intel_plane *intel_plane, uint32_t format)
}
static void
+vlv_update_clrc(struct intel_plane *intel_plane, uint32_t format)
+{
+ struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
+ enum pipe pipe = intel_plane->pipe;
+ int plane = intel_plane->plane;
+ int con, bri, sh_sin, sh_cos;
+
+ if (format_is_yuv(format)) {
+ /*
+ * expand limited range to full range.
+ * contrast is applied first, then brightness
+ */
+ con = ((255 << 7) / 219 + 1) >> 1;
+ bri = -((16 << 1) * 255 / 219 + 1) >> 1;
+ sh_sin = 0;
+ sh_cos = (((128 << 8) / 112) + 1) >> 1;
+ } else {
+ /* pass-through everything */
+ con = 1 << 6;
+ bri = 0;
+ sh_sin = 0;
+ sh_cos = 1 << 7;
+ }
+
+ /* FIXME these register are single buffered :( */
+ I915_WRITE(SPCLRC0(pipe, plane), SP_CONTRAST(con) | SP_BRIGHTNESS(bri));
+ I915_WRITE(SPCLRC1(pipe, plane), SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
+}
+
+static void
vlv_update_plane(struct drm_plane *dplane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
@@ -461,6 +491,8 @@ vlv_update_plane(struct drm_plane *dplane,
if (key->flags & I915_SET_COLORKEY_SOURCE)
sprctl |= SP_SOURCE_KEY;
+ vlv_update_clrc(intel_plane, fb->pixel_format);
+
if (IS_CHERRYVIEW(dev) && pipe == PIPE_B)
chv_update_csc(intel_plane, fb->pixel_format);