blob: 18993ad93540ce5b82aa996a76985be31587e0b7 [file] [log] [blame]
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001/*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Jesse Barnes <jbarnes@virtuousgeek.org>
25 *
26 * New plane/sprite handling.
27 *
28 * The older chips had a separate interface for programming plane related
29 * registers; newer ones are much simpler and we can use the new DRM plane
30 * support.
31 */
David Howells760285e2012-10-02 18:01:07 +010032#include <drm/drmP.h>
33#include <drm/drm_crtc.h>
34#include <drm/drm_fourcc.h>
Jesse Barnesb840d907f2011-12-13 13:19:38 -080035#include "intel_drv.h"
David Howells760285e2012-10-02 18:01:07 +010036#include <drm/i915_drm.h>
Jesse Barnesb840d907f2011-12-13 13:19:38 -080037#include "i915_drv.h"
38
39static void
Jesse Barnes7f1f3852013-04-02 11:22:20 -070040vlv_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
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800208ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
209 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
210 unsigned int crtc_w, unsigned int crtc_h,
211 uint32_t x, uint32_t y,
212 uint32_t src_w, uint32_t src_h)
213{
214 struct drm_device *dev = plane->dev;
215 struct drm_i915_private *dev_priv = dev->dev_private;
216 struct intel_plane *intel_plane = to_intel_plane(plane);
217 int pipe = intel_plane->pipe;
218 u32 sprctl, sprscale = 0;
Damien Lespiau5a35e992012-10-26 18:20:12 +0100219 unsigned long sprsurf_offset, linear_offset;
Ville Syrjälä2bd3c3c2012-10-31 17:50:20 +0200220 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
Ville Syrjälä2c6602d2013-02-08 23:13:35 +0200221 bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800222
223 sprctl = I915_READ(SPRCTL(pipe));
224
225 /* Mask out pixel format bits in case we change it */
226 sprctl &= ~SPRITE_PIXFORMAT_MASK;
227 sprctl &= ~SPRITE_RGB_ORDER_RGBX;
228 sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
Jesse Barnese86fe0d2012-06-26 13:10:11 -0700229 sprctl &= ~SPRITE_TILED;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800230
231 switch (fb->pixel_format) {
232 case DRM_FORMAT_XBGR8888:
Vijay Purushothaman5ee36912012-08-23 12:08:57 +0530233 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800234 break;
235 case DRM_FORMAT_XRGB8888:
Vijay Purushothaman5ee36912012-08-23 12:08:57 +0530236 sprctl |= SPRITE_FORMAT_RGBX888;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800237 break;
238 case DRM_FORMAT_YUYV:
239 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800240 break;
241 case DRM_FORMAT_YVYU:
242 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800243 break;
244 case DRM_FORMAT_UYVY:
245 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800246 break;
247 case DRM_FORMAT_VYUY:
248 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800249 break;
250 default:
Ville Syrjälä28d491d2012-10-31 17:50:21 +0200251 BUG();
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800252 }
253
254 if (obj->tiling_mode != I915_TILING_NONE)
255 sprctl |= SPRITE_TILED;
256
257 /* must disable */
258 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
259 sprctl |= SPRITE_ENABLE;
260
Ville Syrjälä86d3efc2013-01-18 19:11:38 +0200261 if (IS_HASWELL(dev))
262 sprctl |= SPRITE_PIPE_CSC_ENABLE;
263
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800264 /* Sizes are 0 based */
265 src_w--;
266 src_h--;
267 crtc_w--;
268 crtc_h--;
269
270 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
271
272 /*
273 * IVB workaround: must disable low power watermarks for at least
274 * one frame before enabling scaling. LP watermarks can be re-enabled
275 * when scaling is disabled.
276 */
277 if (crtc_w != src_w || crtc_h != src_h) {
Ville Syrjälä2c6602d2013-02-08 23:13:35 +0200278 dev_priv->sprite_scaling_enabled |= 1 << pipe;
279
280 if (!scaling_was_enabled) {
Chris Wilson828ed3e2012-04-18 17:12:26 +0100281 intel_update_watermarks(dev);
282 intel_wait_for_vblank(dev, pipe);
283 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800284 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
Ville Syrjälä2c6602d2013-02-08 23:13:35 +0200285 } else
286 dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800287
288 I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
289 I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
Damien Lespiauc54173a2012-10-26 18:20:11 +0100290
Chris Wilsonca320ac2012-12-19 12:14:22 +0000291 linear_offset = y * fb->pitches[0] + x * pixel_size;
Damien Lespiau5a35e992012-10-26 18:20:12 +0100292 sprsurf_offset =
Chris Wilsonbc752862013-02-21 20:04:31 +0000293 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
294 pixel_size, fb->pitches[0]);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100295 linear_offset -= sprsurf_offset;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800296
Damien Lespiau5a35e992012-10-26 18:20:12 +0100297 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
298 * register */
299 if (IS_HASWELL(dev))
300 I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
301 else if (obj->tiling_mode != I915_TILING_NONE)
302 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
303 else
304 I915_WRITE(SPRLINOFF(pipe), linear_offset);
Damien Lespiauc54173a2012-10-26 18:20:11 +0100305
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800306 I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
Damien Lespiau2d354c32012-10-22 18:19:27 +0100307 if (intel_plane->can_scale)
308 I915_WRITE(SPRSCALE(pipe), sprscale);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800309 I915_WRITE(SPRCTL(pipe), sprctl);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100310 I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset + sprsurf_offset);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800311 POSTING_READ(SPRSURF(pipe));
Ville Syrjälä2c6602d2013-02-08 23:13:35 +0200312
313 /* potentially re-enable LP watermarks */
314 if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
315 intel_update_watermarks(dev);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800316}
317
318static void
319ivb_disable_plane(struct drm_plane *plane)
320{
321 struct drm_device *dev = plane->dev;
322 struct drm_i915_private *dev_priv = dev->dev_private;
323 struct intel_plane *intel_plane = to_intel_plane(plane);
324 int pipe = intel_plane->pipe;
Ville Syrjälä2c6602d2013-02-08 23:13:35 +0200325 bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800326
327 I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
328 /* Can't leave the scaler enabled... */
Damien Lespiau2d354c32012-10-22 18:19:27 +0100329 if (intel_plane->can_scale)
330 I915_WRITE(SPRSCALE(pipe), 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800331 /* Activate double buffered register update */
Armin Reese446f2542012-03-30 16:20:16 -0700332 I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800333 POSTING_READ(SPRSURF(pipe));
Chris Wilson828ed3e2012-04-18 17:12:26 +0100334
Ville Syrjälä2c6602d2013-02-08 23:13:35 +0200335 dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
336
337 /* potentially re-enable LP watermarks */
338 if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
339 intel_update_watermarks(dev);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800340}
341
Jesse Barnes8ea30862012-01-03 08:05:39 -0800342static int
343ivb_update_colorkey(struct drm_plane *plane,
344 struct drm_intel_sprite_colorkey *key)
345{
346 struct drm_device *dev = plane->dev;
347 struct drm_i915_private *dev_priv = dev->dev_private;
348 struct intel_plane *intel_plane;
349 u32 sprctl;
350 int ret = 0;
351
352 intel_plane = to_intel_plane(plane);
353
354 I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
355 I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
356 I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
357
358 sprctl = I915_READ(SPRCTL(intel_plane->pipe));
359 sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
360 if (key->flags & I915_SET_COLORKEY_DESTINATION)
361 sprctl |= SPRITE_DEST_KEY;
362 else if (key->flags & I915_SET_COLORKEY_SOURCE)
363 sprctl |= SPRITE_SOURCE_KEY;
364 I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
365
366 POSTING_READ(SPRKEYMSK(intel_plane->pipe));
367
368 return ret;
369}
370
371static void
372ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
373{
374 struct drm_device *dev = plane->dev;
375 struct drm_i915_private *dev_priv = dev->dev_private;
376 struct intel_plane *intel_plane;
377 u32 sprctl;
378
379 intel_plane = to_intel_plane(plane);
380
381 key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
382 key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
383 key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
384 key->flags = 0;
385
386 sprctl = I915_READ(SPRCTL(intel_plane->pipe));
387
388 if (sprctl & SPRITE_DEST_KEY)
389 key->flags = I915_SET_COLORKEY_DESTINATION;
390 else if (sprctl & SPRITE_SOURCE_KEY)
391 key->flags = I915_SET_COLORKEY_SOURCE;
392 else
393 key->flags = I915_SET_COLORKEY_NONE;
394}
395
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800396static void
Chris Wilsond1686ae2012-04-10 11:41:49 +0100397ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800398 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
399 unsigned int crtc_w, unsigned int crtc_h,
400 uint32_t x, uint32_t y,
401 uint32_t src_w, uint32_t src_h)
402{
403 struct drm_device *dev = plane->dev;
404 struct drm_i915_private *dev_priv = dev->dev_private;
405 struct intel_plane *intel_plane = to_intel_plane(plane);
Ville Syrjälä2bd3c3c2012-10-31 17:50:20 +0200406 int pipe = intel_plane->pipe;
Damien Lespiau5a35e992012-10-26 18:20:12 +0100407 unsigned long dvssurf_offset, linear_offset;
Chris Wilson8aaa81a2012-04-14 22:14:26 +0100408 u32 dvscntr, dvsscale;
Ville Syrjälä2bd3c3c2012-10-31 17:50:20 +0200409 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800410
411 dvscntr = I915_READ(DVSCNTR(pipe));
412
413 /* Mask out pixel format bits in case we change it */
414 dvscntr &= ~DVS_PIXFORMAT_MASK;
Jesse Barnesab2f9df2012-02-27 12:40:10 -0800415 dvscntr &= ~DVS_RGB_ORDER_XBGR;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800416 dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
Ander Conselvan de Oliveira79626522012-07-13 15:50:33 +0300417 dvscntr &= ~DVS_TILED;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800418
419 switch (fb->pixel_format) {
420 case DRM_FORMAT_XBGR8888:
Jesse Barnesab2f9df2012-02-27 12:40:10 -0800421 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800422 break;
423 case DRM_FORMAT_XRGB8888:
Jesse Barnesab2f9df2012-02-27 12:40:10 -0800424 dvscntr |= DVS_FORMAT_RGBX888;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800425 break;
426 case DRM_FORMAT_YUYV:
427 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800428 break;
429 case DRM_FORMAT_YVYU:
430 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800431 break;
432 case DRM_FORMAT_UYVY:
433 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800434 break;
435 case DRM_FORMAT_VYUY:
436 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800437 break;
438 default:
Ville Syrjälä28d491d2012-10-31 17:50:21 +0200439 BUG();
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800440 }
441
442 if (obj->tiling_mode != I915_TILING_NONE)
443 dvscntr |= DVS_TILED;
444
Chris Wilsond1686ae2012-04-10 11:41:49 +0100445 if (IS_GEN6(dev))
446 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800447 dvscntr |= DVS_ENABLE;
448
449 /* Sizes are 0 based */
450 src_w--;
451 src_h--;
452 crtc_w--;
453 crtc_h--;
454
455 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
456
Chris Wilson8aaa81a2012-04-14 22:14:26 +0100457 dvsscale = 0;
458 if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800459 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
460
461 I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
462 I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800463
Chris Wilsonca320ac2012-12-19 12:14:22 +0000464 linear_offset = y * fb->pitches[0] + x * pixel_size;
Damien Lespiau5a35e992012-10-26 18:20:12 +0100465 dvssurf_offset =
Chris Wilsonbc752862013-02-21 20:04:31 +0000466 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
467 pixel_size, fb->pitches[0]);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100468 linear_offset -= dvssurf_offset;
469
470 if (obj->tiling_mode != I915_TILING_NONE)
471 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
472 else
473 I915_WRITE(DVSLINOFF(pipe), linear_offset);
474
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800475 I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
476 I915_WRITE(DVSSCALE(pipe), dvsscale);
477 I915_WRITE(DVSCNTR(pipe), dvscntr);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100478 I915_MODIFY_DISPBASE(DVSSURF(pipe), obj->gtt_offset + dvssurf_offset);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800479 POSTING_READ(DVSSURF(pipe));
480}
481
482static void
Chris Wilsond1686ae2012-04-10 11:41:49 +0100483ilk_disable_plane(struct drm_plane *plane)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800484{
485 struct drm_device *dev = plane->dev;
486 struct drm_i915_private *dev_priv = dev->dev_private;
487 struct intel_plane *intel_plane = to_intel_plane(plane);
488 int pipe = intel_plane->pipe;
489
490 I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
491 /* Disable the scaler */
492 I915_WRITE(DVSSCALE(pipe), 0);
493 /* Flush double buffered register updates */
Armin Reese446f2542012-03-30 16:20:16 -0700494 I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800495 POSTING_READ(DVSSURF(pipe));
496}
497
Jesse Barnes175bd422011-12-13 13:19:39 -0800498static void
499intel_enable_primary(struct drm_crtc *crtc)
500{
501 struct drm_device *dev = crtc->dev;
502 struct drm_i915_private *dev_priv = dev->dev_private;
503 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
504 int reg = DSPCNTR(intel_crtc->plane);
505
Chris Wilson93314b52012-06-13 17:36:55 +0100506 if (!intel_crtc->primary_disabled)
507 return;
508
509 intel_crtc->primary_disabled = false;
510 intel_update_fbc(dev);
511
Jesse Barnes175bd422011-12-13 13:19:39 -0800512 I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
513}
514
515static void
516intel_disable_primary(struct drm_crtc *crtc)
517{
518 struct drm_device *dev = crtc->dev;
519 struct drm_i915_private *dev_priv = dev->dev_private;
520 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
521 int reg = DSPCNTR(intel_crtc->plane);
522
Chris Wilson93314b52012-06-13 17:36:55 +0100523 if (intel_crtc->primary_disabled)
524 return;
525
Jesse Barnes175bd422011-12-13 13:19:39 -0800526 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
Chris Wilson93314b52012-06-13 17:36:55 +0100527
528 intel_crtc->primary_disabled = true;
529 intel_update_fbc(dev);
Jesse Barnes175bd422011-12-13 13:19:39 -0800530}
531
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800532static int
Chris Wilsond1686ae2012-04-10 11:41:49 +0100533ilk_update_colorkey(struct drm_plane *plane,
Jesse Barnes8ea30862012-01-03 08:05:39 -0800534 struct drm_intel_sprite_colorkey *key)
535{
536 struct drm_device *dev = plane->dev;
537 struct drm_i915_private *dev_priv = dev->dev_private;
538 struct intel_plane *intel_plane;
539 u32 dvscntr;
540 int ret = 0;
541
542 intel_plane = to_intel_plane(plane);
543
544 I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
545 I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
546 I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
547
548 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
549 dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
550 if (key->flags & I915_SET_COLORKEY_DESTINATION)
551 dvscntr |= DVS_DEST_KEY;
552 else if (key->flags & I915_SET_COLORKEY_SOURCE)
553 dvscntr |= DVS_SOURCE_KEY;
554 I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
555
556 POSTING_READ(DVSKEYMSK(intel_plane->pipe));
557
558 return ret;
559}
560
561static void
Chris Wilsond1686ae2012-04-10 11:41:49 +0100562ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
Jesse Barnes8ea30862012-01-03 08:05:39 -0800563{
564 struct drm_device *dev = plane->dev;
565 struct drm_i915_private *dev_priv = dev->dev_private;
566 struct intel_plane *intel_plane;
567 u32 dvscntr;
568
569 intel_plane = to_intel_plane(plane);
570
571 key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
572 key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
573 key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
574 key->flags = 0;
575
576 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
577
578 if (dvscntr & DVS_DEST_KEY)
579 key->flags = I915_SET_COLORKEY_DESTINATION;
580 else if (dvscntr & DVS_SOURCE_KEY)
581 key->flags = I915_SET_COLORKEY_SOURCE;
582 else
583 key->flags = I915_SET_COLORKEY_NONE;
584}
585
586static int
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800587intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
588 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
589 unsigned int crtc_w, unsigned int crtc_h,
590 uint32_t src_x, uint32_t src_y,
591 uint32_t src_w, uint32_t src_h)
592{
593 struct drm_device *dev = plane->dev;
594 struct drm_i915_private *dev_priv = dev->dev_private;
595 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
596 struct intel_plane *intel_plane = to_intel_plane(plane);
597 struct intel_framebuffer *intel_fb;
598 struct drm_i915_gem_object *obj, *old_obj;
599 int pipe = intel_plane->pipe;
Paulo Zanoni702e7a52012-10-23 18:29:59 -0200600 enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
601 pipe);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800602 int ret = 0;
603 int x = src_x >> 16, y = src_y >> 16;
604 int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
605 bool disable_primary = false;
606
607 intel_fb = to_intel_framebuffer(fb);
608 obj = intel_fb->obj;
609
610 old_obj = intel_plane->obj;
611
Jesse Barnes5e1bac22013-03-26 09:25:43 -0700612 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
Jesse Barnesb4db1e32012-03-20 10:59:09 -0700621 src_w = src_w >> 16;
622 src_h = src_h >> 16;
623
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800624 /* Pipe must be running... */
Paulo Zanoni702e7a52012-10-23 18:29:59 -0200625 if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE))
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800626 return -EINVAL;
627
628 if (crtc_x >= primary_w || crtc_y >= primary_h)
629 return -EINVAL;
630
631 /* Don't modify another pipe's plane */
632 if (intel_plane->pipe != intel_crtc->pipe)
633 return -EINVAL;
634
Damien Lespiau94c64192012-10-29 15:14:51 +0000635 /* Sprite planes can be linear or x-tiled surfaces */
636 switch (obj->tiling_mode) {
637 case I915_TILING_NONE:
638 case I915_TILING_X:
639 break;
640 default:
641 return -EINVAL;
642 }
643
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800644 /*
645 * Clamp the width & height into the visible area. Note we don't
646 * try to scale the source if part of the visible region is offscreen.
647 * The caller must handle that by adjusting source offset and size.
648 */
649 if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) {
650 crtc_w += crtc_x;
651 crtc_x = 0;
652 }
653 if ((crtc_x + crtc_w) <= 0) /* Nothing to display */
654 goto out;
655 if ((crtc_x + crtc_w) > primary_w)
656 crtc_w = primary_w - crtc_x;
657
658 if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) {
659 crtc_h += crtc_y;
660 crtc_y = 0;
661 }
662 if ((crtc_y + crtc_h) <= 0) /* Nothing to display */
663 goto out;
664 if (crtc_y + crtc_h > primary_h)
665 crtc_h = primary_h - crtc_y;
666
667 if (!crtc_w || !crtc_h) /* Again, nothing to display */
668 goto out;
669
670 /*
Damien Lespiau2d354c32012-10-22 18:19:27 +0100671 * We may not have a scaler, eg. HSW does not have it any more
672 */
673 if (!intel_plane->can_scale && (crtc_w != src_w || crtc_h != src_h))
674 return -EINVAL;
675
676 /*
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800677 * We can take a larger source and scale it down, but
678 * only so much... 16x is the max on SNB.
679 */
680 if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
681 return -EINVAL;
682
683 /*
684 * If the sprite is completely covering the primary plane,
685 * we can disable the primary and save power.
686 */
687 if ((crtc_x == 0) && (crtc_y == 0) &&
688 (crtc_w == primary_w) && (crtc_h == primary_h))
689 disable_primary = true;
690
691 mutex_lock(&dev->struct_mutex);
692
Chris Wilson693db182013-03-05 14:52:39 +0000693 /* 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 */
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800698 ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
Jesse Barnes00c2064b2012-01-13 15:48:39 -0800699 if (ret)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800700 goto out_unlock;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800701
702 intel_plane->obj = obj;
703
Jesse Barnes175bd422011-12-13 13:19:39 -0800704 /*
705 * Be sure to re-enable the primary before the sprite is no longer
706 * covering it fully.
707 */
Chris Wilson93314b52012-06-13 17:36:55 +0100708 if (!disable_primary)
Jesse Barnes175bd422011-12-13 13:19:39 -0800709 intel_enable_primary(crtc);
Jesse Barnes175bd422011-12-13 13:19:39 -0800710
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800711 intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
712 crtc_w, crtc_h, x, y, src_w, src_h);
713
Chris Wilson93314b52012-06-13 17:36:55 +0100714 if (disable_primary)
Jesse Barnes175bd422011-12-13 13:19:39 -0800715 intel_disable_primary(crtc);
Jesse Barnes175bd422011-12-13 13:19:39 -0800716
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800717 /* Unpin old obj after new one is active to avoid ugliness */
718 if (old_obj) {
719 /*
720 * It's fairly common to simply update the position of
721 * an existing object. In that case, we don't need to
722 * wait for vblank to avoid ugliness, we only need to
723 * do the pin & ref bookkeeping.
724 */
725 if (old_obj != obj) {
726 mutex_unlock(&dev->struct_mutex);
727 intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
728 mutex_lock(&dev->struct_mutex);
729 }
Chris Wilson1690e1e2011-12-14 13:57:08 +0100730 intel_unpin_fb_obj(old_obj);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800731 }
732
733out_unlock:
734 mutex_unlock(&dev->struct_mutex);
735out:
736 return ret;
737}
738
739static int
740intel_disable_plane(struct drm_plane *plane)
741{
742 struct drm_device *dev = plane->dev;
743 struct intel_plane *intel_plane = to_intel_plane(plane);
744 int ret = 0;
745
Chris Wilson93314b52012-06-13 17:36:55 +0100746 if (plane->crtc)
Jesse Barnes175bd422011-12-13 13:19:39 -0800747 intel_enable_primary(plane->crtc);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800748 intel_plane->disable_plane(plane);
749
750 if (!intel_plane->obj)
751 goto out;
752
Ville Syrjäläc626d312013-03-27 17:49:13 +0200753 intel_wait_for_vblank(dev, intel_plane->pipe);
754
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800755 mutex_lock(&dev->struct_mutex);
Chris Wilson1690e1e2011-12-14 13:57:08 +0100756 intel_unpin_fb_obj(intel_plane->obj);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800757 intel_plane->obj = NULL;
758 mutex_unlock(&dev->struct_mutex);
759out:
760
761 return ret;
762}
763
764static void intel_destroy_plane(struct drm_plane *plane)
765{
766 struct intel_plane *intel_plane = to_intel_plane(plane);
767 intel_disable_plane(plane);
768 drm_plane_cleanup(plane);
769 kfree(intel_plane);
770}
771
Jesse Barnes8ea30862012-01-03 08:05:39 -0800772int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
773 struct drm_file *file_priv)
774{
775 struct drm_intel_sprite_colorkey *set = data;
Jesse Barnes8ea30862012-01-03 08:05:39 -0800776 struct drm_mode_object *obj;
777 struct drm_plane *plane;
778 struct intel_plane *intel_plane;
779 int ret = 0;
780
Daniel Vetter1cff8f62012-04-24 09:55:08 +0200781 if (!drm_core_check_feature(dev, DRIVER_MODESET))
782 return -ENODEV;
Jesse Barnes8ea30862012-01-03 08:05:39 -0800783
784 /* Make sure we don't try to enable both src & dest simultaneously */
785 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
786 return -EINVAL;
787
Daniel Vettera0e99e62012-12-02 01:05:46 +0100788 drm_modeset_lock_all(dev);
Jesse Barnes8ea30862012-01-03 08:05:39 -0800789
790 obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
791 if (!obj) {
792 ret = -EINVAL;
793 goto out_unlock;
794 }
795
796 plane = obj_to_plane(obj);
797 intel_plane = to_intel_plane(plane);
798 ret = intel_plane->update_colorkey(plane, set);
799
800out_unlock:
Daniel Vettera0e99e62012-12-02 01:05:46 +0100801 drm_modeset_unlock_all(dev);
Jesse Barnes8ea30862012-01-03 08:05:39 -0800802 return ret;
803}
804
805int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
806 struct drm_file *file_priv)
807{
808 struct drm_intel_sprite_colorkey *get = data;
Jesse Barnes8ea30862012-01-03 08:05:39 -0800809 struct drm_mode_object *obj;
810 struct drm_plane *plane;
811 struct intel_plane *intel_plane;
812 int ret = 0;
813
Daniel Vetter1cff8f62012-04-24 09:55:08 +0200814 if (!drm_core_check_feature(dev, DRIVER_MODESET))
815 return -ENODEV;
Jesse Barnes8ea30862012-01-03 08:05:39 -0800816
Daniel Vettera0e99e62012-12-02 01:05:46 +0100817 drm_modeset_lock_all(dev);
Jesse Barnes8ea30862012-01-03 08:05:39 -0800818
819 obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
820 if (!obj) {
821 ret = -EINVAL;
822 goto out_unlock;
823 }
824
825 plane = obj_to_plane(obj);
826 intel_plane = to_intel_plane(plane);
827 intel_plane->get_colorkey(plane, get);
828
829out_unlock:
Daniel Vettera0e99e62012-12-02 01:05:46 +0100830 drm_modeset_unlock_all(dev);
Jesse Barnes8ea30862012-01-03 08:05:39 -0800831 return ret;
832}
833
Jesse Barnes5e1bac22013-03-26 09:25:43 -0700834void 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
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800848static const struct drm_plane_funcs intel_plane_funcs = {
849 .update_plane = intel_update_plane,
850 .disable_plane = intel_disable_plane,
851 .destroy = intel_destroy_plane,
852};
853
Chris Wilsond1686ae2012-04-10 11:41:49 +0100854static uint32_t ilk_plane_formats[] = {
855 DRM_FORMAT_XRGB8888,
856 DRM_FORMAT_YUYV,
857 DRM_FORMAT_YVYU,
858 DRM_FORMAT_UYVY,
859 DRM_FORMAT_VYUY,
860};
861
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800862static uint32_t snb_plane_formats[] = {
863 DRM_FORMAT_XBGR8888,
864 DRM_FORMAT_XRGB8888,
865 DRM_FORMAT_YUYV,
866 DRM_FORMAT_YVYU,
867 DRM_FORMAT_UYVY,
868 DRM_FORMAT_VYUY,
869};
870
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700871static 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
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800885int
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700886intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800887{
888 struct intel_plane *intel_plane;
889 unsigned long possible_crtcs;
Chris Wilsond1686ae2012-04-10 11:41:49 +0100890 const uint32_t *plane_formats;
891 int num_plane_formats;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800892 int ret;
893
Chris Wilsond1686ae2012-04-10 11:41:49 +0100894 if (INTEL_INFO(dev)->gen < 5)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800895 return -ENODEV;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800896
897 intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
898 if (!intel_plane)
899 return -ENOMEM;
900
Chris Wilsond1686ae2012-04-10 11:41:49 +0100901 switch (INTEL_INFO(dev)->gen) {
902 case 5:
903 case 6:
Damien Lespiau2d354c32012-10-22 18:19:27 +0100904 intel_plane->can_scale = true;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800905 intel_plane->max_downscale = 16;
Chris Wilsond1686ae2012-04-10 11:41:49 +0100906 intel_plane->update_plane = ilk_update_plane;
907 intel_plane->disable_plane = ilk_disable_plane;
908 intel_plane->update_colorkey = ilk_update_colorkey;
909 intel_plane->get_colorkey = ilk_get_colorkey;
910
911 if (IS_GEN6(dev)) {
912 plane_formats = snb_plane_formats;
913 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
914 } else {
915 plane_formats = ilk_plane_formats;
916 num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
917 }
918 break;
919
920 case 7:
Damien Lespiaud49f7092013-04-25 15:15:00 +0100921 if (IS_IVYBRIDGE(dev)) {
Damien Lespiau2d354c32012-10-22 18:19:27 +0100922 intel_plane->can_scale = true;
Damien Lespiaud49f7092013-04-25 15:15:00 +0100923 intel_plane->max_downscale = 2;
924 } else {
925 intel_plane->can_scale = false;
926 intel_plane->max_downscale = 1;
927 }
Chris Wilsond1686ae2012-04-10 11:41:49 +0100928
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700929 if (IS_VALLEYVIEW(dev)) {
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700930 intel_plane->update_plane = vlv_update_plane;
931 intel_plane->disable_plane = vlv_disable_plane;
932 intel_plane->update_colorkey = vlv_update_colorkey;
933 intel_plane->get_colorkey = vlv_get_colorkey;
934
935 plane_formats = vlv_plane_formats;
936 num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
937 } else {
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700938 intel_plane->update_plane = ivb_update_plane;
939 intel_plane->disable_plane = ivb_disable_plane;
940 intel_plane->update_colorkey = ivb_update_colorkey;
941 intel_plane->get_colorkey = ivb_get_colorkey;
942
943 plane_formats = snb_plane_formats;
944 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
945 }
Chris Wilsond1686ae2012-04-10 11:41:49 +0100946 break;
947
948 default:
Jesper Juhla8b0bba2012-06-27 00:55:37 +0200949 kfree(intel_plane);
Chris Wilsond1686ae2012-04-10 11:41:49 +0100950 return -ENODEV;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800951 }
952
953 intel_plane->pipe = pipe;
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700954 intel_plane->plane = plane;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800955 possible_crtcs = (1 << pipe);
956 ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
Chris Wilsond1686ae2012-04-10 11:41:49 +0100957 &intel_plane_funcs,
958 plane_formats, num_plane_formats,
959 false);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800960 if (ret)
961 kfree(intel_plane);
962
963 return ret;
964}