]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/i915: Program plane gamma ramps
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Wed, 3 Jul 2019 20:08:21 +0000 (23:08 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Fri, 5 Jul 2019 10:11:04 +0000 (13:11 +0300)
All sprite planes have a progammable gamma ramp. Set it up with
a linear ramp on all platforms. This actually matches the reset
value but soon we'll want to reprogram this ramp on some machines,
so let's just set it up across the board.

Note that on pre-IVB the hardware bypasses the gamma unit
unless a YCbCr pixel format is used.

v2: Add parens around << in ilk_linear_gamma()
    Skip gamma programming for RGB on pre-IVB
    s/DVSGAMC/DVSGAMC_G4X/

Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190703200824.5971-4-ville.syrjala@linux.intel.com
drivers/gpu/drm/i915/display/intel_sprite.c
drivers/gpu/drm/i915/i915_reg.h

index c7314617424aba500c11b09ef5998a792683b01f..dc26d84b1b618b8a1af303b9732a6bb7b0fd3c29 100644 (file)
@@ -683,6 +683,16 @@ skl_plane_get_hw_state(struct intel_plane *plane,
        return ret;
 }
 
+static void i9xx_plane_linear_gamma(u16 gamma[8])
+{
+       /* The points are not evenly spaced. */
+       static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
+       int i;
+
+       for (i = 0; i < 8; i++)
+               gamma[i] = (in[i] << 8) / 32;
+}
+
 static void
 chv_update_csc(const struct intel_plane_state *plane_state)
 {
@@ -858,6 +868,31 @@ static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
        return sprctl;
 }
 
+static void vlv_update_gamma(const struct intel_plane_state *plane_state)
+{
+       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       enum pipe pipe = plane->pipe;
+       enum plane_id plane_id = plane->id;
+       u16 gamma[8];
+       int i;
+
+       /* Seems RGB data bypasses the gamma always */
+       if (!fb->format->is_yuv)
+               return;
+
+       i9xx_plane_linear_gamma(gamma);
+
+       /* FIXME these register are single buffered :( */
+       /* The two end points are implicit (0.0 and 1.0) */
+       for (i = 1; i < 8 - 1; i++)
+               I915_WRITE_FW(SPGAMC(pipe, plane_id, i - 1),
+                             gamma[i] << 16 |
+                             gamma[i] << 8 |
+                             gamma[i]);
+}
+
 static void
 vlv_update_plane(struct intel_plane *plane,
                 const struct intel_crtc_state *crtc_state,
@@ -916,6 +951,7 @@ vlv_update_plane(struct intel_plane *plane,
                      intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
 
        vlv_update_clrc(plane_state);
+       vlv_update_gamma(plane_state);
 
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
@@ -1035,6 +1071,45 @@ static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
        return sprctl;
 }
 
+static void ivb_sprite_linear_gamma(u16 gamma[18])
+{
+       int i;
+
+       for (i = 0; i < 17; i++)
+               gamma[i] = (i << 10) / 16;
+
+       gamma[i] = 3 << 10;
+       i++;
+}
+
+static void ivb_update_gamma(const struct intel_plane_state *plane_state)
+{
+       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum pipe pipe = plane->pipe;
+       u16 gamma[18];
+       int i;
+
+       ivb_sprite_linear_gamma(gamma);
+
+       /* FIXME these register are single buffered :( */
+       for (i = 0; i < 16; i++)
+               I915_WRITE_FW(SPRGAMC(pipe, i),
+                             gamma[i] << 20 |
+                             gamma[i] << 10 |
+                             gamma[i]);
+
+       I915_WRITE_FW(SPRGAMC16(pipe, 0), gamma[i]);
+       I915_WRITE_FW(SPRGAMC16(pipe, 1), gamma[i]);
+       I915_WRITE_FW(SPRGAMC16(pipe, 2), gamma[i]);
+       i++;
+
+       I915_WRITE_FW(SPRGAMC17(pipe, 0), gamma[i]);
+       I915_WRITE_FW(SPRGAMC17(pipe, 1), gamma[i]);
+       I915_WRITE_FW(SPRGAMC17(pipe, 2), gamma[i]);
+       i++;
+}
+
 static void
 ivb_update_plane(struct intel_plane *plane,
                 const struct intel_crtc_state *crtc_state,
@@ -1101,6 +1176,8 @@ ivb_update_plane(struct intel_plane *plane,
        I915_WRITE_FW(SPRSURF(pipe),
                      intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
 
+       ivb_update_gamma(plane_state);
+
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
@@ -1226,6 +1303,66 @@ static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
        return dvscntr;
 }
 
+static void g4x_update_gamma(const struct intel_plane_state *plane_state)
+{
+       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       enum pipe pipe = plane->pipe;
+       u16 gamma[8];
+       int i;
+
+       /* Seems RGB data bypasses the gamma always */
+       if (!fb->format->is_yuv)
+               return;
+
+       i9xx_plane_linear_gamma(gamma);
+
+       /* FIXME these register are single buffered :( */
+       /* The two end points are implicit (0.0 and 1.0) */
+       for (i = 1; i < 8 - 1; i++)
+               I915_WRITE_FW(DVSGAMC_G4X(pipe, i - 1),
+                             gamma[i] << 16 |
+                             gamma[i] << 8 |
+                             gamma[i]);
+}
+
+static void ilk_sprite_linear_gamma(u16 gamma[17])
+{
+       int i;
+
+       for (i = 0; i < 17; i++)
+               gamma[i] = (i << 10) / 16;
+}
+
+static void ilk_update_gamma(const struct intel_plane_state *plane_state)
+{
+       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       enum pipe pipe = plane->pipe;
+       u16 gamma[17];
+       int i;
+
+       /* Seems RGB data bypasses the gamma always */
+       if (!fb->format->is_yuv)
+               return;
+
+       ilk_sprite_linear_gamma(gamma);
+
+       /* FIXME these register are single buffered :( */
+       for (i = 0; i < 16; i++)
+               I915_WRITE_FW(DVSGAMC_ILK(pipe, i),
+                             gamma[i] << 20 |
+                             gamma[i] << 10 |
+                             gamma[i]);
+
+       I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
+       I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
+       I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
+       i++;
+}
+
 static void
 g4x_update_plane(struct intel_plane *plane,
                 const struct intel_crtc_state *crtc_state,
@@ -1285,6 +1422,11 @@ g4x_update_plane(struct intel_plane *plane,
        I915_WRITE_FW(DVSSURF(pipe),
                      intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
 
+       if (IS_G4X(dev_priv))
+               g4x_update_gamma(plane_state);
+       else
+               ilk_update_gamma(plane_state);
+
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
index 6b3affb5a279e251bbdb0e8c717c02a25729c730..089b186097278448c223a0f313ae0cb0401c445c 100644 (file)
@@ -6292,6 +6292,7 @@ enum {
 #define _DSPATILEOFF                           0x701A4 /* 965+ only */
 #define _DSPAOFFSET                            0x701A4 /* HSW */
 #define _DSPASURFLIVE                          0x701AC
+#define _DSPAGAMC                              0x701E0
 
 #define DSPCNTR(plane)         _MMIO_PIPE2(plane, _DSPACNTR)
 #define DSPADDR(plane)         _MMIO_PIPE2(plane, _DSPAADDR)
@@ -6303,6 +6304,7 @@ enum {
 #define DSPLINOFF(plane)       DSPADDR(plane)
 #define DSPOFFSET(plane)       _MMIO_PIPE2(plane, _DSPAOFFSET)
 #define DSPSURFLIVE(plane)     _MMIO_PIPE2(plane, _DSPASURFLIVE)
+#define DSPGAMC(plane, i)      _MMIO(_PIPE2(plane, _DSPAGAMC) + (5 - (i)) * 4) /* plane C only, 6 x u0.8 */
 
 /* CHV pipe B blender and primary plane */
 #define _CHV_BLEND_A           0x60a00
@@ -6405,6 +6407,7 @@ enum {
 #define _DVSAKEYMAXVAL         0x721a0
 #define _DVSATILEOFF           0x721a4
 #define _DVSASURFLIVE          0x721ac
+#define _DVSAGAMC_G4X          0x721e0 /* g4x */
 #define _DVSASCALE             0x72204
 #define   DVS_SCALE_ENABLE     (1 << 31)
 #define   DVS_FILTER_MASK      (3 << 29)
@@ -6413,7 +6416,8 @@ enum {
 #define   DVS_FILTER_SOFTENING (2 << 29)
 #define   DVS_VERTICAL_OFFSET_HALF (1 << 28) /* must be enabled below */
 #define   DVS_VERTICAL_OFFSET_ENABLE (1 << 27)
-#define _DVSAGAMC              0x72300
+#define _DVSAGAMC_ILK          0x72300 /* ilk/snb */
+#define _DVSAGAMCMAX_ILK       0x72340 /* ilk/snb */
 
 #define _DVSBCNTR              0x73180
 #define _DVSBLINOFF            0x73184
@@ -6426,8 +6430,10 @@ enum {
 #define _DVSBKEYMAXVAL         0x731a0
 #define _DVSBTILEOFF           0x731a4
 #define _DVSBSURFLIVE          0x731ac
+#define _DVSBGAMC_G4X          0x731e0 /* g4x */
 #define _DVSBSCALE             0x73204
-#define _DVSBGAMC              0x73300
+#define _DVSBGAMC_ILK          0x73300 /* ilk/snb */
+#define _DVSBGAMCMAX_ILK       0x73340 /* ilk/snb */
 
 #define DVSCNTR(pipe) _MMIO_PIPE(pipe, _DVSACNTR, _DVSBCNTR)
 #define DVSLINOFF(pipe) _MMIO_PIPE(pipe, _DVSALINOFF, _DVSBLINOFF)
@@ -6441,6 +6447,9 @@ enum {
 #define DVSKEYVAL(pipe) _MMIO_PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL)
 #define DVSKEYMSK(pipe) _MMIO_PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK)
 #define DVSSURFLIVE(pipe) _MMIO_PIPE(pipe, _DVSASURFLIVE, _DVSBSURFLIVE)
+#define DVSGAMC_G4X(pipe, i) _MMIO(_PIPE(pipe, _DVSAGAMC_G4X, _DVSBGAMC_G4X) + (5 - (i)) * 4) /* 6 x u0.8 */
+#define DVSGAMC_ILK(pipe, i) _MMIO(_PIPE(pipe, _DVSAGAMC_ILK, _DVSBGAMC_ILK) + (i) * 4) /* 16 x u0.10 */
+#define DVSGAMCMAX_ILK(pipe, i) _MMIO(_PIPE(pipe, _DVSAGAMCMAX_ILK, _DVSBGAMCMAX_ILK) + (i) * 4) /* 3 x u1.10 */
 
 #define _SPRA_CTL              0x70280
 #define   SPRITE_ENABLE                        (1 << 31)
@@ -6488,6 +6497,8 @@ enum {
 #define   SPRITE_VERTICAL_OFFSET_HALF  (1 << 28) /* must be enabled below */
 #define   SPRITE_VERTICAL_OFFSET_ENABLE        (1 << 27)
 #define _SPRA_GAMC             0x70400
+#define _SPRA_GAMC16           0x70440
+#define _SPRA_GAMC17           0x7044c
 
 #define _SPRB_CTL              0x71280
 #define _SPRB_LINOFF           0x71284
@@ -6503,6 +6514,8 @@ enum {
 #define _SPRB_SURFLIVE         0x712ac
 #define _SPRB_SCALE            0x71304
 #define _SPRB_GAMC             0x71400
+#define _SPRB_GAMC16           0x71440
+#define _SPRB_GAMC17           0x7144c
 
 #define SPRCTL(pipe) _MMIO_PIPE(pipe, _SPRA_CTL, _SPRB_CTL)
 #define SPRLINOFF(pipe) _MMIO_PIPE(pipe, _SPRA_LINOFF, _SPRB_LINOFF)
@@ -6516,7 +6529,9 @@ enum {
 #define SPRTILEOFF(pipe) _MMIO_PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF)
 #define SPROFFSET(pipe) _MMIO_PIPE(pipe, _SPRA_OFFSET, _SPRB_OFFSET)
 #define SPRSCALE(pipe) _MMIO_PIPE(pipe, _SPRA_SCALE, _SPRB_SCALE)
-#define SPRGAMC(pipe) _MMIO_PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC)
+#define SPRGAMC(pipe, i) _MMIO(_PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC) + (i) * 4) /* 16 x u0.10 */
+#define SPRGAMC16(pipe, i) _MMIO(_PIPE(pipe, _SPRA_GAMC16, _SPRB_GAMC16) + (i) * 4) /* 3 x u1.10 */
+#define SPRGAMC17(pipe, i) _MMIO(_PIPE(pipe, _SPRA_GAMC17, _SPRB_GAMC17) + (i) * 4) /* 3 x u2.10 */
 #define SPRSURFLIVE(pipe) _MMIO_PIPE(pipe, _SPRA_SURFLIVE, _SPRB_SURFLIVE)
 
 #define _SPACNTR               (VLV_DISPLAY_BASE + 0x72180)
@@ -6559,7 +6574,7 @@ enum {
 #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 _SPAGAMC               (VLV_DISPLAY_BASE + 0x721e0)
 
 #define _SPBCNTR               (VLV_DISPLAY_BASE + 0x72280)
 #define _SPBLINOFF             (VLV_DISPLAY_BASE + 0x72284)
@@ -6574,10 +6589,12 @@ enum {
 #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 _SPBGAMC               (VLV_DISPLAY_BASE + 0x722e0)
 
+#define _VLV_SPR(pipe, plane_id, reg_a, reg_b) \
+       _PIPE((pipe) * 2 + (plane_id) - PLANE_SPRITE0, (reg_a), (reg_b))
 #define _MMIO_VLV_SPR(pipe, plane_id, reg_a, reg_b) \
-       _MMIO_PIPE((pipe) * 2 + (plane_id) - PLANE_SPRITE0, (reg_a), (reg_b))
+       _MMIO(_VLV_SPR((pipe), (plane_id), (reg_a), (reg_b)))
 
 #define SPCNTR(pipe, plane_id)         _MMIO_VLV_SPR((pipe), (plane_id), _SPACNTR, _SPBCNTR)
 #define SPLINOFF(pipe, plane_id)       _MMIO_VLV_SPR((pipe), (plane_id), _SPALINOFF, _SPBLINOFF)
@@ -6592,7 +6609,7 @@ enum {
 #define SPCONSTALPHA(pipe, plane_id)   _MMIO_VLV_SPR((pipe), (plane_id), _SPACONSTALPHA, _SPBCONSTALPHA)
 #define SPCLRC0(pipe, plane_id)                _MMIO_VLV_SPR((pipe), (plane_id), _SPACLRC0, _SPBCLRC0)
 #define SPCLRC1(pipe, plane_id)                _MMIO_VLV_SPR((pipe), (plane_id), _SPACLRC1, _SPBCLRC1)
-#define SPGAMC(pipe, plane_id)         _MMIO_VLV_SPR((pipe), (plane_id), _SPAGAMC, _SPBGAMC)
+#define SPGAMC(pipe, plane_id, i)      _MMIO(_VLV_SPR((pipe), (plane_id), _SPAGAMC, _SPBGAMC) + (5 - (i)) * 4) /* 6 x u0.10 */
 
 /*
  * CHV pipe B sprite CSC