blob: 03307be7a1c4bd5bd697263589f69d5007acba4b [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
40ivb_update_plane(struct drm_plane *plane, 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 = plane->dev;
47 struct drm_i915_private *dev_priv = dev->dev_private;
48 struct intel_plane *intel_plane = to_intel_plane(plane);
49 int pipe = intel_plane->pipe;
50 u32 sprctl, sprscale = 0;
51 int pixel_size;
Damien Lespiau5a35e992012-10-26 18:20:12 +010052 unsigned long sprsurf_offset, linear_offset;
Jesse Barnesb840d907f2011-12-13 13:19:38 -080053
54 sprctl = I915_READ(SPRCTL(pipe));
55
56 /* Mask out pixel format bits in case we change it */
57 sprctl &= ~SPRITE_PIXFORMAT_MASK;
58 sprctl &= ~SPRITE_RGB_ORDER_RGBX;
59 sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
Jesse Barnese86fe0d2012-06-26 13:10:11 -070060 sprctl &= ~SPRITE_TILED;
Jesse Barnesb840d907f2011-12-13 13:19:38 -080061
62 switch (fb->pixel_format) {
63 case DRM_FORMAT_XBGR8888:
Vijay Purushothaman5ee36912012-08-23 12:08:57 +053064 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
Jesse Barnesb840d907f2011-12-13 13:19:38 -080065 pixel_size = 4;
66 break;
67 case DRM_FORMAT_XRGB8888:
Vijay Purushothaman5ee36912012-08-23 12:08:57 +053068 sprctl |= SPRITE_FORMAT_RGBX888;
Jesse Barnesb840d907f2011-12-13 13:19:38 -080069 pixel_size = 4;
70 break;
71 case DRM_FORMAT_YUYV:
72 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
73 pixel_size = 2;
74 break;
75 case DRM_FORMAT_YVYU:
76 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
77 pixel_size = 2;
78 break;
79 case DRM_FORMAT_UYVY:
80 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
81 pixel_size = 2;
82 break;
83 case DRM_FORMAT_VYUY:
84 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
85 pixel_size = 2;
86 break;
87 default:
88 DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
Jesse Barnesf4d71052012-06-26 13:10:12 -070089 sprctl |= SPRITE_FORMAT_RGBX888;
Jesse Barnesb840d907f2011-12-13 13:19:38 -080090 pixel_size = 4;
91 break;
92 }
93
94 if (obj->tiling_mode != I915_TILING_NONE)
95 sprctl |= SPRITE_TILED;
96
97 /* must disable */
98 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
99 sprctl |= SPRITE_ENABLE;
100
101 /* Sizes are 0 based */
102 src_w--;
103 src_h--;
104 crtc_w--;
105 crtc_h--;
106
107 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
108
109 /*
110 * IVB workaround: must disable low power watermarks for at least
111 * one frame before enabling scaling. LP watermarks can be re-enabled
112 * when scaling is disabled.
113 */
114 if (crtc_w != src_w || crtc_h != src_h) {
Chris Wilson828ed3e2012-04-18 17:12:26 +0100115 if (!dev_priv->sprite_scaling_enabled) {
116 dev_priv->sprite_scaling_enabled = true;
117 intel_update_watermarks(dev);
118 intel_wait_for_vblank(dev, pipe);
119 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800120 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
121 } else {
Chris Wilson828ed3e2012-04-18 17:12:26 +0100122 if (dev_priv->sprite_scaling_enabled) {
123 dev_priv->sprite_scaling_enabled = false;
124 /* potentially re-enable LP watermarks */
125 intel_update_watermarks(dev);
126 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800127 }
128
129 I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
130 I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
Damien Lespiauc54173a2012-10-26 18:20:11 +0100131
Damien Lespiau5a35e992012-10-26 18:20:12 +0100132 linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
133 sprsurf_offset =
134 intel_gen4_compute_offset_xtiled(&x, &y,
135 fb->bits_per_pixel / 8,
136 fb->pitches[0]);
137 linear_offset -= sprsurf_offset;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800138
Damien Lespiau5a35e992012-10-26 18:20:12 +0100139 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
140 * register */
141 if (IS_HASWELL(dev))
142 I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
143 else if (obj->tiling_mode != I915_TILING_NONE)
144 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
145 else
146 I915_WRITE(SPRLINOFF(pipe), linear_offset);
Damien Lespiauc54173a2012-10-26 18:20:11 +0100147
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800148 I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
Damien Lespiau2d354c32012-10-22 18:19:27 +0100149 if (intel_plane->can_scale)
150 I915_WRITE(SPRSCALE(pipe), sprscale);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800151 I915_WRITE(SPRCTL(pipe), sprctl);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100152 I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset + sprsurf_offset);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800153 POSTING_READ(SPRSURF(pipe));
154}
155
156static void
157ivb_disable_plane(struct drm_plane *plane)
158{
159 struct drm_device *dev = plane->dev;
160 struct drm_i915_private *dev_priv = dev->dev_private;
161 struct intel_plane *intel_plane = to_intel_plane(plane);
162 int pipe = intel_plane->pipe;
163
164 I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
165 /* Can't leave the scaler enabled... */
Damien Lespiau2d354c32012-10-22 18:19:27 +0100166 if (intel_plane->can_scale)
167 I915_WRITE(SPRSCALE(pipe), 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800168 /* Activate double buffered register update */
Armin Reese446f2542012-03-30 16:20:16 -0700169 I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800170 POSTING_READ(SPRSURF(pipe));
Chris Wilson828ed3e2012-04-18 17:12:26 +0100171
172 dev_priv->sprite_scaling_enabled = false;
173 intel_update_watermarks(dev);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800174}
175
Jesse Barnes8ea30862012-01-03 08:05:39 -0800176static int
177ivb_update_colorkey(struct drm_plane *plane,
178 struct drm_intel_sprite_colorkey *key)
179{
180 struct drm_device *dev = plane->dev;
181 struct drm_i915_private *dev_priv = dev->dev_private;
182 struct intel_plane *intel_plane;
183 u32 sprctl;
184 int ret = 0;
185
186 intel_plane = to_intel_plane(plane);
187
188 I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
189 I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
190 I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
191
192 sprctl = I915_READ(SPRCTL(intel_plane->pipe));
193 sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
194 if (key->flags & I915_SET_COLORKEY_DESTINATION)
195 sprctl |= SPRITE_DEST_KEY;
196 else if (key->flags & I915_SET_COLORKEY_SOURCE)
197 sprctl |= SPRITE_SOURCE_KEY;
198 I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
199
200 POSTING_READ(SPRKEYMSK(intel_plane->pipe));
201
202 return ret;
203}
204
205static void
206ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
207{
208 struct drm_device *dev = plane->dev;
209 struct drm_i915_private *dev_priv = dev->dev_private;
210 struct intel_plane *intel_plane;
211 u32 sprctl;
212
213 intel_plane = to_intel_plane(plane);
214
215 key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
216 key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
217 key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
218 key->flags = 0;
219
220 sprctl = I915_READ(SPRCTL(intel_plane->pipe));
221
222 if (sprctl & SPRITE_DEST_KEY)
223 key->flags = I915_SET_COLORKEY_DESTINATION;
224 else if (sprctl & SPRITE_SOURCE_KEY)
225 key->flags = I915_SET_COLORKEY_SOURCE;
226 else
227 key->flags = I915_SET_COLORKEY_NONE;
228}
229
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800230static void
Chris Wilsond1686ae2012-04-10 11:41:49 +0100231ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800232 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
233 unsigned int crtc_w, unsigned int crtc_h,
234 uint32_t x, uint32_t y,
235 uint32_t src_w, uint32_t src_h)
236{
237 struct drm_device *dev = plane->dev;
238 struct drm_i915_private *dev_priv = dev->dev_private;
239 struct intel_plane *intel_plane = to_intel_plane(plane);
240 int pipe = intel_plane->pipe, pixel_size;
Damien Lespiau5a35e992012-10-26 18:20:12 +0100241 unsigned long dvssurf_offset, linear_offset;
Chris Wilson8aaa81a2012-04-14 22:14:26 +0100242 u32 dvscntr, dvsscale;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800243
244 dvscntr = I915_READ(DVSCNTR(pipe));
245
246 /* Mask out pixel format bits in case we change it */
247 dvscntr &= ~DVS_PIXFORMAT_MASK;
Jesse Barnesab2f9df2012-02-27 12:40:10 -0800248 dvscntr &= ~DVS_RGB_ORDER_XBGR;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800249 dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
Ander Conselvan de Oliveira79626522012-07-13 15:50:33 +0300250 dvscntr &= ~DVS_TILED;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800251
252 switch (fb->pixel_format) {
253 case DRM_FORMAT_XBGR8888:
Jesse Barnesab2f9df2012-02-27 12:40:10 -0800254 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800255 pixel_size = 4;
256 break;
257 case DRM_FORMAT_XRGB8888:
Jesse Barnesab2f9df2012-02-27 12:40:10 -0800258 dvscntr |= DVS_FORMAT_RGBX888;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800259 pixel_size = 4;
260 break;
261 case DRM_FORMAT_YUYV:
262 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
263 pixel_size = 2;
264 break;
265 case DRM_FORMAT_YVYU:
266 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
267 pixel_size = 2;
268 break;
269 case DRM_FORMAT_UYVY:
270 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
271 pixel_size = 2;
272 break;
273 case DRM_FORMAT_VYUY:
274 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
275 pixel_size = 2;
276 break;
277 default:
278 DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
279 dvscntr |= DVS_FORMAT_RGBX888;
280 pixel_size = 4;
281 break;
282 }
283
284 if (obj->tiling_mode != I915_TILING_NONE)
285 dvscntr |= DVS_TILED;
286
Chris Wilsond1686ae2012-04-10 11:41:49 +0100287 if (IS_GEN6(dev))
288 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800289 dvscntr |= DVS_ENABLE;
290
291 /* Sizes are 0 based */
292 src_w--;
293 src_h--;
294 crtc_w--;
295 crtc_h--;
296
297 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
298
Chris Wilson8aaa81a2012-04-14 22:14:26 +0100299 dvsscale = 0;
300 if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800301 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
302
303 I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
304 I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800305
Damien Lespiau5a35e992012-10-26 18:20:12 +0100306 linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
307 dvssurf_offset =
308 intel_gen4_compute_offset_xtiled(&x, &y,
309 fb->bits_per_pixel / 8,
310 fb->pitches[0]);
311 linear_offset -= dvssurf_offset;
312
313 if (obj->tiling_mode != I915_TILING_NONE)
314 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
315 else
316 I915_WRITE(DVSLINOFF(pipe), linear_offset);
317
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800318 I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
319 I915_WRITE(DVSSCALE(pipe), dvsscale);
320 I915_WRITE(DVSCNTR(pipe), dvscntr);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100321 I915_MODIFY_DISPBASE(DVSSURF(pipe), obj->gtt_offset + dvssurf_offset);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800322 POSTING_READ(DVSSURF(pipe));
323}
324
325static void
Chris Wilsond1686ae2012-04-10 11:41:49 +0100326ilk_disable_plane(struct drm_plane *plane)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800327{
328 struct drm_device *dev = plane->dev;
329 struct drm_i915_private *dev_priv = dev->dev_private;
330 struct intel_plane *intel_plane = to_intel_plane(plane);
331 int pipe = intel_plane->pipe;
332
333 I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
334 /* Disable the scaler */
335 I915_WRITE(DVSSCALE(pipe), 0);
336 /* Flush double buffered register updates */
Armin Reese446f2542012-03-30 16:20:16 -0700337 I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800338 POSTING_READ(DVSSURF(pipe));
339}
340
Jesse Barnes175bd422011-12-13 13:19:39 -0800341static void
342intel_enable_primary(struct drm_crtc *crtc)
343{
344 struct drm_device *dev = crtc->dev;
345 struct drm_i915_private *dev_priv = dev->dev_private;
346 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
347 int reg = DSPCNTR(intel_crtc->plane);
348
Chris Wilson93314b52012-06-13 17:36:55 +0100349 if (!intel_crtc->primary_disabled)
350 return;
351
352 intel_crtc->primary_disabled = false;
353 intel_update_fbc(dev);
354
Jesse Barnes175bd422011-12-13 13:19:39 -0800355 I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
356}
357
358static void
359intel_disable_primary(struct drm_crtc *crtc)
360{
361 struct drm_device *dev = crtc->dev;
362 struct drm_i915_private *dev_priv = dev->dev_private;
363 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
364 int reg = DSPCNTR(intel_crtc->plane);
365
Chris Wilson93314b52012-06-13 17:36:55 +0100366 if (intel_crtc->primary_disabled)
367 return;
368
Jesse Barnes175bd422011-12-13 13:19:39 -0800369 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
Chris Wilson93314b52012-06-13 17:36:55 +0100370
371 intel_crtc->primary_disabled = true;
372 intel_update_fbc(dev);
Jesse Barnes175bd422011-12-13 13:19:39 -0800373}
374
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800375static int
Chris Wilsond1686ae2012-04-10 11:41:49 +0100376ilk_update_colorkey(struct drm_plane *plane,
Jesse Barnes8ea30862012-01-03 08:05:39 -0800377 struct drm_intel_sprite_colorkey *key)
378{
379 struct drm_device *dev = plane->dev;
380 struct drm_i915_private *dev_priv = dev->dev_private;
381 struct intel_plane *intel_plane;
382 u32 dvscntr;
383 int ret = 0;
384
385 intel_plane = to_intel_plane(plane);
386
387 I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
388 I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
389 I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
390
391 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
392 dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
393 if (key->flags & I915_SET_COLORKEY_DESTINATION)
394 dvscntr |= DVS_DEST_KEY;
395 else if (key->flags & I915_SET_COLORKEY_SOURCE)
396 dvscntr |= DVS_SOURCE_KEY;
397 I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
398
399 POSTING_READ(DVSKEYMSK(intel_plane->pipe));
400
401 return ret;
402}
403
404static void
Chris Wilsond1686ae2012-04-10 11:41:49 +0100405ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
Jesse Barnes8ea30862012-01-03 08:05:39 -0800406{
407 struct drm_device *dev = plane->dev;
408 struct drm_i915_private *dev_priv = dev->dev_private;
409 struct intel_plane *intel_plane;
410 u32 dvscntr;
411
412 intel_plane = to_intel_plane(plane);
413
414 key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
415 key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
416 key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
417 key->flags = 0;
418
419 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
420
421 if (dvscntr & DVS_DEST_KEY)
422 key->flags = I915_SET_COLORKEY_DESTINATION;
423 else if (dvscntr & DVS_SOURCE_KEY)
424 key->flags = I915_SET_COLORKEY_SOURCE;
425 else
426 key->flags = I915_SET_COLORKEY_NONE;
427}
428
429static int
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800430intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
431 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
432 unsigned int crtc_w, unsigned int crtc_h,
433 uint32_t src_x, uint32_t src_y,
434 uint32_t src_w, uint32_t src_h)
435{
436 struct drm_device *dev = plane->dev;
437 struct drm_i915_private *dev_priv = dev->dev_private;
438 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
439 struct intel_plane *intel_plane = to_intel_plane(plane);
440 struct intel_framebuffer *intel_fb;
441 struct drm_i915_gem_object *obj, *old_obj;
442 int pipe = intel_plane->pipe;
Paulo Zanoni702e7a52012-10-23 18:29:59 -0200443 enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
444 pipe);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800445 int ret = 0;
446 int x = src_x >> 16, y = src_y >> 16;
447 int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
448 bool disable_primary = false;
449
450 intel_fb = to_intel_framebuffer(fb);
451 obj = intel_fb->obj;
452
453 old_obj = intel_plane->obj;
454
Jesse Barnesb4db1e32012-03-20 10:59:09 -0700455 src_w = src_w >> 16;
456 src_h = src_h >> 16;
457
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800458 /* Pipe must be running... */
Paulo Zanoni702e7a52012-10-23 18:29:59 -0200459 if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE))
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800460 return -EINVAL;
461
462 if (crtc_x >= primary_w || crtc_y >= primary_h)
463 return -EINVAL;
464
465 /* Don't modify another pipe's plane */
466 if (intel_plane->pipe != intel_crtc->pipe)
467 return -EINVAL;
468
Damien Lespiau94c64192012-10-29 15:14:51 +0000469 /* Sprite planes can be linear or x-tiled surfaces */
470 switch (obj->tiling_mode) {
471 case I915_TILING_NONE:
472 case I915_TILING_X:
473 break;
474 default:
475 return -EINVAL;
476 }
477
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800478 /*
479 * Clamp the width & height into the visible area. Note we don't
480 * try to scale the source if part of the visible region is offscreen.
481 * The caller must handle that by adjusting source offset and size.
482 */
483 if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) {
484 crtc_w += crtc_x;
485 crtc_x = 0;
486 }
487 if ((crtc_x + crtc_w) <= 0) /* Nothing to display */
488 goto out;
489 if ((crtc_x + crtc_w) > primary_w)
490 crtc_w = primary_w - crtc_x;
491
492 if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) {
493 crtc_h += crtc_y;
494 crtc_y = 0;
495 }
496 if ((crtc_y + crtc_h) <= 0) /* Nothing to display */
497 goto out;
498 if (crtc_y + crtc_h > primary_h)
499 crtc_h = primary_h - crtc_y;
500
501 if (!crtc_w || !crtc_h) /* Again, nothing to display */
502 goto out;
503
504 /*
Damien Lespiau2d354c32012-10-22 18:19:27 +0100505 * We may not have a scaler, eg. HSW does not have it any more
506 */
507 if (!intel_plane->can_scale && (crtc_w != src_w || crtc_h != src_h))
508 return -EINVAL;
509
510 /*
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800511 * We can take a larger source and scale it down, but
512 * only so much... 16x is the max on SNB.
513 */
514 if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
515 return -EINVAL;
516
517 /*
518 * If the sprite is completely covering the primary plane,
519 * we can disable the primary and save power.
520 */
521 if ((crtc_x == 0) && (crtc_y == 0) &&
522 (crtc_w == primary_w) && (crtc_h == primary_h))
523 disable_primary = true;
524
525 mutex_lock(&dev->struct_mutex);
526
527 ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
Jesse Barnes00c2064b2012-01-13 15:48:39 -0800528 if (ret)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800529 goto out_unlock;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800530
531 intel_plane->obj = obj;
532
Jesse Barnes175bd422011-12-13 13:19:39 -0800533 /*
534 * Be sure to re-enable the primary before the sprite is no longer
535 * covering it fully.
536 */
Chris Wilson93314b52012-06-13 17:36:55 +0100537 if (!disable_primary)
Jesse Barnes175bd422011-12-13 13:19:39 -0800538 intel_enable_primary(crtc);
Jesse Barnes175bd422011-12-13 13:19:39 -0800539
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800540 intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
541 crtc_w, crtc_h, x, y, src_w, src_h);
542
Chris Wilson93314b52012-06-13 17:36:55 +0100543 if (disable_primary)
Jesse Barnes175bd422011-12-13 13:19:39 -0800544 intel_disable_primary(crtc);
Jesse Barnes175bd422011-12-13 13:19:39 -0800545
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800546 /* Unpin old obj after new one is active to avoid ugliness */
547 if (old_obj) {
548 /*
549 * It's fairly common to simply update the position of
550 * an existing object. In that case, we don't need to
551 * wait for vblank to avoid ugliness, we only need to
552 * do the pin & ref bookkeeping.
553 */
554 if (old_obj != obj) {
555 mutex_unlock(&dev->struct_mutex);
556 intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
557 mutex_lock(&dev->struct_mutex);
558 }
Chris Wilson1690e1e2011-12-14 13:57:08 +0100559 intel_unpin_fb_obj(old_obj);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800560 }
561
562out_unlock:
563 mutex_unlock(&dev->struct_mutex);
564out:
565 return ret;
566}
567
568static int
569intel_disable_plane(struct drm_plane *plane)
570{
571 struct drm_device *dev = plane->dev;
572 struct intel_plane *intel_plane = to_intel_plane(plane);
573 int ret = 0;
574
Chris Wilson93314b52012-06-13 17:36:55 +0100575 if (plane->crtc)
Jesse Barnes175bd422011-12-13 13:19:39 -0800576 intel_enable_primary(plane->crtc);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800577 intel_plane->disable_plane(plane);
578
579 if (!intel_plane->obj)
580 goto out;
581
582 mutex_lock(&dev->struct_mutex);
Chris Wilson1690e1e2011-12-14 13:57:08 +0100583 intel_unpin_fb_obj(intel_plane->obj);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800584 intel_plane->obj = NULL;
585 mutex_unlock(&dev->struct_mutex);
586out:
587
588 return ret;
589}
590
591static void intel_destroy_plane(struct drm_plane *plane)
592{
593 struct intel_plane *intel_plane = to_intel_plane(plane);
594 intel_disable_plane(plane);
595 drm_plane_cleanup(plane);
596 kfree(intel_plane);
597}
598
Jesse Barnes8ea30862012-01-03 08:05:39 -0800599int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
600 struct drm_file *file_priv)
601{
602 struct drm_intel_sprite_colorkey *set = data;
Jesse Barnes8ea30862012-01-03 08:05:39 -0800603 struct drm_mode_object *obj;
604 struct drm_plane *plane;
605 struct intel_plane *intel_plane;
606 int ret = 0;
607
Daniel Vetter1cff8f62012-04-24 09:55:08 +0200608 if (!drm_core_check_feature(dev, DRIVER_MODESET))
609 return -ENODEV;
Jesse Barnes8ea30862012-01-03 08:05:39 -0800610
611 /* Make sure we don't try to enable both src & dest simultaneously */
612 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
613 return -EINVAL;
614
615 mutex_lock(&dev->mode_config.mutex);
616
617 obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
618 if (!obj) {
619 ret = -EINVAL;
620 goto out_unlock;
621 }
622
623 plane = obj_to_plane(obj);
624 intel_plane = to_intel_plane(plane);
625 ret = intel_plane->update_colorkey(plane, set);
626
627out_unlock:
628 mutex_unlock(&dev->mode_config.mutex);
629 return ret;
630}
631
632int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
633 struct drm_file *file_priv)
634{
635 struct drm_intel_sprite_colorkey *get = data;
Jesse Barnes8ea30862012-01-03 08:05:39 -0800636 struct drm_mode_object *obj;
637 struct drm_plane *plane;
638 struct intel_plane *intel_plane;
639 int ret = 0;
640
Daniel Vetter1cff8f62012-04-24 09:55:08 +0200641 if (!drm_core_check_feature(dev, DRIVER_MODESET))
642 return -ENODEV;
Jesse Barnes8ea30862012-01-03 08:05:39 -0800643
644 mutex_lock(&dev->mode_config.mutex);
645
646 obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
647 if (!obj) {
648 ret = -EINVAL;
649 goto out_unlock;
650 }
651
652 plane = obj_to_plane(obj);
653 intel_plane = to_intel_plane(plane);
654 intel_plane->get_colorkey(plane, get);
655
656out_unlock:
657 mutex_unlock(&dev->mode_config.mutex);
658 return ret;
659}
660
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800661static const struct drm_plane_funcs intel_plane_funcs = {
662 .update_plane = intel_update_plane,
663 .disable_plane = intel_disable_plane,
664 .destroy = intel_destroy_plane,
665};
666
Chris Wilsond1686ae2012-04-10 11:41:49 +0100667static uint32_t ilk_plane_formats[] = {
668 DRM_FORMAT_XRGB8888,
669 DRM_FORMAT_YUYV,
670 DRM_FORMAT_YVYU,
671 DRM_FORMAT_UYVY,
672 DRM_FORMAT_VYUY,
673};
674
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800675static uint32_t snb_plane_formats[] = {
676 DRM_FORMAT_XBGR8888,
677 DRM_FORMAT_XRGB8888,
678 DRM_FORMAT_YUYV,
679 DRM_FORMAT_YVYU,
680 DRM_FORMAT_UYVY,
681 DRM_FORMAT_VYUY,
682};
683
684int
685intel_plane_init(struct drm_device *dev, enum pipe pipe)
686{
687 struct intel_plane *intel_plane;
688 unsigned long possible_crtcs;
Chris Wilsond1686ae2012-04-10 11:41:49 +0100689 const uint32_t *plane_formats;
690 int num_plane_formats;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800691 int ret;
692
Chris Wilsond1686ae2012-04-10 11:41:49 +0100693 if (INTEL_INFO(dev)->gen < 5)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800694 return -ENODEV;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800695
696 intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
697 if (!intel_plane)
698 return -ENOMEM;
699
Chris Wilsond1686ae2012-04-10 11:41:49 +0100700 switch (INTEL_INFO(dev)->gen) {
701 case 5:
702 case 6:
Damien Lespiau2d354c32012-10-22 18:19:27 +0100703 intel_plane->can_scale = true;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800704 intel_plane->max_downscale = 16;
Chris Wilsond1686ae2012-04-10 11:41:49 +0100705 intel_plane->update_plane = ilk_update_plane;
706 intel_plane->disable_plane = ilk_disable_plane;
707 intel_plane->update_colorkey = ilk_update_colorkey;
708 intel_plane->get_colorkey = ilk_get_colorkey;
709
710 if (IS_GEN6(dev)) {
711 plane_formats = snb_plane_formats;
712 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
713 } else {
714 plane_formats = ilk_plane_formats;
715 num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
716 }
717 break;
718
719 case 7:
Damien Lespiau4d8d71b2012-10-25 18:06:19 +0100720 if (IS_HASWELL(dev) || IS_VALLEYVIEW(dev))
Damien Lespiau2d354c32012-10-22 18:19:27 +0100721 intel_plane->can_scale = false;
722 else
723 intel_plane->can_scale = true;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800724 intel_plane->max_downscale = 2;
725 intel_plane->update_plane = ivb_update_plane;
726 intel_plane->disable_plane = ivb_disable_plane;
Jesse Barnes8ea30862012-01-03 08:05:39 -0800727 intel_plane->update_colorkey = ivb_update_colorkey;
728 intel_plane->get_colorkey = ivb_get_colorkey;
Chris Wilsond1686ae2012-04-10 11:41:49 +0100729
730 plane_formats = snb_plane_formats;
731 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
732 break;
733
734 default:
Jesper Juhla8b0bba2012-06-27 00:55:37 +0200735 kfree(intel_plane);
Chris Wilsond1686ae2012-04-10 11:41:49 +0100736 return -ENODEV;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800737 }
738
739 intel_plane->pipe = pipe;
740 possible_crtcs = (1 << pipe);
741 ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
Chris Wilsond1686ae2012-04-10 11:41:49 +0100742 &intel_plane_funcs,
743 plane_formats, num_plane_formats,
744 false);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800745 if (ret)
746 kfree(intel_plane);
747
748 return ret;
749}