aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamien Lespiau <damien.lespiau@intel.com>2015-02-27 06:15:18 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-02-27 12:10:54 -0500
commitb321803dfbe46faeb54e8e758148be40e628225e (patch)
treec40a098826f31ca4b525692f90edf1125ccc9492
parentb5ff6e1637b683d5996ae11ac29afe406c0bee90 (diff)
drm/i915/skl: Allow scanning out Y and Yf fbs
Skylake is able to scannout those tiling formats. We need to allow them in the ADDFB ioctl and tell the harware about it. v2: Rebased for addfb2 interface. (Tvrtko Ursulin) v3: Rebased for fb modifier changes. (Tvrtko Ursulin) v4: Don't allow Y tiled fbs just yet. (Tvrtko Ursulin) v5: Check for stride alignment and max pitch. (Tvrtko Ursulin) v6: Simplify maximum pitch check. (Ville Syrjälä) v7: Drop the gen9 check since requirements are no different. (Ville Syrjälä) v8: Gen2 has different X tiling stride. (Ville Syrjälä) Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Damien Lespiau <damien.lespiau@intel.com> (v7) Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c121
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c18
3 files changed, 101 insertions, 40 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ca6a24064cab..8076bce85160 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2728,6 +2728,40 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
2728 POSTING_READ(reg); 2728 POSTING_READ(reg);
2729} 2729}
2730 2730
2731u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
2732 uint32_t pixel_format)
2733{
2734 u32 bits_per_pixel = drm_format_plane_cpp(pixel_format, 0) * 8;
2735
2736 /*
2737 * The stride is either expressed as a multiple of 64 bytes
2738 * chunks for linear buffers or in number of tiles for tiled
2739 * buffers.
2740 */
2741 switch (fb_modifier) {
2742 case DRM_FORMAT_MOD_NONE:
2743 return 64;
2744 case I915_FORMAT_MOD_X_TILED:
2745 if (INTEL_INFO(dev)->gen == 2)
2746 return 128;
2747 return 512;
2748 case I915_FORMAT_MOD_Y_TILED:
2749 /* No need to check for old gens and Y tiling since this is
2750 * about the display engine and those will be blocked before
2751 * we get here.
2752 */
2753 return 128;
2754 case I915_FORMAT_MOD_Yf_TILED:
2755 if (bits_per_pixel == 8)
2756 return 64;
2757 else
2758 return 128;
2759 default:
2760 MISSING_CASE(fb_modifier);
2761 return 64;
2762 }
2763}
2764
2731static void skylake_update_primary_plane(struct drm_crtc *crtc, 2765static void skylake_update_primary_plane(struct drm_crtc *crtc,
2732 struct drm_framebuffer *fb, 2766 struct drm_framebuffer *fb,
2733 int x, int y) 2767 int x, int y)
@@ -2735,10 +2769,9 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
2735 struct drm_device *dev = crtc->dev; 2769 struct drm_device *dev = crtc->dev;
2736 struct drm_i915_private *dev_priv = dev->dev_private; 2770 struct drm_i915_private *dev_priv = dev->dev_private;
2737 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 2771 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2738 struct intel_framebuffer *intel_fb;
2739 struct drm_i915_gem_object *obj; 2772 struct drm_i915_gem_object *obj;
2740 int pipe = intel_crtc->pipe; 2773 int pipe = intel_crtc->pipe;
2741 u32 plane_ctl, stride; 2774 u32 plane_ctl, stride_div;
2742 2775
2743 if (!intel_crtc->primary_enabled) { 2776 if (!intel_crtc->primary_enabled) {
2744 I915_WRITE(PLANE_CTL(pipe, 0), 0); 2777 I915_WRITE(PLANE_CTL(pipe, 0), 0);
@@ -2773,29 +2806,30 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
2773 BUG(); 2806 BUG();
2774 } 2807 }
2775 2808
2776 intel_fb = to_intel_framebuffer(fb);
2777 obj = intel_fb->obj;
2778
2779 /*
2780 * The stride is either expressed as a multiple of 64 bytes chunks for
2781 * linear buffers or in number of tiles for tiled buffers.
2782 */
2783 switch (fb->modifier[0]) { 2809 switch (fb->modifier[0]) {
2784 case DRM_FORMAT_MOD_NONE: 2810 case DRM_FORMAT_MOD_NONE:
2785 stride = fb->pitches[0] >> 6;
2786 break; 2811 break;
2787 case I915_FORMAT_MOD_X_TILED: 2812 case I915_FORMAT_MOD_X_TILED:
2788 plane_ctl |= PLANE_CTL_TILED_X; 2813 plane_ctl |= PLANE_CTL_TILED_X;
2789 stride = fb->pitches[0] >> 9; 2814 break;
2815 case I915_FORMAT_MOD_Y_TILED:
2816 plane_ctl |= PLANE_CTL_TILED_Y;
2817 break;
2818 case I915_FORMAT_MOD_Yf_TILED:
2819 plane_ctl |= PLANE_CTL_TILED_YF;
2790 break; 2820 break;
2791 default: 2821 default:
2792 BUG(); 2822 MISSING_CASE(fb->modifier[0]);
2793 } 2823 }
2794 2824
2795 plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE; 2825 plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
2796 if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) 2826 if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180))
2797 plane_ctl |= PLANE_CTL_ROTATE_180; 2827 plane_ctl |= PLANE_CTL_ROTATE_180;
2798 2828
2829 obj = intel_fb_obj(fb);
2830 stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
2831 fb->pixel_format);
2832
2799 I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl); 2833 I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
2800 2834
2801 DRM_DEBUG_KMS("Writing base %08lX %d,%d,%d,%d pitch=%d\n", 2835 DRM_DEBUG_KMS("Writing base %08lX %d,%d,%d,%d pitch=%d\n",
@@ -2808,7 +2842,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
2808 I915_WRITE(PLANE_SIZE(pipe, 0), 2842 I915_WRITE(PLANE_SIZE(pipe, 0),
2809 (intel_crtc->config->pipe_src_h - 1) << 16 | 2843 (intel_crtc->config->pipe_src_h - 1) << 16 |
2810 (intel_crtc->config->pipe_src_w - 1)); 2844 (intel_crtc->config->pipe_src_w - 1));
2811 I915_WRITE(PLANE_STRIDE(pipe, 0), stride); 2845 I915_WRITE(PLANE_STRIDE(pipe, 0), fb->pitches[0] / stride_div);
2812 I915_WRITE(PLANE_SURF(pipe, 0), i915_gem_obj_ggtt_offset(obj)); 2846 I915_WRITE(PLANE_SURF(pipe, 0), i915_gem_obj_ggtt_offset(obj));
2813 2847
2814 POSTING_READ(PLANE_SURF(pipe, 0)); 2848 POSTING_READ(PLANE_SURF(pipe, 0));
@@ -12666,14 +12700,43 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = {
12666 .create_handle = intel_user_framebuffer_create_handle, 12700 .create_handle = intel_user_framebuffer_create_handle,
12667}; 12701};
12668 12702
12703static
12704u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
12705 uint32_t pixel_format)
12706{
12707 u32 gen = INTEL_INFO(dev)->gen;
12708
12709 if (gen >= 9) {
12710 /* "The stride in bytes must not exceed the of the size of 8K
12711 * pixels and 32K bytes."
12712 */
12713 return min(8192*drm_format_plane_cpp(pixel_format, 0), 32768);
12714 } else if (gen >= 5 && !IS_VALLEYVIEW(dev)) {
12715 return 32*1024;
12716 } else if (gen >= 4) {
12717 if (fb_modifier == I915_FORMAT_MOD_X_TILED)
12718 return 16*1024;
12719 else
12720 return 32*1024;
12721 } else if (gen >= 3) {
12722 if (fb_modifier == I915_FORMAT_MOD_X_TILED)
12723 return 8*1024;
12724 else
12725 return 16*1024;
12726 } else {
12727 /* XXX DSPC is limited to 4k tiled */
12728 return 8*1024;
12729 }
12730}
12731
12669static int intel_framebuffer_init(struct drm_device *dev, 12732static int intel_framebuffer_init(struct drm_device *dev,
12670 struct intel_framebuffer *intel_fb, 12733 struct intel_framebuffer *intel_fb,
12671 struct drm_mode_fb_cmd2 *mode_cmd, 12734 struct drm_mode_fb_cmd2 *mode_cmd,
12672 struct drm_i915_gem_object *obj) 12735 struct drm_i915_gem_object *obj)
12673{ 12736{
12674 int aligned_height; 12737 int aligned_height;
12675 int pitch_limit;
12676 int ret; 12738 int ret;
12739 u32 pitch_limit, stride_alignment;
12677 12740
12678 WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 12741 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
12679 12742
@@ -12699,31 +12762,19 @@ static int intel_framebuffer_init(struct drm_device *dev,
12699 return -EINVAL; 12762 return -EINVAL;
12700 } 12763 }
12701 12764
12702 if (mode_cmd->pitches[0] & 63) { 12765 stride_alignment = intel_fb_stride_alignment(dev, mode_cmd->modifier[0],
12703 DRM_DEBUG("pitch (%d) must be at least 64 byte aligned\n", 12766 mode_cmd->pixel_format);
12704 mode_cmd->pitches[0]); 12767 if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
12768 DRM_DEBUG("pitch (%d) must be at least %u byte aligned\n",
12769 mode_cmd->pitches[0], stride_alignment);
12705 return -EINVAL; 12770 return -EINVAL;
12706 } 12771 }
12707 12772
12708 if (INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev)) { 12773 pitch_limit = intel_fb_pitch_limit(dev, mode_cmd->modifier[0],
12709 pitch_limit = 32*1024; 12774 mode_cmd->pixel_format);
12710 } else if (INTEL_INFO(dev)->gen >= 4) {
12711 if (mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED)
12712 pitch_limit = 16*1024;
12713 else
12714 pitch_limit = 32*1024;
12715 } else if (INTEL_INFO(dev)->gen >= 3) {
12716 if (mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED)
12717 pitch_limit = 8*1024;
12718 else
12719 pitch_limit = 16*1024;
12720 } else
12721 /* XXX DSPC is limited to 4k tiled */
12722 pitch_limit = 8*1024;
12723
12724 if (mode_cmd->pitches[0] > pitch_limit) { 12775 if (mode_cmd->pitches[0] > pitch_limit) {
12725 DRM_DEBUG("%s pitch (%d) must be at less than %d\n", 12776 DRM_DEBUG("%s pitch (%u) must be at less than %d\n",
12726 mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED ? 12777 mode_cmd->modifier[0] != DRM_FORMAT_MOD_NONE ?
12727 "tiled" : "linear", 12778 "tiled" : "linear",
12728 mode_cmd->pitches[0], pitch_limit); 12779 mode_cmd->pitches[0], pitch_limit);
12729 return -EINVAL; 12780 return -EINVAL;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1fb15298cfba..76df9d6fc205 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -903,6 +903,8 @@ int intel_fb_align_height(struct drm_device *dev, int height,
903 uint64_t fb_format_modifier); 903 uint64_t fb_format_modifier);
904void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire); 904void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire);
905 905
906u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
907 uint32_t pixel_format);
906 908
907/* intel_audio.c */ 909/* intel_audio.c */
908void intel_init_audio(struct drm_device *dev); 910void intel_init_audio(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index f0b06c09da40..bdb64fc14655 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -189,7 +189,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
189 struct intel_plane *intel_plane = to_intel_plane(drm_plane); 189 struct intel_plane *intel_plane = to_intel_plane(drm_plane);
190 const int pipe = intel_plane->pipe; 190 const int pipe = intel_plane->pipe;
191 const int plane = intel_plane->plane + 1; 191 const int plane = intel_plane->plane + 1;
192 u32 plane_ctl, stride; 192 u32 plane_ctl, stride_div;
193 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); 193 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
194 194
195 plane_ctl = I915_READ(PLANE_CTL(pipe, plane)); 195 plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
@@ -247,15 +247,20 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
247 247
248 switch (fb->modifier[0]) { 248 switch (fb->modifier[0]) {
249 case DRM_FORMAT_MOD_NONE: 249 case DRM_FORMAT_MOD_NONE:
250 stride = fb->pitches[0] >> 6;
251 break; 250 break;
252 case I915_FORMAT_MOD_X_TILED: 251 case I915_FORMAT_MOD_X_TILED:
253 plane_ctl |= PLANE_CTL_TILED_X; 252 plane_ctl |= PLANE_CTL_TILED_X;
254 stride = fb->pitches[0] >> 9; 253 break;
254 case I915_FORMAT_MOD_Y_TILED:
255 plane_ctl |= PLANE_CTL_TILED_Y;
256 break;
257 case I915_FORMAT_MOD_Yf_TILED:
258 plane_ctl |= PLANE_CTL_TILED_YF;
255 break; 259 break;
256 default: 260 default:
257 BUG(); 261 MISSING_CASE(fb->modifier[0]);
258 } 262 }
263
259 if (drm_plane->state->rotation == BIT(DRM_ROTATE_180)) 264 if (drm_plane->state->rotation == BIT(DRM_ROTATE_180))
260 plane_ctl |= PLANE_CTL_ROTATE_180; 265 plane_ctl |= PLANE_CTL_ROTATE_180;
261 266
@@ -266,6 +271,9 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
266 pixel_size, true, 271 pixel_size, true,
267 src_w != crtc_w || src_h != crtc_h); 272 src_w != crtc_w || src_h != crtc_h);
268 273
274 stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
275 fb->pixel_format);
276
269 /* Sizes are 0 based */ 277 /* Sizes are 0 based */
270 src_w--; 278 src_w--;
271 src_h--; 279 src_h--;
@@ -273,7 +281,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
273 crtc_h--; 281 crtc_h--;
274 282
275 I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x); 283 I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
276 I915_WRITE(PLANE_STRIDE(pipe, plane), stride); 284 I915_WRITE(PLANE_STRIDE(pipe, plane), fb->pitches[0] / stride_div);
277 I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x); 285 I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
278 I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w); 286 I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w);
279 I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl); 287 I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);