aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_sprite.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sprite.c')
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c243
1 files changed, 234 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 1b6eb76beb7c..c7d25c5dd4e6 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -37,6 +37,174 @@
37#include "i915_drv.h" 37#include "i915_drv.h"
38 38
39static void 39static void
40vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
41 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
42 unsigned int crtc_w, unsigned int crtc_h,
43 uint32_t x, uint32_t y,
44 uint32_t src_w, uint32_t src_h)
45{
46 struct drm_device *dev = dplane->dev;
47 struct drm_i915_private *dev_priv = dev->dev_private;
48 struct intel_plane *intel_plane = to_intel_plane(dplane);
49 int pipe = intel_plane->pipe;
50 int plane = intel_plane->plane;
51 u32 sprctl;
52 unsigned long sprsurf_offset, linear_offset;
53 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
54
55 sprctl = I915_READ(SPCNTR(pipe, plane));
56
57 /* Mask out pixel format bits in case we change it */
58 sprctl &= ~SP_PIXFORMAT_MASK;
59 sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
60 sprctl &= ~SP_TILED;
61
62 switch (fb->pixel_format) {
63 case DRM_FORMAT_YUYV:
64 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
65 break;
66 case DRM_FORMAT_YVYU:
67 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
68 break;
69 case DRM_FORMAT_UYVY:
70 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
71 break;
72 case DRM_FORMAT_VYUY:
73 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
74 break;
75 case DRM_FORMAT_RGB565:
76 sprctl |= SP_FORMAT_BGR565;
77 break;
78 case DRM_FORMAT_XRGB8888:
79 sprctl |= SP_FORMAT_BGRX8888;
80 break;
81 case DRM_FORMAT_ARGB8888:
82 sprctl |= SP_FORMAT_BGRA8888;
83 break;
84 case DRM_FORMAT_XBGR2101010:
85 sprctl |= SP_FORMAT_RGBX1010102;
86 break;
87 case DRM_FORMAT_ABGR2101010:
88 sprctl |= SP_FORMAT_RGBA1010102;
89 break;
90 case DRM_FORMAT_XBGR8888:
91 sprctl |= SP_FORMAT_RGBX8888;
92 break;
93 case DRM_FORMAT_ABGR8888:
94 sprctl |= SP_FORMAT_RGBA8888;
95 break;
96 default:
97 /*
98 * If we get here one of the upper layers failed to filter
99 * out the unsupported plane formats
100 */
101 BUG();
102 break;
103 }
104
105 if (obj->tiling_mode != I915_TILING_NONE)
106 sprctl |= SP_TILED;
107
108 sprctl |= SP_ENABLE;
109
110 /* Sizes are 0 based */
111 src_w--;
112 src_h--;
113 crtc_w--;
114 crtc_h--;
115
116 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
117
118 I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
119 I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
120
121 linear_offset = y * fb->pitches[0] + x * pixel_size;
122 sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
123 obj->tiling_mode,
124 pixel_size,
125 fb->pitches[0]);
126 linear_offset -= sprsurf_offset;
127
128 if (obj->tiling_mode != I915_TILING_NONE)
129 I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
130 else
131 I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
132
133 I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
134 I915_WRITE(SPCNTR(pipe, plane), sprctl);
135 I915_MODIFY_DISPBASE(SPSURF(pipe, plane), obj->gtt_offset +
136 sprsurf_offset);
137 POSTING_READ(SPSURF(pipe, plane));
138}
139
140static void
141vlv_disable_plane(struct drm_plane *dplane)
142{
143 struct drm_device *dev = dplane->dev;
144 struct drm_i915_private *dev_priv = dev->dev_private;
145 struct intel_plane *intel_plane = to_intel_plane(dplane);
146 int pipe = intel_plane->pipe;
147 int plane = intel_plane->plane;
148
149 I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
150 ~SP_ENABLE);
151 /* Activate double buffered register update */
152 I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0);
153 POSTING_READ(SPSURF(pipe, plane));
154}
155
156static int
157vlv_update_colorkey(struct drm_plane *dplane,
158 struct drm_intel_sprite_colorkey *key)
159{
160 struct drm_device *dev = dplane->dev;
161 struct drm_i915_private *dev_priv = dev->dev_private;
162 struct intel_plane *intel_plane = to_intel_plane(dplane);
163 int pipe = intel_plane->pipe;
164 int plane = intel_plane->plane;
165 u32 sprctl;
166
167 if (key->flags & I915_SET_COLORKEY_DESTINATION)
168 return -EINVAL;
169
170 I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
171 I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
172 I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
173
174 sprctl = I915_READ(SPCNTR(pipe, plane));
175 sprctl &= ~SP_SOURCE_KEY;
176 if (key->flags & I915_SET_COLORKEY_SOURCE)
177 sprctl |= SP_SOURCE_KEY;
178 I915_WRITE(SPCNTR(pipe, plane), sprctl);
179
180 POSTING_READ(SPKEYMSK(pipe, plane));
181
182 return 0;
183}
184
185static void
186vlv_get_colorkey(struct drm_plane *dplane,
187 struct drm_intel_sprite_colorkey *key)
188{
189 struct drm_device *dev = dplane->dev;
190 struct drm_i915_private *dev_priv = dev->dev_private;
191 struct intel_plane *intel_plane = to_intel_plane(dplane);
192 int pipe = intel_plane->pipe;
193 int plane = intel_plane->plane;
194 u32 sprctl;
195
196 key->min_value = I915_READ(SPKEYMINVAL(pipe, plane));
197 key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane));
198 key->channel_mask = I915_READ(SPKEYMSK(pipe, plane));
199
200 sprctl = I915_READ(SPCNTR(pipe, plane));
201 if (sprctl & SP_SOURCE_KEY)
202 key->flags = I915_SET_COLORKEY_SOURCE;
203 else
204 key->flags = I915_SET_COLORKEY_NONE;
205}
206
207static void
40ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, 208ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
41 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y, 209 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
42 unsigned int crtc_w, unsigned int crtc_h, 210 unsigned int crtc_w, unsigned int crtc_h,
@@ -441,6 +609,15 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
441 609
442 old_obj = intel_plane->obj; 610 old_obj = intel_plane->obj;
443 611
612 intel_plane->crtc_x = crtc_x;
613 intel_plane->crtc_y = crtc_y;
614 intel_plane->crtc_w = crtc_w;
615 intel_plane->crtc_h = crtc_h;
616 intel_plane->src_x = src_x;
617 intel_plane->src_y = src_y;
618 intel_plane->src_w = src_w;
619 intel_plane->src_h = src_h;
620
444 src_w = src_w >> 16; 621 src_w = src_w >> 16;
445 src_h = src_h >> 16; 622 src_h = src_h >> 16;
446 623
@@ -513,6 +690,11 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
513 690
514 mutex_lock(&dev->struct_mutex); 691 mutex_lock(&dev->struct_mutex);
515 692
693 /* Note that this will apply the VT-d workaround for scanouts,
694 * which is more restrictive than required for sprites. (The
695 * primary plane requires 256KiB alignment with 64 PTE padding,
696 * the sprite planes only require 128KiB alignment and 32 PTE padding.
697 */
516 ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); 698 ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
517 if (ret) 699 if (ret)
518 goto out_unlock; 700 goto out_unlock;
@@ -568,6 +750,8 @@ intel_disable_plane(struct drm_plane *plane)
568 if (!intel_plane->obj) 750 if (!intel_plane->obj)
569 goto out; 751 goto out;
570 752
753 intel_wait_for_vblank(dev, intel_plane->pipe);
754
571 mutex_lock(&dev->struct_mutex); 755 mutex_lock(&dev->struct_mutex);
572 intel_unpin_fb_obj(intel_plane->obj); 756 intel_unpin_fb_obj(intel_plane->obj);
573 intel_plane->obj = NULL; 757 intel_plane->obj = NULL;
@@ -647,6 +831,20 @@ out_unlock:
647 return ret; 831 return ret;
648} 832}
649 833
834void intel_plane_restore(struct drm_plane *plane)
835{
836 struct intel_plane *intel_plane = to_intel_plane(plane);
837
838 if (!plane->crtc || !plane->fb)
839 return;
840
841 intel_update_plane(plane, plane->crtc, plane->fb,
842 intel_plane->crtc_x, intel_plane->crtc_y,
843 intel_plane->crtc_w, intel_plane->crtc_h,
844 intel_plane->src_x, intel_plane->src_y,
845 intel_plane->src_w, intel_plane->src_h);
846}
847
650static const struct drm_plane_funcs intel_plane_funcs = { 848static const struct drm_plane_funcs intel_plane_funcs = {
651 .update_plane = intel_update_plane, 849 .update_plane = intel_update_plane,
652 .disable_plane = intel_disable_plane, 850 .disable_plane = intel_disable_plane,
@@ -670,8 +868,22 @@ static uint32_t snb_plane_formats[] = {
670 DRM_FORMAT_VYUY, 868 DRM_FORMAT_VYUY,
671}; 869};
672 870
871static uint32_t vlv_plane_formats[] = {
872 DRM_FORMAT_RGB565,
873 DRM_FORMAT_ABGR8888,
874 DRM_FORMAT_ARGB8888,
875 DRM_FORMAT_XBGR8888,
876 DRM_FORMAT_XRGB8888,
877 DRM_FORMAT_XBGR2101010,
878 DRM_FORMAT_ABGR2101010,
879 DRM_FORMAT_YUYV,
880 DRM_FORMAT_YVYU,
881 DRM_FORMAT_UYVY,
882 DRM_FORMAT_VYUY,
883};
884
673int 885int
674intel_plane_init(struct drm_device *dev, enum pipe pipe) 886intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
675{ 887{
676 struct intel_plane *intel_plane; 888 struct intel_plane *intel_plane;
677 unsigned long possible_crtcs; 889 unsigned long possible_crtcs;
@@ -710,14 +922,26 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe)
710 intel_plane->can_scale = false; 922 intel_plane->can_scale = false;
711 else 923 else
712 intel_plane->can_scale = true; 924 intel_plane->can_scale = true;
713 intel_plane->max_downscale = 2; 925
714 intel_plane->update_plane = ivb_update_plane; 926 if (IS_VALLEYVIEW(dev)) {
715 intel_plane->disable_plane = ivb_disable_plane; 927 intel_plane->max_downscale = 1;
716 intel_plane->update_colorkey = ivb_update_colorkey; 928 intel_plane->update_plane = vlv_update_plane;
717 intel_plane->get_colorkey = ivb_get_colorkey; 929 intel_plane->disable_plane = vlv_disable_plane;
718 930 intel_plane->update_colorkey = vlv_update_colorkey;
719 plane_formats = snb_plane_formats; 931 intel_plane->get_colorkey = vlv_get_colorkey;
720 num_plane_formats = ARRAY_SIZE(snb_plane_formats); 932
933 plane_formats = vlv_plane_formats;
934 num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
935 } else {
936 intel_plane->max_downscale = 2;
937 intel_plane->update_plane = ivb_update_plane;
938 intel_plane->disable_plane = ivb_disable_plane;
939 intel_plane->update_colorkey = ivb_update_colorkey;
940 intel_plane->get_colorkey = ivb_get_colorkey;
941
942 plane_formats = snb_plane_formats;
943 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
944 }
721 break; 945 break;
722 946
723 default: 947 default:
@@ -726,6 +950,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe)
726 } 950 }
727 951
728 intel_plane->pipe = pipe; 952 intel_plane->pipe = pipe;
953 intel_plane->plane = plane;
729 possible_crtcs = (1 << pipe); 954 possible_crtcs = (1 << pipe);
730 ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, 955 ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
731 &intel_plane_funcs, 956 &intel_plane_funcs,