diff options
author | Damien Lespiau <damien.lespiau@intel.com> | 2015-02-27 06:15:18 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-02-27 12:10:54 -0500 |
commit | b321803dfbe46faeb54e8e758148be40e628225e (patch) | |
tree | c40a098826f31ca4b525692f90edf1125ccc9492 | |
parent | b5ff6e1637b683d5996ae11ac29afe406c0bee90 (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.c | 121 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sprite.c | 18 |
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 | ||
2731 | u32 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 | |||
2731 | static void skylake_update_primary_plane(struct drm_crtc *crtc, | 2765 | static 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 | ||
12703 | static | ||
12704 | u32 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 | |||
12669 | static int intel_framebuffer_init(struct drm_device *dev, | 12732 | static 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); |
904 | void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire); | 904 | void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire); |
905 | 905 | ||
906 | u32 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 */ |
908 | void intel_init_audio(struct drm_device *dev); | 910 | void 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); |