drm/i915/skl: Implement drm_plane vfuncs
authorDamien Lespiau <damien.lespiau@intel.com>
Wed, 4 Dec 2013 00:49:41 +0000 (00:49 +0000)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 24 Sep 2014 12:57:30 +0000 (14:57 +0200)
SKL Uses the same hardware for all planes now, so called "universal"
planes. Ie both the primary planes and sprite planes share the same
logic. This patch implements the drm_plane vfuncs for "sprites" ie
planes that aren't the primary plane.

v2: Couple of fixes:
  - Actually enabled the planes and fix the plane number

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_sprite.c

index c5c3ee3..bc14aaa 100644 (file)
@@ -4517,7 +4517,9 @@ enum punit_power_well {
 #define   PLANE_CTL_FORMAT_INDEXED             ( 12 << 24)
 #define   PLANE_CTL_FORMAT_RGB_565             ( 14 << 24)
 #define   PLANE_CTL_PIPE_CSC_ENABLE            (1 << 23)
-#define   PLANE_CTL_KEY_ENABLE                 (1 << 22)
+#define   PLANE_CTL_KEY_ENABLE_MASK            (0x3 << 21)
+#define   PLANE_CTL_KEY_ENABLE_SOURCE          (  1 << 21)
+#define   PLANE_CTL_KEY_ENABLE_DESTINATION     (  2 << 21)
 #define   PLANE_CTL_ORDER_BGRX                 (0 << 20)
 #define   PLANE_CTL_ORDER_RGBX                 (1 << 20)
 #define   PLANE_CTL_YUV422_ORDER_MASK          (0x3 << 16)
@@ -4552,6 +4554,12 @@ enum punit_power_well {
 #define _PLANE_OFFSET_1_A                      0x701a4
 #define _PLANE_OFFSET_2_A                      0x702a4
 #define _PLANE_OFFSET_3_A                      0x703a4
+#define _PLANE_KEYVAL_1_A                      0x70194
+#define _PLANE_KEYVAL_2_A                      0x70294
+#define _PLANE_KEYMSK_1_A                      0x70198
+#define _PLANE_KEYMSK_2_A                      0x70298
+#define _PLANE_KEYMAX_1_A                      0x701a0
+#define _PLANE_KEYMAX_2_A                      0x702a0
 
 #define _PLANE_CTL_1_B                         0x71180
 #define _PLANE_CTL_2_B                         0x71280
@@ -4608,6 +4616,27 @@ enum punit_power_well {
 #define PLANE_OFFSET(pipe, plane)      \
        _PLANE(plane, _PLANE_OFFSET_1(pipe), _PLANE_OFFSET_2(pipe))
 
+#define _PLANE_KEYVAL_1_B                      0x71194
+#define _PLANE_KEYVAL_2_B                      0x71294
+#define _PLANE_KEYVAL_1(pipe) _PIPE(pipe, _PLANE_KEYVAL_1_A, _PLANE_KEYVAL_1_B)
+#define _PLANE_KEYVAL_2(pipe) _PIPE(pipe, _PLANE_KEYVAL_2_A, _PLANE_KEYVAL_2_B)
+#define PLANE_KEYVAL(pipe, plane)      \
+       _PLANE(plane, _PLANE_KEYVAL_1(pipe), _PLANE_KEYVAL_2(pipe))
+
+#define _PLANE_KEYMSK_1_B                      0x71198
+#define _PLANE_KEYMSK_2_B                      0x71298
+#define _PLANE_KEYMSK_1(pipe) _PIPE(pipe, _PLANE_KEYMSK_1_A, _PLANE_KEYMSK_1_B)
+#define _PLANE_KEYMSK_2(pipe) _PIPE(pipe, _PLANE_KEYMSK_2_A, _PLANE_KEYMSK_2_B)
+#define PLANE_KEYMSK(pipe, plane)      \
+       _PLANE(plane, _PLANE_KEYMSK_1(pipe), _PLANE_KEYMSK_2(pipe))
+
+#define _PLANE_KEYMAX_1_B                      0x711a0
+#define _PLANE_KEYMAX_2_B                      0x712a0
+#define _PLANE_KEYMAX_1(pipe) _PIPE(pipe, _PLANE_KEYMAX_1_A, _PLANE_KEYMAX_1_B)
+#define _PLANE_KEYMAX_2(pipe) _PIPE(pipe, _PLANE_KEYMAX_2_A, _PLANE_KEYMAX_2_B)
+#define PLANE_KEYMAX(pipe, plane)      \
+       _PLANE(plane, _PLANE_KEYMAX_1(pipe), _PLANE_KEYMAX_2(pipe))
+
 /* VBIOS regs */
 #define VGACNTRL               0x71400
 # define VGA_DISP_DISABLE                      (1 << 31)
index 07a74ef..57e7190 100644 (file)
@@ -139,6 +139,184 @@ static void intel_update_primary_plane(struct intel_crtc *crtc)
 }
 
 static void
+skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
+                struct drm_framebuffer *fb,
+                struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
+                unsigned int crtc_w, unsigned int crtc_h,
+                uint32_t x, uint32_t y,
+                uint32_t src_w, uint32_t src_h)
+{
+       struct drm_device *dev = drm_plane->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_plane *intel_plane = to_intel_plane(drm_plane);
+       const int pipe = intel_plane->pipe;
+       const int plane = intel_plane->plane + 1;
+       u32 plane_ctl, stride;
+       int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+
+       plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
+
+       /* Mask out pixel format bits in case we change it */
+       plane_ctl &= ~PLANE_CTL_FORMAT_MASK;
+       plane_ctl &= ~PLANE_CTL_ORDER_RGBX;
+       plane_ctl &= ~PLANE_CTL_YUV422_ORDER_MASK;
+       plane_ctl &= ~PLANE_CTL_TILED_MASK;
+       plane_ctl &= ~PLANE_CTL_ALPHA_MASK;
+
+       /* Trickle feed has to be enabled */
+       plane_ctl &= ~PLANE_CTL_TRICKLE_FEED_DISABLE;
+
+       switch (fb->pixel_format) {
+       case DRM_FORMAT_RGB565:
+               plane_ctl |= PLANE_CTL_FORMAT_RGB_565;
+               break;
+       case DRM_FORMAT_XBGR8888:
+               plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
+               break;
+       case DRM_FORMAT_XRGB8888:
+               plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888;
+               break;
+       /*
+        * XXX: For ARBG/ABGR formats we default to expecting scanout buffers
+        * to be already pre-multiplied. We need to add a knob (or a different
+        * DRM_FORMAT) for user-space to configure that.
+        */
+       case DRM_FORMAT_ABGR8888:
+               plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888 |
+                            PLANE_CTL_ORDER_RGBX |
+                            PLANE_CTL_ALPHA_SW_PREMULTIPLY;
+               break;
+       case DRM_FORMAT_ARGB8888:
+               plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888 |
+                            PLANE_CTL_ALPHA_SW_PREMULTIPLY;
+               break;
+       case DRM_FORMAT_YUYV:
+               plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
+               break;
+       case DRM_FORMAT_YVYU:
+               plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YVYU;
+               break;
+       case DRM_FORMAT_UYVY:
+               plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY;
+               break;
+       case DRM_FORMAT_VYUY:
+               plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
+               break;
+       default:
+               BUG();
+       }
+
+       switch (obj->tiling_mode) {
+       case I915_TILING_NONE:
+               stride = fb->pitches[0] >> 6;
+               break;
+       case I915_TILING_X:
+               plane_ctl |= PLANE_CTL_TILED_X;
+               stride = fb->pitches[0] >> 9;
+               break;
+       default:
+               BUG();
+       }
+
+       plane_ctl |= PLANE_CTL_ENABLE;
+       plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
+
+       intel_update_sprite_watermarks(drm_plane, crtc, src_w, src_h,
+                                      pixel_size, true,
+                                      src_w != crtc_w || src_h != crtc_h);
+
+       /* Sizes are 0 based */
+       src_w--;
+       src_h--;
+       crtc_w--;
+       crtc_h--;
+
+       I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
+       I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
+       I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
+       I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w);
+       I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
+       I915_WRITE(PLANE_SURF(pipe, plane), i915_gem_obj_ggtt_offset(obj));
+       POSTING_READ(PLANE_SURF(pipe, plane));
+}
+
+static void
+skl_disable_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc)
+{
+       struct drm_device *dev = drm_plane->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_plane *intel_plane = to_intel_plane(drm_plane);
+       const int pipe = intel_plane->pipe;
+       const int plane = intel_plane->plane + 1;
+
+       I915_WRITE(PLANE_CTL(pipe, plane),
+                  I915_READ(PLANE_CTL(pipe, plane)) & ~PLANE_CTL_ENABLE);
+
+       /* Activate double buffered register update */
+       I915_WRITE(PLANE_CTL(pipe, plane), 0);
+       POSTING_READ(PLANE_CTL(pipe, plane));
+
+       intel_update_sprite_watermarks(drm_plane, crtc, 0, 0, 0, false, false);
+}
+
+static int
+skl_update_colorkey(struct drm_plane *drm_plane,
+                   struct drm_intel_sprite_colorkey *key)
+{
+       struct drm_device *dev = drm_plane->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_plane *intel_plane = to_intel_plane(drm_plane);
+       const int pipe = intel_plane->pipe;
+       const int plane = intel_plane->plane;
+       u32 plane_ctl;
+
+       I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
+       I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
+       I915_WRITE(PLANE_KEYMSK(pipe, plane), key->channel_mask);
+
+       plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
+       plane_ctl &= ~PLANE_CTL_KEY_ENABLE_MASK;
+       if (key->flags & I915_SET_COLORKEY_DESTINATION)
+               plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
+       else if (key->flags & I915_SET_COLORKEY_SOURCE)
+               plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
+       I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
+
+       POSTING_READ(PLANE_CTL(pipe, plane));
+
+       return 0;
+}
+
+static void
+skl_get_colorkey(struct drm_plane *drm_plane,
+                struct drm_intel_sprite_colorkey *key)
+{
+       struct drm_device *dev = drm_plane->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_plane *intel_plane = to_intel_plane(drm_plane);
+       const int pipe = intel_plane->pipe;
+       const int plane = intel_plane->plane;
+       u32 plane_ctl;
+
+       key->min_value = I915_READ(PLANE_KEYVAL(pipe, plane));
+       key->max_value = I915_READ(PLANE_KEYMAX(pipe, plane));
+       key->channel_mask = I915_READ(PLANE_KEYMSK(pipe, plane));
+
+       plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
+
+       switch (plane_ctl & PLANE_CTL_KEY_ENABLE_MASK) {
+       case PLANE_CTL_KEY_ENABLE_DESTINATION:
+               key->flags = I915_SET_COLORKEY_DESTINATION;
+               break;
+       case PLANE_CTL_KEY_ENABLE_SOURCE:
+               key->flags = I915_SET_COLORKEY_SOURCE;
+               break;
+       default:
+               key->flags = I915_SET_COLORKEY_NONE;
+       }
+}
+
+static void
 vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
                 struct drm_framebuffer *fb,
                 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
