blob: c692adea4332080ba98c2883abc0796dba9a6814 [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>
Ville Syrjälä17316932013-04-24 18:52:38 +030035#include <drm/drm_rect.h>
Jesse Barnesb840d907f2011-12-13 13:19:38 -080036#include "intel_drv.h"
David Howells760285e2012-10-02 18:01:07 +010037#include <drm/i915_drm.h>
Jesse Barnesb840d907f2011-12-13 13:19:38 -080038#include "i915_drv.h"
39
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +030040static bool
41format_is_yuv(uint32_t format)
42{
43 switch (format) {
44 case DRM_FORMAT_YUYV:
45 case DRM_FORMAT_UYVY:
46 case DRM_FORMAT_VYUY:
47 case DRM_FORMAT_YVYU:
48 return true;
49 default:
50 return false;
51 }
52}
53
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030054static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs)
55{
56 /* paranoia */
57 if (!mode->crtc_htotal)
58 return 1;
59
60 return DIV_ROUND_UP(usecs * mode->crtc_clock, 1000 * mode->crtc_htotal);
61}
62
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +020063/**
64 * intel_pipe_update_start() - start update of a set of display registers
65 * @crtc: the crtc of which the registers are going to be updated
66 * @start_vbl_count: vblank counter return pointer used for error checking
67 *
68 * Mark the start of an update to pipe registers that should be updated
69 * atomically regarding vblank. If the next vblank will happens within
70 * the next 100 us, this function waits until the vblank passes.
71 *
72 * After a successful call to this function, interrupts will be disabled
73 * until a subsequent call to intel_pipe_update_end(). That is done to
74 * avoid random delays. The value written to @start_vbl_count should be
75 * supplied to intel_pipe_update_end() for error checking.
76 *
77 * Return: true if the call was successful
78 */
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030079static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
80{
81 struct drm_device *dev = crtc->base.dev;
82 const struct drm_display_mode *mode = &crtc->config.adjusted_mode;
83 enum pipe pipe = crtc->pipe;
84 long timeout = msecs_to_jiffies_timeout(1);
85 int scanline, min, max, vblank_start;
Ville Syrjälä210871b62014-05-22 19:00:50 +030086 wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030087 DEFINE_WAIT(wait);
88
Rob Clark51fd3712013-11-19 12:10:12 -050089 WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex));
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030090
91 vblank_start = mode->crtc_vblank_start;
92 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
93 vblank_start = DIV_ROUND_UP(vblank_start, 2);
94
95 /* FIXME needs to be calibrated sensibly */
96 min = vblank_start - usecs_to_scanlines(mode, 100);
97 max = vblank_start - 1;
98
99 if (min <= 0 || max <= 0)
100 return false;
101
102 if (WARN_ON(drm_vblank_get(dev, pipe)))
103 return false;
104
105 local_irq_disable();
106
Ville Syrjälä25ef2842014-04-29 13:35:48 +0300107 trace_i915_pipe_update_start(crtc, min, max);
108
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300109 for (;;) {
110 /*
111 * prepare_to_wait() has a memory barrier, which guarantees
112 * other CPUs can see the task state update by the time we
113 * read the scanline.
114 */
Ville Syrjälä210871b62014-05-22 19:00:50 +0300115 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300116
117 scanline = intel_get_crtc_scanline(crtc);
118 if (scanline < min || scanline > max)
119 break;
120
121 if (timeout <= 0) {
122 DRM_ERROR("Potential atomic update failure on pipe %c\n",
123 pipe_name(crtc->pipe));
124 break;
125 }
126
127 local_irq_enable();
128
129 timeout = schedule_timeout(timeout);
130
131 local_irq_disable();
132 }
133
Ville Syrjälä210871b62014-05-22 19:00:50 +0300134 finish_wait(wq, &wait);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300135
136 drm_vblank_put(dev, pipe);
137
138 *start_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
139
Ville Syrjälä25ef2842014-04-29 13:35:48 +0300140 trace_i915_pipe_update_vblank_evaded(crtc, min, max, *start_vbl_count);
141
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300142 return true;
143}
144
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +0200145/**
146 * intel_pipe_update_end() - end update of a set of display registers
147 * @crtc: the crtc of which the registers were updated
148 * @start_vbl_count: start vblank counter (used for error checking)
149 *
150 * Mark the end of an update started with intel_pipe_update_start(). This
151 * re-enables interrupts and verifies the update was actually completed
152 * before a vblank using the value of @start_vbl_count.
153 */
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300154static void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count)
155{
156 struct drm_device *dev = crtc->base.dev;
157 enum pipe pipe = crtc->pipe;
158 u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
159
Ville Syrjälä25ef2842014-04-29 13:35:48 +0300160 trace_i915_pipe_update_end(crtc, end_vbl_count);
161
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300162 local_irq_enable();
163
164 if (start_vbl_count != end_vbl_count)
165 DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u)\n",
166 pipe_name(pipe), start_vbl_count, end_vbl_count);
167}
168
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300169static void intel_update_primary_plane(struct intel_crtc *crtc)
170{
171 struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
172 int reg = DSPCNTR(crtc->plane);
173
174 if (crtc->primary_enabled)
175 I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
176 else
177 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
178}
179
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800180static void
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000181skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
182 struct drm_framebuffer *fb,
183 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
184 unsigned int crtc_w, unsigned int crtc_h,
185 uint32_t x, uint32_t y,
186 uint32_t src_w, uint32_t src_h)
187{
188 struct drm_device *dev = drm_plane->dev;
189 struct drm_i915_private *dev_priv = dev->dev_private;
190 struct intel_plane *intel_plane = to_intel_plane(drm_plane);
191 const int pipe = intel_plane->pipe;
192 const int plane = intel_plane->plane + 1;
193 u32 plane_ctl, stride;
194 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
195
196 plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
197
198 /* Mask out pixel format bits in case we change it */
199 plane_ctl &= ~PLANE_CTL_FORMAT_MASK;
200 plane_ctl &= ~PLANE_CTL_ORDER_RGBX;
201 plane_ctl &= ~PLANE_CTL_YUV422_ORDER_MASK;
202 plane_ctl &= ~PLANE_CTL_TILED_MASK;
203 plane_ctl &= ~PLANE_CTL_ALPHA_MASK;
Sonika Jindal1447dde2014-10-04 10:53:31 +0100204 plane_ctl &= ~PLANE_CTL_ROTATE_MASK;
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000205
206 /* Trickle feed has to be enabled */
207 plane_ctl &= ~PLANE_CTL_TRICKLE_FEED_DISABLE;
208
209 switch (fb->pixel_format) {
210 case DRM_FORMAT_RGB565:
211 plane_ctl |= PLANE_CTL_FORMAT_RGB_565;
212 break;
213 case DRM_FORMAT_XBGR8888:
214 plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
215 break;
216 case DRM_FORMAT_XRGB8888:
217 plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888;
218 break;
219 /*
220 * XXX: For ARBG/ABGR formats we default to expecting scanout buffers
221 * to be already pre-multiplied. We need to add a knob (or a different
222 * DRM_FORMAT) for user-space to configure that.
223 */
224 case DRM_FORMAT_ABGR8888:
225 plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888 |
226 PLANE_CTL_ORDER_RGBX |
227 PLANE_CTL_ALPHA_SW_PREMULTIPLY;
228 break;
229 case DRM_FORMAT_ARGB8888:
230 plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888 |
231 PLANE_CTL_ALPHA_SW_PREMULTIPLY;
232 break;
233 case DRM_FORMAT_YUYV:
234 plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
235 break;
236 case DRM_FORMAT_YVYU:
237 plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YVYU;
238 break;
239 case DRM_FORMAT_UYVY:
240 plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY;
241 break;
242 case DRM_FORMAT_VYUY:
243 plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
244 break;
245 default:
246 BUG();
247 }
248
249 switch (obj->tiling_mode) {
250 case I915_TILING_NONE:
251 stride = fb->pitches[0] >> 6;
252 break;
253 case I915_TILING_X:
254 plane_ctl |= PLANE_CTL_TILED_X;
255 stride = fb->pitches[0] >> 9;
256 break;
257 default:
258 BUG();
259 }
Sonika Jindal1447dde2014-10-04 10:53:31 +0100260 if (intel_plane->rotation == BIT(DRM_ROTATE_180))
261 plane_ctl |= PLANE_CTL_ROTATE_180;
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000262
263 plane_ctl |= PLANE_CTL_ENABLE;
264 plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
265
266 intel_update_sprite_watermarks(drm_plane, crtc, src_w, src_h,
267 pixel_size, true,
268 src_w != crtc_w || src_h != crtc_h);
269
270 /* Sizes are 0 based */
271 src_w--;
272 src_h--;
273 crtc_w--;
274 crtc_h--;
275
276 I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
277 I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
278 I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
279 I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w);
280 I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
281 I915_WRITE(PLANE_SURF(pipe, plane), i915_gem_obj_ggtt_offset(obj));
282 POSTING_READ(PLANE_SURF(pipe, plane));
283}
284
285static void
286skl_disable_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc)
287{
288 struct drm_device *dev = drm_plane->dev;
289 struct drm_i915_private *dev_priv = dev->dev_private;
290 struct intel_plane *intel_plane = to_intel_plane(drm_plane);
291 const int pipe = intel_plane->pipe;
292 const int plane = intel_plane->plane + 1;
293
294 I915_WRITE(PLANE_CTL(pipe, plane),
295 I915_READ(PLANE_CTL(pipe, plane)) & ~PLANE_CTL_ENABLE);
296
297 /* Activate double buffered register update */
298 I915_WRITE(PLANE_CTL(pipe, plane), 0);
299 POSTING_READ(PLANE_CTL(pipe, plane));
300
301 intel_update_sprite_watermarks(drm_plane, crtc, 0, 0, 0, false, false);
302}
303
304static int
305skl_update_colorkey(struct drm_plane *drm_plane,
306 struct drm_intel_sprite_colorkey *key)
307{
308 struct drm_device *dev = drm_plane->dev;
309 struct drm_i915_private *dev_priv = dev->dev_private;
310 struct intel_plane *intel_plane = to_intel_plane(drm_plane);
311 const int pipe = intel_plane->pipe;
312 const int plane = intel_plane->plane;
313 u32 plane_ctl;
314
315 I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
316 I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
317 I915_WRITE(PLANE_KEYMSK(pipe, plane), key->channel_mask);
318
319 plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
320 plane_ctl &= ~PLANE_CTL_KEY_ENABLE_MASK;
321 if (key->flags & I915_SET_COLORKEY_DESTINATION)
322 plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
323 else if (key->flags & I915_SET_COLORKEY_SOURCE)
324 plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
325 I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
326
327 POSTING_READ(PLANE_CTL(pipe, plane));
328
329 return 0;
330}
331
332static void
333skl_get_colorkey(struct drm_plane *drm_plane,
334 struct drm_intel_sprite_colorkey *key)
335{
336 struct drm_device *dev = drm_plane->dev;
337 struct drm_i915_private *dev_priv = dev->dev_private;
338 struct intel_plane *intel_plane = to_intel_plane(drm_plane);
339 const int pipe = intel_plane->pipe;
340 const int plane = intel_plane->plane;
341 u32 plane_ctl;
342
343 key->min_value = I915_READ(PLANE_KEYVAL(pipe, plane));
344 key->max_value = I915_READ(PLANE_KEYMAX(pipe, plane));
345 key->channel_mask = I915_READ(PLANE_KEYMSK(pipe, plane));
346
347 plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
348
349 switch (plane_ctl & PLANE_CTL_KEY_ENABLE_MASK) {
350 case PLANE_CTL_KEY_ENABLE_DESTINATION:
351 key->flags = I915_SET_COLORKEY_DESTINATION;
352 break;
353 case PLANE_CTL_KEY_ENABLE_SOURCE:
354 key->flags = I915_SET_COLORKEY_SOURCE;
355 break;
356 default:
357 key->flags = I915_SET_COLORKEY_NONE;
358 }
359}
360
361static void
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300362chv_update_csc(struct intel_plane *intel_plane, uint32_t format)
363{
364 struct drm_i915_private *dev_priv = intel_plane->base.dev->dev_private;
365 int plane = intel_plane->plane;
366
367 /* Seems RGB data bypasses the CSC always */
368 if (!format_is_yuv(format))
369 return;
370
371 /*
372 * BT.601 limited range YCbCr -> full range RGB
373 *
374 * |r| | 6537 4769 0| |cr |
375 * |g| = |-3330 4769 -1605| x |y-64|
376 * |b| | 0 4769 8263| |cb |
377 *
378 * Cb and Cr apparently come in as signed already, so no
379 * need for any offset. For Y we need to remove the offset.
380 */
381 I915_WRITE(SPCSCYGOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(-64));
382 I915_WRITE(SPCSCCBOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
383 I915_WRITE(SPCSCCROFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
384
385 I915_WRITE(SPCSCC01(plane), SPCSC_C1(4769) | SPCSC_C0(6537));
386 I915_WRITE(SPCSCC23(plane), SPCSC_C1(-3330) | SPCSC_C0(0));
387 I915_WRITE(SPCSCC45(plane), SPCSC_C1(-1605) | SPCSC_C0(4769));
388 I915_WRITE(SPCSCC67(plane), SPCSC_C1(4769) | SPCSC_C0(0));
389 I915_WRITE(SPCSCC8(plane), SPCSC_C0(8263));
390
391 I915_WRITE(SPCSCYGICLAMP(plane), SPCSC_IMAX(940) | SPCSC_IMIN(64));
392 I915_WRITE(SPCSCCBICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
393 I915_WRITE(SPCSCCRICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
394
395 I915_WRITE(SPCSCYGOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
396 I915_WRITE(SPCSCCBOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
397 I915_WRITE(SPCSCCROCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
398}
399
400static void
Ville Syrjäläb39d53f2013-08-06 22:24:09 +0300401vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
402 struct drm_framebuffer *fb,
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700403 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
404 unsigned int crtc_w, unsigned int crtc_h,
405 uint32_t x, uint32_t y,
406 uint32_t src_w, uint32_t src_h)
407{
408 struct drm_device *dev = dplane->dev;
409 struct drm_i915_private *dev_priv = dev->dev_private;
410 struct intel_plane *intel_plane = to_intel_plane(dplane);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300411 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700412 int pipe = intel_plane->pipe;
413 int plane = intel_plane->plane;
414 u32 sprctl;
415 unsigned long sprsurf_offset, linear_offset;
416 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300417 u32 start_vbl_count;
418 bool atomic_update;
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700419
420 sprctl = I915_READ(SPCNTR(pipe, plane));
421
422 /* Mask out pixel format bits in case we change it */
423 sprctl &= ~SP_PIXFORMAT_MASK;
424 sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
425 sprctl &= ~SP_TILED;
Ville Syrjälä76eebda2014-08-05 11:26:52 +0530426 sprctl &= ~SP_ROTATE_180;
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700427
428 switch (fb->pixel_format) {
429 case DRM_FORMAT_YUYV:
430 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
431 break;
432 case DRM_FORMAT_YVYU:
433 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
434 break;
435 case DRM_FORMAT_UYVY:
436 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
437 break;
438 case DRM_FORMAT_VYUY:
439 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
440 break;
441 case DRM_FORMAT_RGB565:
442 sprctl |= SP_FORMAT_BGR565;
443 break;
444 case DRM_FORMAT_XRGB8888:
445 sprctl |= SP_FORMAT_BGRX8888;
446 break;
447 case DRM_FORMAT_ARGB8888:
448 sprctl |= SP_FORMAT_BGRA8888;
449 break;
450 case DRM_FORMAT_XBGR2101010:
451 sprctl |= SP_FORMAT_RGBX1010102;
452 break;
453 case DRM_FORMAT_ABGR2101010:
454 sprctl |= SP_FORMAT_RGBA1010102;
455 break;
456 case DRM_FORMAT_XBGR8888:
457 sprctl |= SP_FORMAT_RGBX8888;
458 break;
459 case DRM_FORMAT_ABGR8888:
460 sprctl |= SP_FORMAT_RGBA8888;
461 break;
462 default:
463 /*
464 * If we get here one of the upper layers failed to filter
465 * out the unsupported plane formats
466 */
467 BUG();
468 break;
469 }
470
Ville Syrjälä4ea67bc2013-11-18 18:32:38 -0800471 /*
472 * Enable gamma to match primary/cursor plane behaviour.
473 * FIXME should be user controllable via propertiesa.
474 */
475 sprctl |= SP_GAMMA_ENABLE;
476
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700477 if (obj->tiling_mode != I915_TILING_NONE)
478 sprctl |= SP_TILED;
479
480 sprctl |= SP_ENABLE;
481
Damien Lespiaued57cb82014-07-15 09:21:24 +0200482 intel_update_sprite_watermarks(dplane, crtc, src_w, src_h,
483 pixel_size, true,
Ville Syrjälä67ca28f2013-07-05 11:57:14 +0300484 src_w != crtc_w || src_h != crtc_h);
485
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700486 /* Sizes are 0 based */
487 src_w--;
488 src_h--;
489 crtc_w--;
490 crtc_h--;
491
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700492 linear_offset = y * fb->pitches[0] + x * pixel_size;
493 sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
494 obj->tiling_mode,
495 pixel_size,
496 fb->pitches[0]);
497 linear_offset -= sprsurf_offset;
498
Ville Syrjälä76eebda2014-08-05 11:26:52 +0530499 if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
500 sprctl |= SP_ROTATE_180;
501
502 x += src_w;
503 y += src_h;
504 linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
505 }
506
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300507 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
508
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300509 intel_update_primary_plane(intel_crtc);
510
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300511 if (IS_CHERRYVIEW(dev) && pipe == PIPE_B)
512 chv_update_csc(intel_plane, fb->pixel_format);
513
Ville Syrjäläca6ad022014-01-17 20:09:03 +0200514 I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
515 I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
516
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700517 if (obj->tiling_mode != I915_TILING_NONE)
518 I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
519 else
520 I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
521
Ville Syrjäläc14b0482014-10-16 20:52:34 +0300522 I915_WRITE(SPCONSTALPHA(pipe, plane), 0);
523
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700524 I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
525 I915_WRITE(SPCNTR(pipe, plane), sprctl);
Daniel Vetter85ba7b72014-01-24 10:31:44 +0100526 I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
527 sprsurf_offset);
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300528
529 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300530
531 if (atomic_update)
532 intel_pipe_update_end(intel_crtc, start_vbl_count);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700533}
534
535static void
Ville Syrjäläb39d53f2013-08-06 22:24:09 +0300536vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700537{
538 struct drm_device *dev = dplane->dev;
539 struct drm_i915_private *dev_priv = dev->dev_private;
540 struct intel_plane *intel_plane = to_intel_plane(dplane);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300541 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700542 int pipe = intel_plane->pipe;
543 int plane = intel_plane->plane;
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300544 u32 start_vbl_count;
545 bool atomic_update;
546
547 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700548
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300549 intel_update_primary_plane(intel_crtc);
550
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700551 I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
552 ~SP_ENABLE);
553 /* Activate double buffered register update */
Daniel Vetter85ba7b72014-01-24 10:31:44 +0100554 I915_WRITE(SPSURF(pipe, plane), 0);
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300555
556 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
Ville Syrjäläa95fd8c2013-08-06 22:24:12 +0300557
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300558 if (atomic_update)
559 intel_pipe_update_end(intel_crtc, start_vbl_count);
560
Damien Lespiaued57cb82014-07-15 09:21:24 +0200561 intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700562}
563
564static int
565vlv_update_colorkey(struct drm_plane *dplane,
566 struct drm_intel_sprite_colorkey *key)
567{
568 struct drm_device *dev = dplane->dev;
569 struct drm_i915_private *dev_priv = dev->dev_private;
570 struct intel_plane *intel_plane = to_intel_plane(dplane);
571 int pipe = intel_plane->pipe;
572 int plane = intel_plane->plane;
573 u32 sprctl;
574
575 if (key->flags & I915_SET_COLORKEY_DESTINATION)
576 return -EINVAL;
577
578 I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
579 I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
580 I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
581
582 sprctl = I915_READ(SPCNTR(pipe, plane));
583 sprctl &= ~SP_SOURCE_KEY;
584 if (key->flags & I915_SET_COLORKEY_SOURCE)
585 sprctl |= SP_SOURCE_KEY;
586 I915_WRITE(SPCNTR(pipe, plane), sprctl);
587
588 POSTING_READ(SPKEYMSK(pipe, plane));
589
590 return 0;
591}
592
593static void
594vlv_get_colorkey(struct drm_plane *dplane,
595 struct drm_intel_sprite_colorkey *key)
596{
597 struct drm_device *dev = dplane->dev;
598 struct drm_i915_private *dev_priv = dev->dev_private;
599 struct intel_plane *intel_plane = to_intel_plane(dplane);
600 int pipe = intel_plane->pipe;
601 int plane = intel_plane->plane;
602 u32 sprctl;
603
604 key->min_value = I915_READ(SPKEYMINVAL(pipe, plane));
605 key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane));
606 key->channel_mask = I915_READ(SPKEYMSK(pipe, plane));
607
608 sprctl = I915_READ(SPCNTR(pipe, plane));
609 if (sprctl & SP_SOURCE_KEY)
610 key->flags = I915_SET_COLORKEY_SOURCE;
611 else
612 key->flags = I915_SET_COLORKEY_NONE;
613}
614
615static void
Ville Syrjäläb39d53f2013-08-06 22:24:09 +0300616ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
617 struct drm_framebuffer *fb,
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800618 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
619 unsigned int crtc_w, unsigned int crtc_h,
620 uint32_t x, uint32_t y,
621 uint32_t src_w, uint32_t src_h)
622{
623 struct drm_device *dev = plane->dev;
624 struct drm_i915_private *dev_priv = dev->dev_private;
625 struct intel_plane *intel_plane = to_intel_plane(plane);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300626 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800627 int pipe = intel_plane->pipe;
628 u32 sprctl, sprscale = 0;
Damien Lespiau5a35e992012-10-26 18:20:12 +0100629 unsigned long sprsurf_offset, linear_offset;
Ville Syrjälä2bd3c3c2012-10-31 17:50:20 +0200630 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300631 u32 start_vbl_count;
632 bool atomic_update;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800633
634 sprctl = I915_READ(SPRCTL(pipe));
635
636 /* Mask out pixel format bits in case we change it */
637 sprctl &= ~SPRITE_PIXFORMAT_MASK;
638 sprctl &= ~SPRITE_RGB_ORDER_RGBX;
639 sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
Jesse Barnese86fe0d2012-06-26 13:10:11 -0700640 sprctl &= ~SPRITE_TILED;
Ville Syrjälä76eebda2014-08-05 11:26:52 +0530641 sprctl &= ~SPRITE_ROTATE_180;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800642
643 switch (fb->pixel_format) {
644 case DRM_FORMAT_XBGR8888:
Vijay Purushothaman5ee36912012-08-23 12:08:57 +0530645 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800646 break;
647 case DRM_FORMAT_XRGB8888:
Vijay Purushothaman5ee36912012-08-23 12:08:57 +0530648 sprctl |= SPRITE_FORMAT_RGBX888;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800649 break;
650 case DRM_FORMAT_YUYV:
651 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800652 break;
653 case DRM_FORMAT_YVYU:
654 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800655 break;
656 case DRM_FORMAT_UYVY:
657 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800658 break;
659 case DRM_FORMAT_VYUY:
660 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800661 break;
662 default:
Ville Syrjälä28d491d2012-10-31 17:50:21 +0200663 BUG();
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800664 }
665
Ville Syrjälä4ea67bc2013-11-18 18:32:38 -0800666 /*
667 * Enable gamma to match primary/cursor plane behaviour.
668 * FIXME should be user controllable via propertiesa.
669 */
670 sprctl |= SPRITE_GAMMA_ENABLE;
671
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800672 if (obj->tiling_mode != I915_TILING_NONE)
673 sprctl |= SPRITE_TILED;
674
Ville Syrjäläb42c6002013-11-03 13:47:27 +0200675 if (IS_HASWELL(dev) || IS_BROADWELL(dev))
Paulo Zanoni1f5d76d2013-08-23 19:51:28 -0300676 sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
677 else
678 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
679
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800680 sprctl |= SPRITE_ENABLE;
681
Ville Syrjälä6bbfa1c2013-11-02 21:07:39 -0700682 if (IS_HASWELL(dev) || IS_BROADWELL(dev))
Ville Syrjälä86d3efc2013-01-18 19:11:38 +0200683 sprctl |= SPRITE_PIPE_CSC_ENABLE;
684
Damien Lespiaued57cb82014-07-15 09:21:24 +0200685 intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size,
686 true,
Ville Syrjälä67ca28f2013-07-05 11:57:14 +0300687 src_w != crtc_w || src_h != crtc_h);
688
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800689 /* Sizes are 0 based */
690 src_w--;
691 src_h--;
692 crtc_w--;
693 crtc_h--;
694
Ville Syrjälä8553c182013-12-05 15:51:39 +0200695 if (crtc_w != src_w || crtc_h != src_h)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800696 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800697
Chris Wilsonca320ac2012-12-19 12:14:22 +0000698 linear_offset = y * fb->pitches[0] + x * pixel_size;
Damien Lespiau5a35e992012-10-26 18:20:12 +0100699 sprsurf_offset =
Chris Wilsonbc752862013-02-21 20:04:31 +0000700 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
701 pixel_size, fb->pitches[0]);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100702 linear_offset -= sprsurf_offset;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800703
Ville Syrjälä76eebda2014-08-05 11:26:52 +0530704 if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
705 sprctl |= SPRITE_ROTATE_180;
706
707 /* HSW and BDW does this automagically in hardware */
708 if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
709 x += src_w;
710 y += src_h;
711 linear_offset += src_h * fb->pitches[0] +
712 src_w * pixel_size;
713 }
714 }
715
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300716 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
717
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300718 intel_update_primary_plane(intel_crtc);
719
Ville Syrjäläca6ad022014-01-17 20:09:03 +0200720 I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
721 I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
722
Damien Lespiau5a35e992012-10-26 18:20:12 +0100723 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
724 * register */
Paulo Zanonib3dc6852013-11-02 21:07:33 -0700725 if (IS_HASWELL(dev) || IS_BROADWELL(dev))
Damien Lespiau5a35e992012-10-26 18:20:12 +0100726 I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
727 else if (obj->tiling_mode != I915_TILING_NONE)
728 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
729 else
730 I915_WRITE(SPRLINOFF(pipe), linear_offset);
Damien Lespiauc54173a2012-10-26 18:20:11 +0100731
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800732 I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
Damien Lespiau2d354c32012-10-22 18:19:27 +0100733 if (intel_plane->can_scale)
734 I915_WRITE(SPRSCALE(pipe), sprscale);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800735 I915_WRITE(SPRCTL(pipe), sprctl);
Daniel Vetter85ba7b72014-01-24 10:31:44 +0100736 I915_WRITE(SPRSURF(pipe),
737 i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300738
739 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300740
741 if (atomic_update)
742 intel_pipe_update_end(intel_crtc, start_vbl_count);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800743}
744
745static void
Ville Syrjäläb39d53f2013-08-06 22:24:09 +0300746ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800747{
748 struct drm_device *dev = plane->dev;
749 struct drm_i915_private *dev_priv = dev->dev_private;
750 struct intel_plane *intel_plane = to_intel_plane(plane);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300751 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800752 int pipe = intel_plane->pipe;
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300753 u32 start_vbl_count;
754 bool atomic_update;
755
756 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800757
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300758 intel_update_primary_plane(intel_crtc);
759
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800760 I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
761 /* Can't leave the scaler enabled... */
Damien Lespiau2d354c32012-10-22 18:19:27 +0100762 if (intel_plane->can_scale)
763 I915_WRITE(SPRSCALE(pipe), 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800764 /* Activate double buffered register update */
Daniel Vetter85ba7b72014-01-24 10:31:44 +0100765 I915_WRITE(SPRSURF(pipe), 0);
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300766
767 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
Chris Wilson828ed3e2012-04-18 17:12:26 +0100768
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300769 if (atomic_update)
770 intel_pipe_update_end(intel_crtc, start_vbl_count);
771
Ville Syrjälä1bd09ec2013-12-05 15:51:41 +0200772 /*
773 * Avoid underruns when disabling the sprite.
774 * FIXME remove once watermark updates are done properly.
775 */
776 intel_wait_for_vblank(dev, pipe);
777
Damien Lespiaued57cb82014-07-15 09:21:24 +0200778 intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800779}
780
Jesse Barnes8ea30862012-01-03 08:05:39 -0800781static int
782ivb_update_colorkey(struct drm_plane *plane,
783 struct drm_intel_sprite_colorkey *key)
784{
785 struct drm_device *dev = plane->dev;
786 struct drm_i915_private *dev_priv = dev->dev_private;
787 struct intel_plane *intel_plane;
788 u32 sprctl;
789 int ret = 0;
790
791 intel_plane = to_intel_plane(plane);
792
793 I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
794 I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
795 I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
796
797 sprctl = I915_READ(SPRCTL(intel_plane->pipe));
798 sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
799 if (key->flags & I915_SET_COLORKEY_DESTINATION)
800 sprctl |= SPRITE_DEST_KEY;
801 else if (key->flags & I915_SET_COLORKEY_SOURCE)
802 sprctl |= SPRITE_SOURCE_KEY;
803 I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
804
805 POSTING_READ(SPRKEYMSK(intel_plane->pipe));
806
807 return ret;
808}
809
810static void
811ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
812{
813 struct drm_device *dev = plane->dev;
814 struct drm_i915_private *dev_priv = dev->dev_private;
815 struct intel_plane *intel_plane;
816 u32 sprctl;
817
818 intel_plane = to_intel_plane(plane);
819
820 key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
821 key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
822 key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
823 key->flags = 0;
824
825 sprctl = I915_READ(SPRCTL(intel_plane->pipe));
826
827 if (sprctl & SPRITE_DEST_KEY)
828 key->flags = I915_SET_COLORKEY_DESTINATION;
829 else if (sprctl & SPRITE_SOURCE_KEY)
830 key->flags = I915_SET_COLORKEY_SOURCE;
831 else
832 key->flags = I915_SET_COLORKEY_NONE;
833}
834
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800835static void
Ville Syrjäläb39d53f2013-08-06 22:24:09 +0300836ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
837 struct drm_framebuffer *fb,
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800838 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
839 unsigned int crtc_w, unsigned int crtc_h,
840 uint32_t x, uint32_t y,
841 uint32_t src_w, uint32_t src_h)
842{
843 struct drm_device *dev = plane->dev;
844 struct drm_i915_private *dev_priv = dev->dev_private;
845 struct intel_plane *intel_plane = to_intel_plane(plane);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300846 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
Ville Syrjälä2bd3c3c2012-10-31 17:50:20 +0200847 int pipe = intel_plane->pipe;
Damien Lespiau5a35e992012-10-26 18:20:12 +0100848 unsigned long dvssurf_offset, linear_offset;
Chris Wilson8aaa81a2012-04-14 22:14:26 +0100849 u32 dvscntr, dvsscale;
Ville Syrjälä2bd3c3c2012-10-31 17:50:20 +0200850 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300851 u32 start_vbl_count;
852 bool atomic_update;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800853
854 dvscntr = I915_READ(DVSCNTR(pipe));
855
856 /* Mask out pixel format bits in case we change it */
857 dvscntr &= ~DVS_PIXFORMAT_MASK;
Jesse Barnesab2f9df2012-02-27 12:40:10 -0800858 dvscntr &= ~DVS_RGB_ORDER_XBGR;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800859 dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
Ander Conselvan de Oliveira79626522012-07-13 15:50:33 +0300860 dvscntr &= ~DVS_TILED;
Ville Syrjälä76eebda2014-08-05 11:26:52 +0530861 dvscntr &= ~DVS_ROTATE_180;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800862
863 switch (fb->pixel_format) {
864 case DRM_FORMAT_XBGR8888:
Jesse Barnesab2f9df2012-02-27 12:40:10 -0800865 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800866 break;
867 case DRM_FORMAT_XRGB8888:
Jesse Barnesab2f9df2012-02-27 12:40:10 -0800868 dvscntr |= DVS_FORMAT_RGBX888;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800869 break;
870 case DRM_FORMAT_YUYV:
871 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800872 break;
873 case DRM_FORMAT_YVYU:
874 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800875 break;
876 case DRM_FORMAT_UYVY:
877 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800878 break;
879 case DRM_FORMAT_VYUY:
880 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800881 break;
882 default:
Ville Syrjälä28d491d2012-10-31 17:50:21 +0200883 BUG();
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800884 }
885
Ville Syrjälä4ea67bc2013-11-18 18:32:38 -0800886 /*
887 * Enable gamma to match primary/cursor plane behaviour.
888 * FIXME should be user controllable via propertiesa.
889 */
890 dvscntr |= DVS_GAMMA_ENABLE;
891
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800892 if (obj->tiling_mode != I915_TILING_NONE)
893 dvscntr |= DVS_TILED;
894
Chris Wilsond1686ae2012-04-10 11:41:49 +0100895 if (IS_GEN6(dev))
896 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800897 dvscntr |= DVS_ENABLE;
898
Damien Lespiaued57cb82014-07-15 09:21:24 +0200899 intel_update_sprite_watermarks(plane, crtc, src_w, src_h,
900 pixel_size, true,
Ville Syrjälä67ca28f2013-07-05 11:57:14 +0300901 src_w != crtc_w || src_h != crtc_h);
902
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800903 /* Sizes are 0 based */
904 src_w--;
905 src_h--;
906 crtc_w--;
907 crtc_h--;
908
Chris Wilson8aaa81a2012-04-14 22:14:26 +0100909 dvsscale = 0;
Ville Syrjälä8368f012013-12-05 15:51:31 +0200910 if (crtc_w != src_w || crtc_h != src_h)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800911 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
912
Chris Wilsonca320ac2012-12-19 12:14:22 +0000913 linear_offset = y * fb->pitches[0] + x * pixel_size;
Damien Lespiau5a35e992012-10-26 18:20:12 +0100914 dvssurf_offset =
Chris Wilsonbc752862013-02-21 20:04:31 +0000915 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
916 pixel_size, fb->pitches[0]);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100917 linear_offset -= dvssurf_offset;
918
Ville Syrjälä76eebda2014-08-05 11:26:52 +0530919 if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
920 dvscntr |= DVS_ROTATE_180;
921
922 x += src_w;
923 y += src_h;
924 linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
925 }
926
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300927 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
928
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300929 intel_update_primary_plane(intel_crtc);
930
Ville Syrjäläca6ad022014-01-17 20:09:03 +0200931 I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
932 I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
933
Damien Lespiau5a35e992012-10-26 18:20:12 +0100934 if (obj->tiling_mode != I915_TILING_NONE)
935 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
936 else
937 I915_WRITE(DVSLINOFF(pipe), linear_offset);
938
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800939 I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
940 I915_WRITE(DVSSCALE(pipe), dvsscale);
941 I915_WRITE(DVSCNTR(pipe), dvscntr);
Daniel Vetter85ba7b72014-01-24 10:31:44 +0100942 I915_WRITE(DVSSURF(pipe),
943 i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300944
945 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300946
947 if (atomic_update)
948 intel_pipe_update_end(intel_crtc, start_vbl_count);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800949}
950
951static void
Ville Syrjäläb39d53f2013-08-06 22:24:09 +0300952ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800953{
954 struct drm_device *dev = plane->dev;
955 struct drm_i915_private *dev_priv = dev->dev_private;
956 struct intel_plane *intel_plane = to_intel_plane(plane);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300957 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800958 int pipe = intel_plane->pipe;
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300959 u32 start_vbl_count;
960 bool atomic_update;
961
962 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800963
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300964 intel_update_primary_plane(intel_crtc);
965
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800966 I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
967 /* Disable the scaler */
968 I915_WRITE(DVSSCALE(pipe), 0);
969 /* Flush double buffered register updates */
Daniel Vetter85ba7b72014-01-24 10:31:44 +0100970 I915_WRITE(DVSSURF(pipe), 0);
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300971
972 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
Ville Syrjäläa95fd8c2013-08-06 22:24:12 +0300973
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300974 if (atomic_update)
975 intel_pipe_update_end(intel_crtc, start_vbl_count);
976
Ville Syrjälä1bd09ec2013-12-05 15:51:41 +0200977 /*
978 * Avoid underruns when disabling the sprite.
979 * FIXME remove once watermark updates are done properly.
980 */
981 intel_wait_for_vblank(dev, pipe);
982
Damien Lespiaued57cb82014-07-15 09:21:24 +0200983 intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800984}
985
Jesse Barnes175bd422011-12-13 13:19:39 -0800986static void
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300987intel_post_enable_primary(struct drm_crtc *crtc)
Jesse Barnes175bd422011-12-13 13:19:39 -0800988{
989 struct drm_device *dev = crtc->dev;
Jesse Barnes175bd422011-12-13 13:19:39 -0800990 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
Ville Syrjäläabae50e2013-10-01 18:02:16 +0300991
Ville Syrjälä20bc86732013-10-01 18:02:17 +0300992 /*
Ville Syrjälä33c3b0d2014-06-24 13:59:28 +0300993 * BDW signals flip done immediately if the plane
994 * is disabled, even if the plane enable is already
995 * armed to occur at the next vblank :(
996 */
997 if (IS_BROADWELL(dev))
998 intel_wait_for_vblank(dev, intel_crtc->pipe);
999
1000 /*
Ville Syrjälä20bc86732013-10-01 18:02:17 +03001001 * FIXME IPS should be fine as long as one plane is
1002 * enabled, but in practice it seems to have problems
1003 * when going from primary only to sprite only and vice
1004 * versa.
1005 */
Ville Syrjäläcea165c2014-04-15 21:41:35 +03001006 hsw_enable_ips(intel_crtc);
Ville Syrjälä20bc86732013-10-01 18:02:17 +03001007
Ville Syrjälä82284b62013-10-01 18:02:12 +03001008 mutex_lock(&dev->struct_mutex);
Chris Wilson93314b52012-06-13 17:36:55 +01001009 intel_update_fbc(dev);
Ville Syrjälä82284b62013-10-01 18:02:12 +03001010 mutex_unlock(&dev->struct_mutex);
Jesse Barnes175bd422011-12-13 13:19:39 -08001011}
1012
1013static void
Ville Syrjälä5b633d62014-04-29 13:35:47 +03001014intel_pre_disable_primary(struct drm_crtc *crtc)
Jesse Barnes175bd422011-12-13 13:19:39 -08001015{
1016 struct drm_device *dev = crtc->dev;
1017 struct drm_i915_private *dev_priv = dev->dev_private;
1018 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
Ville Syrjälä82284b62013-10-01 18:02:12 +03001019
1020 mutex_lock(&dev->struct_mutex);
Ville Syrjäläabae50e2013-10-01 18:02:16 +03001021 if (dev_priv->fbc.plane == intel_crtc->plane)
1022 intel_disable_fbc(dev);
Ville Syrjälä82284b62013-10-01 18:02:12 +03001023 mutex_unlock(&dev->struct_mutex);
Ville Syrjäläabae50e2013-10-01 18:02:16 +03001024
Ville Syrjälä20bc86732013-10-01 18:02:17 +03001025 /*
1026 * FIXME IPS should be fine as long as one plane is
1027 * enabled, but in practice it seems to have problems
1028 * when going from primary only to sprite only and vice
1029 * versa.
1030 */
1031 hsw_disable_ips(intel_crtc);
Jesse Barnes175bd422011-12-13 13:19:39 -08001032}
1033
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001034static int
Chris Wilsond1686ae2012-04-10 11:41:49 +01001035ilk_update_colorkey(struct drm_plane *plane,
Jesse Barnes8ea30862012-01-03 08:05:39 -08001036 struct drm_intel_sprite_colorkey *key)
1037{
1038 struct drm_device *dev = plane->dev;
1039 struct drm_i915_private *dev_priv = dev->dev_private;
1040 struct intel_plane *intel_plane;
1041 u32 dvscntr;
1042 int ret = 0;
1043
1044 intel_plane = to_intel_plane(plane);
1045
1046 I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
1047 I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
1048 I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
1049
1050 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
1051 dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
1052 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1053 dvscntr |= DVS_DEST_KEY;
1054 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1055 dvscntr |= DVS_SOURCE_KEY;
1056 I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
1057
1058 POSTING_READ(DVSKEYMSK(intel_plane->pipe));
1059
1060 return ret;
1061}
1062
1063static void
Chris Wilsond1686ae2012-04-10 11:41:49 +01001064ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
Jesse Barnes8ea30862012-01-03 08:05:39 -08001065{
1066 struct drm_device *dev = plane->dev;
1067 struct drm_i915_private *dev_priv = dev->dev_private;
1068 struct intel_plane *intel_plane;
1069 u32 dvscntr;
1070
1071 intel_plane = to_intel_plane(plane);
1072
1073 key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
1074 key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
1075 key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
1076 key->flags = 0;
1077
1078 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
1079
1080 if (dvscntr & DVS_DEST_KEY)
1081 key->flags = I915_SET_COLORKEY_DESTINATION;
1082 else if (dvscntr & DVS_SOURCE_KEY)
1083 key->flags = I915_SET_COLORKEY_SOURCE;
1084 else
1085 key->flags = I915_SET_COLORKEY_NONE;
1086}
1087
Ville Syrjäläefb31d12013-12-05 15:51:40 +02001088static bool colorkey_enabled(struct intel_plane *intel_plane)
1089{
1090 struct drm_intel_sprite_colorkey key;
1091
1092 intel_plane->get_colorkey(&intel_plane->base, &key);
1093
1094 return key.flags != I915_SET_COLORKEY_NONE;
1095}
1096
Jesse Barnes8ea30862012-01-03 08:05:39 -08001097static int
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001098intel_check_sprite_plane(struct drm_plane *plane,
1099 struct intel_plane_state *state)
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001100{
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001101 struct intel_crtc *intel_crtc = to_intel_crtc(state->crtc);
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001102 struct intel_plane *intel_plane = to_intel_plane(plane);
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001103 struct drm_framebuffer *fb = state->fb;
Gustavo Padovan77cde952014-10-24 14:51:33 +01001104 struct drm_i915_gem_object *obj = intel_fb_obj(fb);
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001105 int crtc_x, crtc_y;
1106 unsigned int crtc_w, crtc_h;
1107 uint32_t src_x, src_y, src_w, src_h;
1108 struct drm_rect *src = &state->src;
1109 struct drm_rect *dst = &state->dst;
1110 struct drm_rect *orig_src = &state->orig_src;
1111 const struct drm_rect *clip = &state->clip;
Ville Syrjälä17316932013-04-24 18:52:38 +03001112 int hscale, vscale;
1113 int max_scale, min_scale;
1114 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
Jesse Barnes5e1bac22013-03-26 09:25:43 -07001115
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001116 /* Don't modify another pipe's plane */
Ville Syrjälä17316932013-04-24 18:52:38 +03001117 if (intel_plane->pipe != intel_crtc->pipe) {
1118 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001119 return -EINVAL;
Ville Syrjälä17316932013-04-24 18:52:38 +03001120 }
1121
1122 /* FIXME check all gen limits */
1123 if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) {
1124 DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
1125 return -EINVAL;
1126 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001127
Damien Lespiau94c64192012-10-29 15:14:51 +00001128 /* Sprite planes can be linear or x-tiled surfaces */
1129 switch (obj->tiling_mode) {
1130 case I915_TILING_NONE:
1131 case I915_TILING_X:
1132 break;
1133 default:
Ville Syrjälä17316932013-04-24 18:52:38 +03001134 DRM_DEBUG_KMS("Unsupported tiling mode\n");
Damien Lespiau94c64192012-10-29 15:14:51 +00001135 return -EINVAL;
1136 }
1137
Ville Syrjälä3c3686c2013-04-24 18:52:39 +03001138 /*
1139 * FIXME the following code does a bunch of fuzzy adjustments to the
1140 * coordinates and sizes. We probably need some way to decide whether
1141 * more strict checking should be done instead.
1142 */
Ville Syrjälä17316932013-04-24 18:52:38 +03001143 max_scale = intel_plane->max_downscale << 16;
1144 min_scale = intel_plane->can_scale ? 1 : (1 << 16);
1145
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001146 drm_rect_rotate(src, fb->width << 16, fb->height << 16,
Ville Syrjälä76eebda2014-08-05 11:26:52 +05301147 intel_plane->rotation);
1148
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001149 hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
Ville Syrjälä3c3686c2013-04-24 18:52:39 +03001150 BUG_ON(hscale < 0);
Ville Syrjälä17316932013-04-24 18:52:38 +03001151
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001152 vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
Ville Syrjälä3c3686c2013-04-24 18:52:39 +03001153 BUG_ON(vscale < 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001154
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001155 state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001156
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001157 crtc_x = dst->x1;
1158 crtc_y = dst->y1;
1159 crtc_w = drm_rect_width(dst);
1160 crtc_h = drm_rect_height(dst);
Damien Lespiau2d354c32012-10-22 18:19:27 +01001161
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001162 if (state->visible) {
Ville Syrjälä3c3686c2013-04-24 18:52:39 +03001163 /* check again in case clipping clamped the results */
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001164 hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
Ville Syrjälä3c3686c2013-04-24 18:52:39 +03001165 if (hscale < 0) {
1166 DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001167 drm_rect_debug_print(src, true);
1168 drm_rect_debug_print(dst, false);
Ville Syrjälä3c3686c2013-04-24 18:52:39 +03001169
1170 return hscale;
1171 }
1172
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001173 vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
Ville Syrjälä3c3686c2013-04-24 18:52:39 +03001174 if (vscale < 0) {
1175 DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001176 drm_rect_debug_print(src, true);
1177 drm_rect_debug_print(dst, false);
Ville Syrjälä3c3686c2013-04-24 18:52:39 +03001178
1179 return vscale;
1180 }
1181
Ville Syrjälä17316932013-04-24 18:52:38 +03001182 /* Make the source viewport size an exact multiple of the scaling factors. */
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001183 drm_rect_adjust_size(src,
1184 drm_rect_width(dst) * hscale - drm_rect_width(src),
1185 drm_rect_height(dst) * vscale - drm_rect_height(src));
Ville Syrjälä17316932013-04-24 18:52:38 +03001186
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001187 drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
Ville Syrjälä76eebda2014-08-05 11:26:52 +05301188 intel_plane->rotation);
1189
Ville Syrjälä17316932013-04-24 18:52:38 +03001190 /* sanity check to make sure the src viewport wasn't enlarged */
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001191 WARN_ON(src->x1 < (int) orig_src->x1 ||
1192 src->y1 < (int) orig_src->y1 ||
1193 src->x2 > (int) orig_src->x2 ||
1194 src->y2 > (int) orig_src->y2);
Ville Syrjälä17316932013-04-24 18:52:38 +03001195
1196 /*
1197 * Hardware doesn't handle subpixel coordinates.
1198 * Adjust to (macro)pixel boundary, but be careful not to
1199 * increase the source viewport size, because that could
1200 * push the downscaling factor out of bounds.
Ville Syrjälä17316932013-04-24 18:52:38 +03001201 */
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001202 src_x = src->x1 >> 16;
1203 src_w = drm_rect_width(src) >> 16;
1204 src_y = src->y1 >> 16;
1205 src_h = drm_rect_height(src) >> 16;
Ville Syrjälä17316932013-04-24 18:52:38 +03001206
1207 if (format_is_yuv(fb->pixel_format)) {
1208 src_x &= ~1;
1209 src_w &= ~1;
1210
1211 /*
1212 * Must keep src and dst the
1213 * same if we can't scale.
1214 */
1215 if (!intel_plane->can_scale)
1216 crtc_w &= ~1;
1217
1218 if (crtc_w == 0)
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001219 state->visible = false;
Ville Syrjälä17316932013-04-24 18:52:38 +03001220 }
1221 }
1222
1223 /* Check size restrictions when scaling */
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001224 if (state->visible && (src_w != crtc_w || src_h != crtc_h)) {
Ville Syrjälä17316932013-04-24 18:52:38 +03001225 unsigned int width_bytes;
1226
1227 WARN_ON(!intel_plane->can_scale);
1228
1229 /* FIXME interlacing min height is 6 */
1230
1231 if (crtc_w < 3 || crtc_h < 3)
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001232 state->visible = false;
Ville Syrjälä17316932013-04-24 18:52:38 +03001233
1234 if (src_w < 3 || src_h < 3)
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001235 state->visible = false;
Ville Syrjälä17316932013-04-24 18:52:38 +03001236
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001237 width_bytes = ((src_x * pixel_size) & 63) +
1238 src_w * pixel_size;
Ville Syrjälä17316932013-04-24 18:52:38 +03001239
1240 if (src_w > 2048 || src_h > 2048 ||
1241 width_bytes > 4096 || fb->pitches[0] > 4096) {
1242 DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
1243 return -EINVAL;
1244 }
1245 }
1246
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001247 if (state->visible) {
1248 src->x1 = src_x;
1249 src->x2 = src_x + src_w;
1250 src->y1 = src_y;
1251 src->y2 = src_y + src_h;
1252 }
1253
1254 dst->x1 = crtc_x;
1255 dst->x2 = crtc_x + crtc_w;
1256 dst->y1 = crtc_y;
1257 dst->y2 = crtc_y + crtc_h;
1258
1259 return 0;
1260}
1261
1262static int
Gustavo Padovan34aa50a2014-10-24 14:51:32 +01001263intel_prepare_sprite_plane(struct drm_plane *plane,
1264 struct intel_plane_state *state)
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001265{
1266 struct drm_device *dev = plane->dev;
1267 struct drm_crtc *crtc = state->crtc;
1268 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001269 enum pipe pipe = intel_crtc->pipe;
1270 struct drm_framebuffer *fb = state->fb;
Gustavo Padovan34aa50a2014-10-24 14:51:32 +01001271 struct drm_i915_gem_object *obj = intel_fb_obj(fb);
1272 struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001273 int ret;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001274
Gustavo Padovan25067bf2014-09-10 12:03:17 -03001275 if (old_obj != obj) {
1276 mutex_lock(&dev->struct_mutex);
Ville Syrjälä82284b62013-10-01 18:02:12 +03001277
Gustavo Padovan25067bf2014-09-10 12:03:17 -03001278 /* Note that this will apply the VT-d workaround for scanouts,
1279 * which is more restrictive than required for sprites. (The
1280 * primary plane requires 256KiB alignment with 64 PTE padding,
1281 * the sprite planes only require 128KiB alignment and 32 PTE
1282 * padding.
1283 */
Tvrtko Ursulin850c4cd2014-10-30 16:39:38 +00001284 ret = intel_pin_and_fence_fb_obj(plane, fb, NULL);
Gustavo Padovan25067bf2014-09-10 12:03:17 -03001285 if (ret == 0)
1286 i915_gem_track_fb(old_obj, obj,
1287 INTEL_FRONTBUFFER_SPRITE(pipe));
1288 mutex_unlock(&dev->struct_mutex);
1289 if (ret)
1290 return ret;
1291 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001292
Gustavo Padovan34aa50a2014-10-24 14:51:32 +01001293 return 0;
1294}
1295
1296static void
1297intel_commit_sprite_plane(struct drm_plane *plane,
1298 struct intel_plane_state *state)
1299{
1300 struct drm_device *dev = plane->dev;
1301 struct drm_crtc *crtc = state->crtc;
1302 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1303 struct intel_plane *intel_plane = to_intel_plane(plane);
1304 enum pipe pipe = intel_crtc->pipe;
1305 struct drm_framebuffer *fb = state->fb;
Gustavo Padovan77cde952014-10-24 14:51:33 +01001306 struct drm_i915_gem_object *obj = intel_fb_obj(fb);
1307 struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
Gustavo Padovan34aa50a2014-10-24 14:51:32 +01001308 int crtc_x, crtc_y;
1309 unsigned int crtc_w, crtc_h;
1310 uint32_t src_x, src_y, src_w, src_h;
1311 struct drm_rect *dst = &state->dst;
1312 const struct drm_rect *clip = &state->clip;
1313 bool primary_enabled;
1314
1315 /*
1316 * If the sprite is completely covering the primary plane,
1317 * we can disable the primary and save power.
1318 */
1319 primary_enabled = !drm_rect_equals(dst, clip) || colorkey_enabled(intel_plane);
1320 WARN_ON(!primary_enabled && !state->visible && intel_crtc->active);
1321
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001322 intel_plane->crtc_x = state->orig_dst.x1;
1323 intel_plane->crtc_y = state->orig_dst.y1;
1324 intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
1325 intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
1326 intel_plane->src_x = state->orig_src.x1;
1327 intel_plane->src_y = state->orig_src.y1;
1328 intel_plane->src_w = drm_rect_width(&state->orig_src);
1329 intel_plane->src_h = drm_rect_height(&state->orig_src);
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001330 intel_plane->obj = obj;
1331
Ville Syrjälä03c5b252013-10-01 18:02:11 +03001332 if (intel_crtc->active) {
Ville Syrjälä5b633d62014-04-29 13:35:47 +03001333 bool primary_was_enabled = intel_crtc->primary_enabled;
1334
1335 intel_crtc->primary_enabled = primary_enabled;
1336
Ville Syrjälä46a55d32014-05-21 14:04:46 +03001337 if (primary_was_enabled != primary_enabled)
1338 intel_crtc_wait_for_pending_flips(crtc);
1339
Ville Syrjälä5b633d62014-04-29 13:35:47 +03001340 if (primary_was_enabled && !primary_enabled)
1341 intel_pre_disable_primary(crtc);
Jesse Barnes175bd422011-12-13 13:19:39 -08001342
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001343 if (state->visible) {
1344 crtc_x = state->dst.x1;
Gustavo Padovane259f172014-09-11 17:42:15 -03001345 crtc_y = state->dst.y1;
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001346 crtc_w = drm_rect_width(&state->dst);
1347 crtc_h = drm_rect_height(&state->dst);
1348 src_x = state->src.x1;
1349 src_y = state->src.y1;
1350 src_w = drm_rect_width(&state->src);
1351 src_h = drm_rect_height(&state->src);
Ville Syrjälä03c5b252013-10-01 18:02:11 +03001352 intel_plane->update_plane(plane, crtc, fb, obj,
1353 crtc_x, crtc_y, crtc_w, crtc_h,
1354 src_x, src_y, src_w, src_h);
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001355 } else {
Ville Syrjälä03c5b252013-10-01 18:02:11 +03001356 intel_plane->disable_plane(plane, crtc);
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001357 }
1358
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001359
Daniel Vetterf99d7062014-06-19 16:01:59 +02001360 intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_SPRITE(pipe));
1361
Ville Syrjälä5b633d62014-04-29 13:35:47 +03001362 if (!primary_was_enabled && primary_enabled)
1363 intel_post_enable_primary(crtc);
Ville Syrjälä03c5b252013-10-01 18:02:11 +03001364 }
Jesse Barnes175bd422011-12-13 13:19:39 -08001365
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001366 /* Unpin old obj after new one is active to avoid ugliness */
Gustavo Padovan25067bf2014-09-10 12:03:17 -03001367 if (old_obj && old_obj != obj) {
1368
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001369 /*
1370 * It's fairly common to simply update the position of
1371 * an existing object. In that case, we don't need to
1372 * wait for vblank to avoid ugliness, we only need to
1373 * do the pin & ref bookkeeping.
1374 */
Gustavo Padovan25067bf2014-09-10 12:03:17 -03001375 if (intel_crtc->active)
Ville Syrjälä2afd9ef2013-10-01 18:02:14 +03001376 intel_wait_for_vblank(dev, intel_crtc->pipe);
Ville Syrjälä82284b62013-10-01 18:02:12 +03001377
1378 mutex_lock(&dev->struct_mutex);
Chris Wilson1690e1e2011-12-14 13:57:08 +01001379 intel_unpin_fb_obj(old_obj);
Ville Syrjälä82284b62013-10-01 18:02:12 +03001380 mutex_unlock(&dev->struct_mutex);
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001381 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001382}
1383
1384static int
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001385intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
1386 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
1387 unsigned int crtc_w, unsigned int crtc_h,
1388 uint32_t src_x, uint32_t src_y,
1389 uint32_t src_w, uint32_t src_h)
1390{
1391 struct intel_plane_state state;
1392 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1393 int ret;
1394
1395 state.crtc = crtc;
1396 state.fb = fb;
1397
1398 /* sample coordinates in 16.16 fixed point */
1399 state.src.x1 = src_x;
1400 state.src.x2 = src_x + src_w;
1401 state.src.y1 = src_y;
1402 state.src.y2 = src_y + src_h;
1403
1404 /* integer pixels */
1405 state.dst.x1 = crtc_x;
1406 state.dst.x2 = crtc_x + crtc_w;
1407 state.dst.y1 = crtc_y;
1408 state.dst.y2 = crtc_y + crtc_h;
1409
1410 state.clip.x1 = 0;
1411 state.clip.y1 = 0;
1412 state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0;
1413 state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0;
1414 state.orig_src = state.src;
1415 state.orig_dst = state.dst;
1416
1417 ret = intel_check_sprite_plane(plane, &state);
1418 if (ret)
1419 return ret;
1420
Gustavo Padovan34aa50a2014-10-24 14:51:32 +01001421 ret = intel_prepare_sprite_plane(plane, &state);
1422 if (ret)
1423 return ret;
1424
1425 intel_commit_sprite_plane(plane, &state);
1426 return 0;
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001427}
1428
1429static int
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001430intel_disable_plane(struct drm_plane *plane)
1431{
1432 struct drm_device *dev = plane->dev;
1433 struct intel_plane *intel_plane = to_intel_plane(plane);
Ville Syrjälä03c5b252013-10-01 18:02:11 +03001434 struct intel_crtc *intel_crtc;
Daniel Vettera071fa02014-06-18 23:28:09 +02001435 enum pipe pipe;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001436
Ville Syrjälä88a94a52013-08-07 13:30:23 +03001437 if (!plane->fb)
1438 return 0;
1439
1440 if (WARN_ON(!plane->crtc))
1441 return -EINVAL;
1442
Ville Syrjälä03c5b252013-10-01 18:02:11 +03001443 intel_crtc = to_intel_crtc(plane->crtc);
Daniel Vettera071fa02014-06-18 23:28:09 +02001444 pipe = intel_crtc->pipe;
Ville Syrjälä03c5b252013-10-01 18:02:11 +03001445
1446 if (intel_crtc->active) {
Ville Syrjälä5b633d62014-04-29 13:35:47 +03001447 bool primary_was_enabled = intel_crtc->primary_enabled;
1448
1449 intel_crtc->primary_enabled = true;
1450
Ville Syrjälä03c5b252013-10-01 18:02:11 +03001451 intel_plane->disable_plane(plane, plane->crtc);
Ville Syrjälä5b633d62014-04-29 13:35:47 +03001452
1453 if (!primary_was_enabled && intel_crtc->primary_enabled)
1454 intel_post_enable_primary(plane->crtc);
Ville Syrjälä03c5b252013-10-01 18:02:11 +03001455 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001456
Ville Syrjälä5f3fb462013-10-01 18:02:13 +03001457 if (intel_plane->obj) {
1458 if (intel_crtc->active)
1459 intel_wait_for_vblank(dev, intel_plane->pipe);
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001460
Ville Syrjälä5f3fb462013-10-01 18:02:13 +03001461 mutex_lock(&dev->struct_mutex);
1462 intel_unpin_fb_obj(intel_plane->obj);
Daniel Vettera071fa02014-06-18 23:28:09 +02001463 i915_gem_track_fb(intel_plane->obj, NULL,
1464 INTEL_FRONTBUFFER_SPRITE(pipe));
Ville Syrjälä5f3fb462013-10-01 18:02:13 +03001465 mutex_unlock(&dev->struct_mutex);
Ville Syrjäläc626d312013-03-27 17:49:13 +02001466
Ville Syrjälä5f3fb462013-10-01 18:02:13 +03001467 intel_plane->obj = NULL;
1468 }
Ville Syrjälä82284b62013-10-01 18:02:12 +03001469
Ville Syrjälä5f3fb462013-10-01 18:02:13 +03001470 return 0;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001471}
1472
1473static void intel_destroy_plane(struct drm_plane *plane)
1474{
1475 struct intel_plane *intel_plane = to_intel_plane(plane);
1476 intel_disable_plane(plane);
1477 drm_plane_cleanup(plane);
1478 kfree(intel_plane);
1479}
1480
Jesse Barnes8ea30862012-01-03 08:05:39 -08001481int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
1482 struct drm_file *file_priv)
1483{
1484 struct drm_intel_sprite_colorkey *set = data;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001485 struct drm_plane *plane;
1486 struct intel_plane *intel_plane;
1487 int ret = 0;
1488
Daniel Vetter1cff8f62012-04-24 09:55:08 +02001489 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1490 return -ENODEV;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001491
1492 /* Make sure we don't try to enable both src & dest simultaneously */
1493 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1494 return -EINVAL;
1495
Daniel Vettera0e99e62012-12-02 01:05:46 +01001496 drm_modeset_lock_all(dev);
Jesse Barnes8ea30862012-01-03 08:05:39 -08001497
Rob Clark7707e652014-07-17 23:30:04 -04001498 plane = drm_plane_find(dev, set->plane_id);
1499 if (!plane) {
Ville Syrjälä3f2c2052013-10-17 13:35:03 +03001500 ret = -ENOENT;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001501 goto out_unlock;
1502 }
1503
Jesse Barnes8ea30862012-01-03 08:05:39 -08001504 intel_plane = to_intel_plane(plane);
1505 ret = intel_plane->update_colorkey(plane, set);
1506
1507out_unlock:
Daniel Vettera0e99e62012-12-02 01:05:46 +01001508 drm_modeset_unlock_all(dev);
Jesse Barnes8ea30862012-01-03 08:05:39 -08001509 return ret;
1510}
1511
1512int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
1513 struct drm_file *file_priv)
1514{
1515 struct drm_intel_sprite_colorkey *get = data;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001516 struct drm_plane *plane;
1517 struct intel_plane *intel_plane;
1518 int ret = 0;
1519
Daniel Vetter1cff8f62012-04-24 09:55:08 +02001520 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1521 return -ENODEV;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001522
Daniel Vettera0e99e62012-12-02 01:05:46 +01001523 drm_modeset_lock_all(dev);
Jesse Barnes8ea30862012-01-03 08:05:39 -08001524
Rob Clark7707e652014-07-17 23:30:04 -04001525 plane = drm_plane_find(dev, get->plane_id);
1526 if (!plane) {
Ville Syrjälä3f2c2052013-10-17 13:35:03 +03001527 ret = -ENOENT;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001528 goto out_unlock;
1529 }
1530
Jesse Barnes8ea30862012-01-03 08:05:39 -08001531 intel_plane = to_intel_plane(plane);
1532 intel_plane->get_colorkey(plane, get);
1533
1534out_unlock:
Daniel Vettera0e99e62012-12-02 01:05:46 +01001535 drm_modeset_unlock_all(dev);
Jesse Barnes8ea30862012-01-03 08:05:39 -08001536 return ret;
1537}
1538
Sonika Jindal48404c12014-08-22 14:06:04 +05301539int intel_plane_set_property(struct drm_plane *plane,
1540 struct drm_property *prop,
1541 uint64_t val)
Ville Syrjälä7ed6eee2014-08-05 11:26:55 +05301542{
1543 struct drm_device *dev = plane->dev;
1544 struct intel_plane *intel_plane = to_intel_plane(plane);
1545 uint64_t old_val;
1546 int ret = -ENOENT;
1547
1548 if (prop == dev->mode_config.rotation_property) {
1549 /* exactly one rotation angle please */
1550 if (hweight32(val & 0xf) != 1)
1551 return -EINVAL;
1552
Ville Syrjälä09dba002014-09-01 18:08:25 +03001553 if (intel_plane->rotation == val)
1554 return 0;
1555
Ville Syrjälä7ed6eee2014-08-05 11:26:55 +05301556 old_val = intel_plane->rotation;
1557 intel_plane->rotation = val;
1558 ret = intel_plane_restore(plane);
1559 if (ret)
1560 intel_plane->rotation = old_val;
1561 }
1562
1563 return ret;
1564}
1565
Ville Syrjäläe57465f2014-08-05 11:26:53 +05301566int intel_plane_restore(struct drm_plane *plane)
Jesse Barnes5e1bac22013-03-26 09:25:43 -07001567{
1568 struct intel_plane *intel_plane = to_intel_plane(plane);
1569
1570 if (!plane->crtc || !plane->fb)
Ville Syrjäläe57465f2014-08-05 11:26:53 +05301571 return 0;
Jesse Barnes5e1bac22013-03-26 09:25:43 -07001572
Sonika Jindal48404c12014-08-22 14:06:04 +05301573 return plane->funcs->update_plane(plane, plane->crtc, plane->fb,
Ville Syrjäläe57465f2014-08-05 11:26:53 +05301574 intel_plane->crtc_x, intel_plane->crtc_y,
1575 intel_plane->crtc_w, intel_plane->crtc_h,
1576 intel_plane->src_x, intel_plane->src_y,
1577 intel_plane->src_w, intel_plane->src_h);
Jesse Barnes5e1bac22013-03-26 09:25:43 -07001578}
1579
Ville Syrjäläbb53d4a2013-06-04 13:49:04 +03001580void intel_plane_disable(struct drm_plane *plane)
1581{
1582 if (!plane->crtc || !plane->fb)
1583 return;
1584
1585 intel_disable_plane(plane);
1586}
1587
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001588static const struct drm_plane_funcs intel_plane_funcs = {
1589 .update_plane = intel_update_plane,
1590 .disable_plane = intel_disable_plane,
1591 .destroy = intel_destroy_plane,
Ville Syrjälä7ed6eee2014-08-05 11:26:55 +05301592 .set_property = intel_plane_set_property,
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001593};
1594
Chris Wilsond1686ae2012-04-10 11:41:49 +01001595static uint32_t ilk_plane_formats[] = {
1596 DRM_FORMAT_XRGB8888,
1597 DRM_FORMAT_YUYV,
1598 DRM_FORMAT_YVYU,
1599 DRM_FORMAT_UYVY,
1600 DRM_FORMAT_VYUY,
1601};
1602
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001603static uint32_t snb_plane_formats[] = {
1604 DRM_FORMAT_XBGR8888,
1605 DRM_FORMAT_XRGB8888,
1606 DRM_FORMAT_YUYV,
1607 DRM_FORMAT_YVYU,
1608 DRM_FORMAT_UYVY,
1609 DRM_FORMAT_VYUY,
1610};
1611
Jesse Barnes7f1f3852013-04-02 11:22:20 -07001612static uint32_t vlv_plane_formats[] = {
1613 DRM_FORMAT_RGB565,
1614 DRM_FORMAT_ABGR8888,
1615 DRM_FORMAT_ARGB8888,
1616 DRM_FORMAT_XBGR8888,
1617 DRM_FORMAT_XRGB8888,
1618 DRM_FORMAT_XBGR2101010,
1619 DRM_FORMAT_ABGR2101010,
1620 DRM_FORMAT_YUYV,
1621 DRM_FORMAT_YVYU,
1622 DRM_FORMAT_UYVY,
1623 DRM_FORMAT_VYUY,
1624};
1625
Damien Lespiaudc2a41b2013-12-04 00:49:41 +00001626static uint32_t skl_plane_formats[] = {
1627 DRM_FORMAT_RGB565,
1628 DRM_FORMAT_ABGR8888,
1629 DRM_FORMAT_ARGB8888,
1630 DRM_FORMAT_XBGR8888,
1631 DRM_FORMAT_XRGB8888,
1632 DRM_FORMAT_YUYV,
1633 DRM_FORMAT_YVYU,
1634 DRM_FORMAT_UYVY,
1635 DRM_FORMAT_VYUY,
1636};
1637
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001638int
Jesse Barnes7f1f3852013-04-02 11:22:20 -07001639intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001640{
1641 struct intel_plane *intel_plane;
1642 unsigned long possible_crtcs;
Chris Wilsond1686ae2012-04-10 11:41:49 +01001643 const uint32_t *plane_formats;
1644 int num_plane_formats;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001645 int ret;
1646
Chris Wilsond1686ae2012-04-10 11:41:49 +01001647 if (INTEL_INFO(dev)->gen < 5)
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001648 return -ENODEV;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001649
Daniel Vetterb14c5672013-09-19 12:18:32 +02001650 intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001651 if (!intel_plane)
1652 return -ENOMEM;
1653
Chris Wilsond1686ae2012-04-10 11:41:49 +01001654 switch (INTEL_INFO(dev)->gen) {
1655 case 5:
1656 case 6:
Damien Lespiau2d354c32012-10-22 18:19:27 +01001657 intel_plane->can_scale = true;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001658 intel_plane->max_downscale = 16;
Chris Wilsond1686ae2012-04-10 11:41:49 +01001659 intel_plane->update_plane = ilk_update_plane;
1660 intel_plane->disable_plane = ilk_disable_plane;
1661 intel_plane->update_colorkey = ilk_update_colorkey;
1662 intel_plane->get_colorkey = ilk_get_colorkey;
1663
1664 if (IS_GEN6(dev)) {
1665 plane_formats = snb_plane_formats;
1666 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1667 } else {
1668 plane_formats = ilk_plane_formats;
1669 num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
1670 }
1671 break;
1672
1673 case 7:
Ben Widawsky4e0bbc32013-11-02 21:07:07 -07001674 case 8:
Damien Lespiaud49f7092013-04-25 15:15:00 +01001675 if (IS_IVYBRIDGE(dev)) {
Damien Lespiau2d354c32012-10-22 18:19:27 +01001676 intel_plane->can_scale = true;
Damien Lespiaud49f7092013-04-25 15:15:00 +01001677 intel_plane->max_downscale = 2;
1678 } else {
1679 intel_plane->can_scale = false;
1680 intel_plane->max_downscale = 1;
1681 }
Chris Wilsond1686ae2012-04-10 11:41:49 +01001682
Jesse Barnes7f1f3852013-04-02 11:22:20 -07001683 if (IS_VALLEYVIEW(dev)) {
Jesse Barnes7f1f3852013-04-02 11:22:20 -07001684 intel_plane->update_plane = vlv_update_plane;
1685 intel_plane->disable_plane = vlv_disable_plane;
1686 intel_plane->update_colorkey = vlv_update_colorkey;
1687 intel_plane->get_colorkey = vlv_get_colorkey;
1688
1689 plane_formats = vlv_plane_formats;
1690 num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1691 } else {
Jesse Barnes7f1f3852013-04-02 11:22:20 -07001692 intel_plane->update_plane = ivb_update_plane;
1693 intel_plane->disable_plane = ivb_disable_plane;
1694 intel_plane->update_colorkey = ivb_update_colorkey;
1695 intel_plane->get_colorkey = ivb_get_colorkey;
1696
1697 plane_formats = snb_plane_formats;
1698 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1699 }
Chris Wilsond1686ae2012-04-10 11:41:49 +01001700 break;
Damien Lespiaudc2a41b2013-12-04 00:49:41 +00001701 case 9:
1702 /*
1703 * FIXME: Skylake planes can be scaled (with some restrictions),
1704 * but this is for another time.
1705 */
1706 intel_plane->can_scale = false;
1707 intel_plane->max_downscale = 1;
1708 intel_plane->update_plane = skl_update_plane;
1709 intel_plane->disable_plane = skl_disable_plane;
1710 intel_plane->update_colorkey = skl_update_colorkey;
1711 intel_plane->get_colorkey = skl_get_colorkey;
Chris Wilsond1686ae2012-04-10 11:41:49 +01001712
Damien Lespiaudc2a41b2013-12-04 00:49:41 +00001713 plane_formats = skl_plane_formats;
1714 num_plane_formats = ARRAY_SIZE(skl_plane_formats);
1715 break;
Chris Wilsond1686ae2012-04-10 11:41:49 +01001716 default:
Jesper Juhla8b0bba2012-06-27 00:55:37 +02001717 kfree(intel_plane);
Chris Wilsond1686ae2012-04-10 11:41:49 +01001718 return -ENODEV;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001719 }
1720
1721 intel_plane->pipe = pipe;
Jesse Barnes7f1f3852013-04-02 11:22:20 -07001722 intel_plane->plane = plane;
Ville Syrjälä76eebda2014-08-05 11:26:52 +05301723 intel_plane->rotation = BIT(DRM_ROTATE_0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001724 possible_crtcs = (1 << pipe);
Derek Foreman8fe8a3f2014-09-03 10:38:20 -03001725 ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
1726 &intel_plane_funcs,
1727 plane_formats, num_plane_formats,
1728 DRM_PLANE_TYPE_OVERLAY);
Ville Syrjälä7ed6eee2014-08-05 11:26:55 +05301729 if (ret) {
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001730 kfree(intel_plane);
Ville Syrjälä7ed6eee2014-08-05 11:26:55 +05301731 goto out;
1732 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001733
Ville Syrjälä7ed6eee2014-08-05 11:26:55 +05301734 if (!dev->mode_config.rotation_property)
1735 dev->mode_config.rotation_property =
1736 drm_mode_create_rotation_property(dev,
1737 BIT(DRM_ROTATE_0) |
1738 BIT(DRM_ROTATE_180));
1739
1740 if (dev->mode_config.rotation_property)
1741 drm_object_attach_property(&intel_plane->base.base,
1742 dev->mode_config.rotation_property,
1743 intel_plane->rotation);
1744
1745 out:
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001746 return ret;
1747}