@@ -1305,6 +1483,18 @@ static uint32_t vlv_plane_formats[] = {
        DRM_FORMAT_VYUY,
 };
 
+static uint32_t skl_plane_formats[] = {
+       DRM_FORMAT_RGB565,
+       DRM_FORMAT_ABGR8888,
+       DRM_FORMAT_ARGB8888,
+       DRM_FORMAT_XBGR8888,
+       DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_YUYV,
+       DRM_FORMAT_YVYU,
+       DRM_FORMAT_UYVY,
+       DRM_FORMAT_VYUY,
+};
+
 int
 intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
 {
@@ -1368,7 +1558,21 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
                        num_plane_formats = ARRAY_SIZE(snb_plane_formats);
                }
                break;
-
+       case 9:
+               /*
+                * FIXME: Skylake planes can be scaled (with some restrictions),
+                * but this is for another time.
+                */
+               intel_plane->can_scale = false;
+               intel_plane->max_downscale = 1;
+               intel_plane->update_plane = skl_update_plane;
+               intel_plane->disable_plane = skl_disable_plane;
+               intel_plane->update_colorkey = skl_update_colorkey;
+               intel_plane->get_colorkey = skl_get_colorkey;
+
+               plane_formats = skl_plane_formats;
+               num_plane_formats = ARRAY_SIZE(skl_plane_formats);
+               break;
        default:
                kfree(intel_plane);
                return -ENODEV;