drm/i915: Remove duplicate intel_uncore_forcewake_reset.
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_sprite.c
CommitLineData
b840d907
JB
1/*
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 */
760285e7
DH
32#include <drm/drmP.h>
33#include <drm/drm_crtc.h>
34#include <drm/drm_fourcc.h>
1731693a 35#include <drm/drm_rect.h>
b840d907 36#include "intel_drv.h"
760285e7 37#include <drm/i915_drm.h>
b840d907
JB
38#include "i915_drv.h"
39
7f1f3851 40static void
b39d53f6
VS
41vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
42 struct drm_framebuffer *fb,
7f1f3851
JB
43 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
44 unsigned int crtc_w, unsigned int crtc_h,
45 uint32_t x, uint32_t y,
46 uint32_t src_w, uint32_t src_h)
47{
48 struct drm_device *dev = dplane->dev;
49 struct drm_i915_private *dev_priv = dev->dev_private;
50 struct intel_plane *intel_plane = to_intel_plane(dplane);
51 int pipe = intel_plane->pipe;
52 int plane = intel_plane->plane;
53 u32 sprctl;
54 unsigned long sprsurf_offset, linear_offset;
55 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
56
57 sprctl = I915_READ(SPCNTR(pipe, plane));
58
59 /* Mask out pixel format bits in case we change it */
60 sprctl &= ~SP_PIXFORMAT_MASK;
61 sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
62 sprctl &= ~SP_TILED;
63
64 switch (fb->pixel_format) {
65 case DRM_FORMAT_YUYV:
66 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
67 break;
68 case DRM_FORMAT_YVYU:
69 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
70 break;
71 case DRM_FORMAT_UYVY:
72 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
73 break;
74 case DRM_FORMAT_VYUY:
75 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
76 break;
77 case DRM_FORMAT_RGB565:
78 sprctl |= SP_FORMAT_BGR565;
79 break;
80 case DRM_FORMAT_XRGB8888:
81 sprctl |= SP_FORMAT_BGRX8888;
82 break;
83 case DRM_FORMAT_ARGB8888:
84 sprctl |= SP_FORMAT_BGRA8888;
85 break;
86 case DRM_FORMAT_XBGR2101010:
87 sprctl |= SP_FORMAT_RGBX1010102;
88 break;
89 case DRM_FORMAT_ABGR2101010:
90 sprctl |= SP_FORMAT_RGBA1010102;
91 break;
92 case DRM_FORMAT_XBGR8888:
93 sprctl |= SP_FORMAT_RGBX8888;
94 break;
95 case DRM_FORMAT_ABGR8888:
96 sprctl |= SP_FORMAT_RGBA8888;
97 break;
98 default:
99 /*
100 * If we get here one of the upper layers failed to filter
101 * out the unsupported plane formats
102 */
103 BUG();
104 break;
105 }
106
4ea67bc7
VS
107 /*
108 * Enable gamma to match primary/cursor plane behaviour.
109 * FIXME should be user controllable via propertiesa.
110 */
111 sprctl |= SP_GAMMA_ENABLE;
112
7f1f3851
JB
113 if (obj->tiling_mode != I915_TILING_NONE)
114 sprctl |= SP_TILED;
115
116 sprctl |= SP_ENABLE;
117
adf3d35e 118 intel_update_sprite_watermarks(dplane, crtc, src_w, pixel_size, true,
67ca28f3
VS
119 src_w != crtc_w || src_h != crtc_h);
120
7f1f3851
JB
121 /* Sizes are 0 based */
122 src_w--;
123 src_h--;
124 crtc_w--;
125 crtc_h--;
126
7f1f3851
JB
127 I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
128 I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
129
130 linear_offset = y * fb->pitches[0] + x * pixel_size;
131 sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
132 obj->tiling_mode,
133 pixel_size,
134 fb->pitches[0]);
135 linear_offset -= sprsurf_offset;
136
137 if (obj->tiling_mode != I915_TILING_NONE)
138 I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
139 else
140 I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
141
142 I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
143 I915_WRITE(SPCNTR(pipe, plane), sprctl);
f343c5f6 144 I915_MODIFY_DISPBASE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
7f1f3851
JB
145 sprsurf_offset);
146 POSTING_READ(SPSURF(pipe, plane));
147}
148
149static void
b39d53f6 150vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
7f1f3851
JB
151{
152 struct drm_device *dev = dplane->dev;
153 struct drm_i915_private *dev_priv = dev->dev_private;
154 struct intel_plane *intel_plane = to_intel_plane(dplane);
155 int pipe = intel_plane->pipe;
156 int plane = intel_plane->plane;
157
158 I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
159 ~SP_ENABLE);
160 /* Activate double buffered register update */
161 I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0);
162 POSTING_READ(SPSURF(pipe, plane));
a95fd8ca
VS
163
164 intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false);
7f1f3851
JB
165}
166
167static int
168vlv_update_colorkey(struct drm_plane *dplane,
169 struct drm_intel_sprite_colorkey *key)
170{
171 struct drm_device *dev = dplane->dev;
172 struct drm_i915_private *dev_priv = dev->dev_private;
173 struct intel_plane *intel_plane = to_intel_plane(dplane);
174 int pipe = intel_plane->pipe;
175 int plane = intel_plane->plane;
176 u32 sprctl;
177
178 if (key->flags & I915_SET_COLORKEY_DESTINATION)
179 return -EINVAL;
180
181 I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
182 I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
183 I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
184
185 sprctl = I915_READ(SPCNTR(pipe, plane));
186 sprctl &= ~SP_SOURCE_KEY;
187 if (key->flags & I915_SET_COLORKEY_SOURCE)
188 sprctl |= SP_SOURCE_KEY;
189 I915_WRITE(SPCNTR(pipe, plane), sprctl);
190
191 POSTING_READ(SPKEYMSK(pipe, plane));
192
193 return 0;
194}
195
196static void
197vlv_get_colorkey(struct drm_plane *dplane,
198 struct drm_intel_sprite_colorkey *key)
199{
200 struct drm_device *dev = dplane->dev;
201 struct drm_i915_private *dev_priv = dev->dev_private;
202 struct intel_plane *intel_plane = to_intel_plane(dplane);
203 int pipe = intel_plane->pipe;
204 int plane = intel_plane->plane;
205 u32 sprctl;
206
207 key->min_value = I915_READ(SPKEYMINVAL(pipe, plane));
208 key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane));
209 key->channel_mask = I915_READ(SPKEYMSK(pipe, plane));
210
211 sprctl = I915_READ(SPCNTR(pipe, plane));
212 if (sprctl & SP_SOURCE_KEY)
213 key->flags = I915_SET_COLORKEY_SOURCE;
214 else
215 key->flags = I915_SET_COLORKEY_NONE;
216}
217
b840d907 218static void
b39d53f6
VS
219ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
220 struct drm_framebuffer *fb,
b840d907
JB
221 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
222 unsigned int crtc_w, unsigned int crtc_h,
223 uint32_t x, uint32_t y,
224 uint32_t src_w, uint32_t src_h)
225{
226 struct drm_device *dev = plane->dev;
227 struct drm_i915_private *dev_priv = dev->dev_private;
228 struct intel_plane *intel_plane = to_intel_plane(plane);
229 int pipe = intel_plane->pipe;
230 u32 sprctl, sprscale = 0;
5a35e99e 231 unsigned long sprsurf_offset, linear_offset;
2bd3c3cb 232 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
2c6602df 233 bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
b840d907
JB
234
235 sprctl = I915_READ(SPRCTL(pipe));
236
237 /* Mask out pixel format bits in case we change it */
238 sprctl &= ~SPRITE_PIXFORMAT_MASK;
239 sprctl &= ~SPRITE_RGB_ORDER_RGBX;
240 sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
e86fe0d3 241 sprctl &= ~SPRITE_TILED;
b840d907
JB
242
243 switch (fb->pixel_format) {
244 case DRM_FORMAT_XBGR8888:
5ee36913 245 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
b840d907
JB
246 break;
247 case DRM_FORMAT_XRGB8888:
5ee36913 248 sprctl |= SPRITE_FORMAT_RGBX888;
b840d907
JB
249 break;
250 case DRM_FORMAT_YUYV:
251 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
b840d907
JB
252 break;
253 case DRM_FORMAT_YVYU:
254 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
b840d907
JB
255 break;
256 case DRM_FORMAT_UYVY:
257 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
b840d907
JB
258 break;
259 case DRM_FORMAT_VYUY:
260 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
b840d907
JB
261 break;
262 default:
28d491df 263 BUG();
b840d907
JB
264 }
265
4ea67bc7
VS
266 /*
267 * Enable gamma to match primary/cursor plane behaviour.
268 * FIXME should be user controllable via propertiesa.
269 */
270 sprctl |= SPRITE_GAMMA_ENABLE;
271
b840d907
JB
272 if (obj->tiling_mode != I915_TILING_NONE)
273 sprctl |= SPRITE_TILED;
274
b42c6009 275 if (IS_HASWELL(dev) || IS_BROADWELL(dev))
1f5d76db
PZ
276 sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
277 else
278 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
279
b840d907
JB
280 sprctl |= SPRITE_ENABLE;
281
6bbfa1c5 282 if (IS_HASWELL(dev) || IS_BROADWELL(dev))
86d3efce
VS
283 sprctl |= SPRITE_PIPE_CSC_ENABLE;
284
adf3d35e 285 intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
67ca28f3
VS
286 src_w != crtc_w || src_h != crtc_h);
287
b840d907
JB
288 /* Sizes are 0 based */
289 src_w--;
290 src_h--;
291 crtc_w--;
292 crtc_h--;
293
b840d907
JB
294 /*
295 * IVB workaround: must disable low power watermarks for at least
296 * one frame before enabling scaling. LP watermarks can be re-enabled
297 * when scaling is disabled.
298 */
299 if (crtc_w != src_w || crtc_h != src_h) {
2c6602df
VS
300 dev_priv->sprite_scaling_enabled |= 1 << pipe;
301
302 if (!scaling_was_enabled) {
46ba614c 303 intel_update_watermarks(crtc);
828ed3e1
CW
304 intel_wait_for_vblank(dev, pipe);
305 }
b840d907 306 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
2c6602df
VS
307 } else
308 dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
b840d907
JB
309
310 I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
311 I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
c54173a8 312
ca320ac4 313 linear_offset = y * fb->pitches[0] + x * pixel_size;
5a35e99e 314 sprsurf_offset =
bc752862
CW
315 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
316 pixel_size, fb->pitches[0]);
5a35e99e
DL
317 linear_offset -= sprsurf_offset;
318
319 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
320 * register */
b3dc685e 321 if (IS_HASWELL(dev) || IS_BROADWELL(dev))
c54173a8 322 I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
5a35e99e 323 else if (obj->tiling_mode != I915_TILING_NONE)
b840d907 324 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
5a35e99e
DL
325 else
326 I915_WRITE(SPRLINOFF(pipe), linear_offset);
c54173a8 327
b840d907 328 I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
2d354c34
DL
329 if (intel_plane->can_scale)
330 I915_WRITE(SPRSCALE(pipe), sprscale);
b840d907 331 I915_WRITE(SPRCTL(pipe), sprctl);
f343c5f6
BW
332 I915_MODIFY_DISPBASE(SPRSURF(pipe),
333 i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
b840d907 334 POSTING_READ(SPRSURF(pipe));
2c6602df
VS
335
336 /* potentially re-enable LP watermarks */
337 if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
46ba614c 338 intel_update_watermarks(crtc);
b840d907
JB
339}
340
341static void
b39d53f6 342ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
b840d907
JB
343{
344 struct drm_device *dev = plane->dev;
345 struct drm_i915_private *dev_priv = dev->dev_private;
346 struct intel_plane *intel_plane = to_intel_plane(plane);
347 int pipe = intel_plane->pipe;
2c6602df 348 bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
b840d907
JB
349
350 I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
351 /* Can't leave the scaler enabled... */
2d354c34
DL
352 if (intel_plane->can_scale)
353 I915_WRITE(SPRSCALE(pipe), 0);
b840d907 354 /* Activate double buffered register update */
446f2545 355 I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
b840d907 356 POSTING_READ(SPRSURF(pipe));
828ed3e1 357
2c6602df
VS
358 dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
359
adf3d35e 360 intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
4c4ff43a 361
2c6602df
VS
362 /* potentially re-enable LP watermarks */
363 if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
46ba614c 364 intel_update_watermarks(crtc);
b840d907
JB
365}
366
8ea30864
JB
367static int
368ivb_update_colorkey(struct drm_plane *plane,
369 struct drm_intel_sprite_colorkey *key)
370{
371 struct drm_device *dev = plane->dev;
372 struct drm_i915_private *dev_priv = dev->dev_private;
373 struct intel_plane *intel_plane;
374 u32 sprctl;
375 int ret = 0;
376
377 intel_plane = to_intel_plane(plane);
378
379 I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
380 I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
381 I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
382
383 sprctl = I915_READ(SPRCTL(intel_plane->pipe));
384 sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
385 if (key->flags & I915_SET_COLORKEY_DESTINATION)
386 sprctl |= SPRITE_DEST_KEY;
387 else if (key->flags & I915_SET_COLORKEY_SOURCE)
388 sprctl |= SPRITE_SOURCE_KEY;
389 I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
390
391 POSTING_READ(SPRKEYMSK(intel_plane->pipe));
392
393 return ret;
394}
395
396static void
397ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
398{
399 struct drm_device *dev = plane->dev;
400 struct drm_i915_private *dev_priv = dev->dev_private;
401 struct intel_plane *intel_plane;
402 u32 sprctl;
403
404 intel_plane = to_intel_plane(plane);
405
406 key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
407 key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
408 key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
409 key->flags = 0;
410
411 sprctl = I915_READ(SPRCTL(intel_plane->pipe));
412
413 if (sprctl & SPRITE_DEST_KEY)
414 key->flags = I915_SET_COLORKEY_DESTINATION;
415 else if (sprctl & SPRITE_SOURCE_KEY)
416 key->flags = I915_SET_COLORKEY_SOURCE;
417 else
418 key->flags = I915_SET_COLORKEY_NONE;
419}
420
b840d907 421static void
b39d53f6
VS
422ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
423 struct drm_framebuffer *fb,
b840d907
JB
424 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
425 unsigned int crtc_w, unsigned int crtc_h,
426 uint32_t x, uint32_t y,
427 uint32_t src_w, uint32_t src_h)
428{
429 struct drm_device *dev = plane->dev;
430 struct drm_i915_private *dev_priv = dev->dev_private;
431 struct intel_plane *intel_plane = to_intel_plane(plane);
2bd3c3cb 432 int pipe = intel_plane->pipe;
5a35e99e 433 unsigned long dvssurf_offset, linear_offset;
8aaa81a1 434 u32 dvscntr, dvsscale;
2bd3c3cb 435 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
b840d907
JB
436
437 dvscntr = I915_READ(DVSCNTR(pipe));
438
439 /* Mask out pixel format bits in case we change it */
440 dvscntr &= ~DVS_PIXFORMAT_MASK;
ab2f9df1 441 dvscntr &= ~DVS_RGB_ORDER_XBGR;
b840d907 442 dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
79626523 443 dvscntr &= ~DVS_TILED;
b840d907
JB
444
445 switch (fb->pixel_format) {
446 case DRM_FORMAT_XBGR8888:
ab2f9df1 447 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
b840d907
JB
448 break;
449 case DRM_FORMAT_XRGB8888:
ab2f9df1 450 dvscntr |= DVS_FORMAT_RGBX888;
b840d907
JB
451 break;
452 case DRM_FORMAT_YUYV:
453 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
b840d907
JB
454 break;
455 case DRM_FORMAT_YVYU:
456 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
b840d907
JB
457 break;
458 case DRM_FORMAT_UYVY:
459 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
b840d907
JB
460 break;
461 case DRM_FORMAT_VYUY:
462 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
b840d907
JB
463 break;
464 default:
28d491df 465 BUG();
b840d907
JB
466 }
467
4ea67bc7
VS
468 /*
469 * Enable gamma to match primary/cursor plane behaviour.
470 * FIXME should be user controllable via propertiesa.
471 */
472 dvscntr |= DVS_GAMMA_ENABLE;
473
b840d907
JB
474 if (obj->tiling_mode != I915_TILING_NONE)
475 dvscntr |= DVS_TILED;
476
d1686ae3
CW
477 if (IS_GEN6(dev))
478 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
b840d907
JB
479 dvscntr |= DVS_ENABLE;
480
adf3d35e 481 intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
67ca28f3
VS
482 src_w != crtc_w || src_h != crtc_h);
483
b840d907
JB
484 /* Sizes are 0 based */
485 src_w--;
486 src_h--;
487 crtc_w--;
488 crtc_h--;
489
8aaa81a1
CW
490 dvsscale = 0;
491 if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
b840d907
JB
492 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
493
494 I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
495 I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
5a35e99e 496
ca320ac4 497 linear_offset = y * fb->pitches[0] + x * pixel_size;
5a35e99e 498 dvssurf_offset =
bc752862
CW
499 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
500 pixel_size, fb->pitches[0]);
5a35e99e
DL
501 linear_offset -= dvssurf_offset;
502
503 if (obj->tiling_mode != I915_TILING_NONE)
b840d907 504 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
5a35e99e
DL
505 else
506 I915_WRITE(DVSLINOFF(pipe), linear_offset);
b840d907 507
b840d907
JB
508 I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
509 I915_WRITE(DVSSCALE(pipe), dvsscale);
510 I915_WRITE(DVSCNTR(pipe), dvscntr);
f343c5f6
BW
511 I915_MODIFY_DISPBASE(DVSSURF(pipe),
512 i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
b840d907
JB
513 POSTING_READ(DVSSURF(pipe));
514}
515
516static void
b39d53f6 517ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
b840d907
JB
518{
519 struct drm_device *dev = plane->dev;
520 struct drm_i915_private *dev_priv = dev->dev_private;
521 struct intel_plane *intel_plane = to_intel_plane(plane);
522 int pipe = intel_plane->pipe;
523
524 I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
525 /* Disable the scaler */
526 I915_WRITE(DVSSCALE(pipe), 0);
527 /* Flush double buffered register updates */
446f2545 528 I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
b840d907 529 POSTING_READ(DVSSURF(pipe));
a95fd8ca
VS
530
531 intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
b840d907
JB
532}
533
175bd420
JB
534static void
535intel_enable_primary(struct drm_crtc *crtc)
536{
537 struct drm_device *dev = crtc->dev;
538 struct drm_i915_private *dev_priv = dev->dev_private;
539 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
540 int reg = DSPCNTR(intel_crtc->plane);
541
4c445e0e 542 if (intel_crtc->primary_enabled)
93314b5b
CW
543 return;
544
4c445e0e 545 intel_crtc->primary_enabled = true;
82284b6b 546
abae50ed 547 I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
0fc9f599 548 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
abae50ed 549
20bc8673
VS
550 /*
551 * FIXME IPS should be fine as long as one plane is
552 * enabled, but in practice it seems to have problems
553 * when going from primary only to sprite only and vice
554 * versa.
555 */
556 if (intel_crtc->config.ips_enabled) {
557 intel_wait_for_vblank(dev, intel_crtc->pipe);
558 hsw_enable_ips(intel_crtc);
559 }
560
82284b6b 561 mutex_lock(&dev->struct_mutex);
93314b5b 562 intel_update_fbc(dev);
82284b6b 563 mutex_unlock(&dev->struct_mutex);
175bd420
JB
564}
565
566static void
567intel_disable_primary(struct drm_crtc *crtc)
568{
569 struct drm_device *dev = crtc->dev;
570 struct drm_i915_private *dev_priv = dev->dev_private;
571 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
572 int reg = DSPCNTR(intel_crtc->plane);
573
4c445e0e 574 if (!intel_crtc->primary_enabled)
93314b5b
CW
575 return;
576
4c445e0e 577 intel_crtc->primary_enabled = false;
82284b6b
VS
578
579 mutex_lock(&dev->struct_mutex);
abae50ed
VS
580 if (dev_priv->fbc.plane == intel_crtc->plane)
581 intel_disable_fbc(dev);
82284b6b 582 mutex_unlock(&dev->struct_mutex);
abae50ed 583
20bc8673
VS
584 /*
585 * FIXME IPS should be fine as long as one plane is
586 * enabled, but in practice it seems to have problems
587 * when going from primary only to sprite only and vice
588 * versa.
589 */
590 hsw_disable_ips(intel_crtc);
591
abae50ed 592 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
0fc9f599 593 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
175bd420
JB
594}
595
8ea30864 596static int
d1686ae3 597ilk_update_colorkey(struct drm_plane *plane,
8ea30864
JB
598 struct drm_intel_sprite_colorkey *key)
599{
600 struct drm_device *dev = plane->dev;
601 struct drm_i915_private *dev_priv = dev->dev_private;
602 struct intel_plane *intel_plane;
603 u32 dvscntr;
604 int ret = 0;
605
606 intel_plane = to_intel_plane(plane);
607
608 I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
609 I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
610 I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
611
612 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
613 dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
614 if (key->flags & I915_SET_COLORKEY_DESTINATION)
615 dvscntr |= DVS_DEST_KEY;
616 else if (key->flags & I915_SET_COLORKEY_SOURCE)
617 dvscntr |= DVS_SOURCE_KEY;
618 I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
619
620 POSTING_READ(DVSKEYMSK(intel_plane->pipe));
621
622 return ret;
623}
624
625static void
d1686ae3 626ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
8ea30864
JB
627{
628 struct drm_device *dev = plane->dev;
629 struct drm_i915_private *dev_priv = dev->dev_private;
630 struct intel_plane *intel_plane;
631 u32 dvscntr;
632
633 intel_plane = to_intel_plane(plane);
634
635 key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
636 key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
637 key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
638 key->flags = 0;
639
640 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
641
642 if (dvscntr & DVS_DEST_KEY)
643 key->flags = I915_SET_COLORKEY_DESTINATION;
644 else if (dvscntr & DVS_SOURCE_KEY)
645 key->flags = I915_SET_COLORKEY_SOURCE;
646 else
647 key->flags = I915_SET_COLORKEY_NONE;
648}
649
1731693a
VS
650static bool
651format_is_yuv(uint32_t format)
652{
653 switch (format) {
654 case DRM_FORMAT_YUYV:
655 case DRM_FORMAT_UYVY:
656 case DRM_FORMAT_VYUY:
657 case DRM_FORMAT_YVYU:
658 return true;
659 default:
660 return false;
661 }
662}
663
b840d907
JB
664static int
665intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
666 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
667 unsigned int crtc_w, unsigned int crtc_h,
668 uint32_t src_x, uint32_t src_y,
669 uint32_t src_w, uint32_t src_h)
670{
671 struct drm_device *dev = plane->dev;
b840d907
JB
672 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
673 struct intel_plane *intel_plane = to_intel_plane(plane);
2afd9efd
VS
674 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
675 struct drm_i915_gem_object *obj = intel_fb->obj;
676 struct drm_i915_gem_object *old_obj = intel_plane->obj;
677 int ret;
b840d907 678 bool disable_primary = false;
1731693a
VS
679 bool visible;
680 int hscale, vscale;
681 int max_scale, min_scale;
682 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
683 struct drm_rect src = {
684 /* sample coordinates in 16.16 fixed point */
685 .x1 = src_x,
686 .x2 = src_x + src_w,
687 .y1 = src_y,
688 .y2 = src_y + src_h,
689 };
690 struct drm_rect dst = {
691 /* integer pixels */
692 .x1 = crtc_x,
693 .x2 = crtc_x + crtc_w,
694 .y1 = crtc_y,
695 .y2 = crtc_y + crtc_h,
696 };
697 const struct drm_rect clip = {
03c5b25f
VS
698 .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
699 .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
1731693a 700 };
098ebd6b
VS
701 const struct {
702 int crtc_x, crtc_y;
703 unsigned int crtc_w, crtc_h;
704 uint32_t src_x, src_y, src_w, src_h;
705 } orig = {
706 .crtc_x = crtc_x,
707 .crtc_y = crtc_y,
708 .crtc_w = crtc_w,
709 .crtc_h = crtc_h,
710 .src_x = src_x,
711 .src_y = src_y,
712 .src_w = src_w,
713 .src_h = src_h,
714 };
5e1bac2f 715
1731693a
VS
716 /* Don't modify another pipe's plane */
717 if (intel_plane->pipe != intel_crtc->pipe) {
718 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
b840d907 719 return -EINVAL;
1731693a 720 }
b840d907 721
1731693a
VS
722 /* FIXME check all gen limits */
723 if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) {
724 DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
b840d907 725 return -EINVAL;
1731693a 726 }
b840d907 727
94c6419e
DL
728 /* Sprite planes can be linear or x-tiled surfaces */
729 switch (obj->tiling_mode) {
730 case I915_TILING_NONE:
731 case I915_TILING_X:
732 break;
733 default:
1731693a 734 DRM_DEBUG_KMS("Unsupported tiling mode\n");
94c6419e
DL
735 return -EINVAL;
736 }
737
3c3686cd
VS
738 /*
739 * FIXME the following code does a bunch of fuzzy adjustments to the
740 * coordinates and sizes. We probably need some way to decide whether
741 * more strict checking should be done instead.
742 */
1731693a
VS
743 max_scale = intel_plane->max_downscale << 16;
744 min_scale = intel_plane->can_scale ? 1 : (1 << 16);
745
3c3686cd
VS
746 hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale);
747 BUG_ON(hscale < 0);
1731693a 748
3c3686cd
VS
749 vscale = drm_rect_calc_vscale_relaxed(&src, &dst, min_scale, max_scale);
750 BUG_ON(vscale < 0);
b840d907 751
1731693a 752 visible = drm_rect_clip_scaled(&src, &dst, &clip, hscale, vscale);
b840d907 753
1731693a
VS
754 crtc_x = dst.x1;
755 crtc_y = dst.y1;
756 crtc_w = drm_rect_width(&dst);
757 crtc_h = drm_rect_height(&dst);
2d354c34 758
1731693a 759 if (visible) {
3c3686cd
VS
760 /* check again in case clipping clamped the results */
761 hscale = drm_rect_calc_hscale(&src, &dst, min_scale, max_scale);
762 if (hscale < 0) {
763 DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
764 drm_rect_debug_print(&src, true);
765 drm_rect_debug_print(&dst, false);
766
767 return hscale;
768 }
769
770 vscale = drm_rect_calc_vscale(&src, &dst, min_scale, max_scale);
771 if (vscale < 0) {
772 DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
773 drm_rect_debug_print(&src, true);
774 drm_rect_debug_print(&dst, false);
775
776 return vscale;
777 }
778
1731693a
VS
779 /* Make the source viewport size an exact multiple of the scaling factors. */
780 drm_rect_adjust_size(&src,
781 drm_rect_width(&dst) * hscale - drm_rect_width(&src),
782 drm_rect_height(&dst) * vscale - drm_rect_height(&src));
783
784 /* sanity check to make sure the src viewport wasn't enlarged */
785 WARN_ON(src.x1 < (int) src_x ||
786 src.y1 < (int) src_y ||
787 src.x2 > (int) (src_x + src_w) ||
788 src.y2 > (int) (src_y + src_h));
789
790 /*
791 * Hardware doesn't handle subpixel coordinates.
792 * Adjust to (macro)pixel boundary, but be careful not to
793 * increase the source viewport size, because that could
794 * push the downscaling factor out of bounds.
1731693a
VS
795 */
796 src_x = src.x1 >> 16;
797 src_w = drm_rect_width(&src) >> 16;
798 src_y = src.y1 >> 16;
799 src_h = drm_rect_height(&src) >> 16;
800
801 if (format_is_yuv(fb->pixel_format)) {
802 src_x &= ~1;
803 src_w &= ~1;
804
805 /*
806 * Must keep src and dst the
807 * same if we can't scale.
808 */
809 if (!intel_plane->can_scale)
810 crtc_w &= ~1;
811
812 if (crtc_w == 0)
813 visible = false;
814 }
815 }
816
817 /* Check size restrictions when scaling */
818 if (visible && (src_w != crtc_w || src_h != crtc_h)) {
819 unsigned int width_bytes;
820
821 WARN_ON(!intel_plane->can_scale);
822
823 /* FIXME interlacing min height is 6 */
824
825 if (crtc_w < 3 || crtc_h < 3)
826 visible = false;
827
828 if (src_w < 3 || src_h < 3)
829 visible = false;
830
831 width_bytes = ((src_x * pixel_size) & 63) + src_w * pixel_size;
832
833 if (src_w > 2048 || src_h > 2048 ||
834 width_bytes > 4096 || fb->pitches[0] > 4096) {
835 DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
836 return -EINVAL;
837 }
838 }
839
840 dst.x1 = crtc_x;
841 dst.x2 = crtc_x + crtc_w;
842 dst.y1 = crtc_y;
843 dst.y2 = crtc_y + crtc_h;
b840d907
JB
844
845 /*
846 * If the sprite is completely covering the primary plane,
847 * we can disable the primary and save power.
848 */
1731693a 849 disable_primary = drm_rect_equals(&dst, &clip);
03c5b25f 850 WARN_ON(disable_primary && !visible && intel_crtc->active);
b840d907
JB
851
852 mutex_lock(&dev->struct_mutex);
853
693db184
CW
854 /* Note that this will apply the VT-d workaround for scanouts,
855 * which is more restrictive than required for sprites. (The
856 * primary plane requires 256KiB alignment with 64 PTE padding,
857 * the sprite planes only require 128KiB alignment and 32 PTE padding.
858 */
b840d907 859 ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
82284b6b
VS
860
861 mutex_unlock(&dev->struct_mutex);
862
00c2064b 863 if (ret)
82284b6b 864 return ret;
b840d907 865
098ebd6b
VS
866 intel_plane->crtc_x = orig.crtc_x;
867 intel_plane->crtc_y = orig.crtc_y;
868 intel_plane->crtc_w = orig.crtc_w;
869 intel_plane->crtc_h = orig.crtc_h;
870 intel_plane->src_x = orig.src_x;
871 intel_plane->src_y = orig.src_y;
872 intel_plane->src_w = orig.src_w;
873 intel_plane->src_h = orig.src_h;
b840d907
JB
874 intel_plane->obj = obj;
875
03c5b25f
VS
876 if (intel_crtc->active) {
877 /*
878 * Be sure to re-enable the primary before the sprite is no longer
879 * covering it fully.
880 */
881 if (!disable_primary)
882 intel_enable_primary(crtc);
883
884 if (visible)
885 intel_plane->update_plane(plane, crtc, fb, obj,
886 crtc_x, crtc_y, crtc_w, crtc_h,
887 src_x, src_y, src_w, src_h);
888 else
889 intel_plane->disable_plane(plane, crtc);
890
891 if (disable_primary)
892 intel_disable_primary(crtc);
893 }
175bd420 894
b840d907
JB
895 /* Unpin old obj after new one is active to avoid ugliness */
896 if (old_obj) {
897 /*
898 * It's fairly common to simply update the position of
899 * an existing object. In that case, we don't need to
900 * wait for vblank to avoid ugliness, we only need to
901 * do the pin & ref bookkeeping.
902 */
82284b6b 903 if (old_obj != obj && intel_crtc->active)
2afd9efd 904 intel_wait_for_vblank(dev, intel_crtc->pipe);
82284b6b
VS
905
906 mutex_lock(&dev->struct_mutex);
1690e1eb 907 intel_unpin_fb_obj(old_obj);
82284b6b 908 mutex_unlock(&dev->struct_mutex);
b840d907
JB
909 }
910
82284b6b 911 return 0;
b840d907
JB
912}
913
914static int
915intel_disable_plane(struct drm_plane *plane)
916{
917 struct drm_device *dev = plane->dev;
918 struct intel_plane *intel_plane = to_intel_plane(plane);
03c5b25f 919 struct intel_crtc *intel_crtc;
b840d907 920
88a94a58
VS
921 if (!plane->fb)
922 return 0;
923
924 if (WARN_ON(!plane->crtc))
925 return -EINVAL;
926
03c5b25f
VS
927 intel_crtc = to_intel_crtc(plane->crtc);
928
929 if (intel_crtc->active) {
930 intel_enable_primary(plane->crtc);
931 intel_plane->disable_plane(plane, plane->crtc);
932 }
b840d907 933
5f3fb46b
VS
934 if (intel_plane->obj) {
935 if (intel_crtc->active)
936 intel_wait_for_vblank(dev, intel_plane->pipe);
c626d317 937
5f3fb46b
VS
938 mutex_lock(&dev->struct_mutex);
939 intel_unpin_fb_obj(intel_plane->obj);
940 mutex_unlock(&dev->struct_mutex);
82284b6b 941
5f3fb46b
VS
942 intel_plane->obj = NULL;
943 }
b840d907 944
5f3fb46b 945 return 0;
b840d907
JB
946}
947
948static void intel_destroy_plane(struct drm_plane *plane)
949{
950 struct intel_plane *intel_plane = to_intel_plane(plane);
951 intel_disable_plane(plane);
952 drm_plane_cleanup(plane);
953 kfree(intel_plane);
954}
955
8ea30864
JB
956int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
957 struct drm_file *file_priv)
958{
959 struct drm_intel_sprite_colorkey *set = data;
8ea30864
JB
960 struct drm_mode_object *obj;
961 struct drm_plane *plane;
962 struct intel_plane *intel_plane;
963 int ret = 0;
964
1cff8f6b
DV
965 if (!drm_core_check_feature(dev, DRIVER_MODESET))
966 return -ENODEV;
8ea30864
JB
967
968 /* Make sure we don't try to enable both src & dest simultaneously */
969 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
970 return -EINVAL;
971
a0e99e68 972 drm_modeset_lock_all(dev);
8ea30864
JB
973
974 obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
975 if (!obj) {
3f2c2057 976 ret = -ENOENT;
8ea30864
JB
977 goto out_unlock;
978 }
979
980 plane = obj_to_plane(obj);
981 intel_plane = to_intel_plane(plane);
982 ret = intel_plane->update_colorkey(plane, set);
983
984out_unlock:
a0e99e68 985 drm_modeset_unlock_all(dev);
8ea30864
JB
986 return ret;
987}
988
989int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
990 struct drm_file *file_priv)
991{
992 struct drm_intel_sprite_colorkey *get = data;
8ea30864
JB
993 struct drm_mode_object *obj;
994 struct drm_plane *plane;
995 struct intel_plane *intel_plane;
996 int ret = 0;
997
1cff8f6b
DV
998 if (!drm_core_check_feature(dev, DRIVER_MODESET))
999 return -ENODEV;
8ea30864 1000
a0e99e68 1001 drm_modeset_lock_all(dev);
8ea30864
JB
1002
1003 obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
1004 if (!obj) {
3f2c2057 1005 ret = -ENOENT;
8ea30864
JB
1006 goto out_unlock;
1007 }
1008
1009 plane = obj_to_plane(obj);
1010 intel_plane = to_intel_plane(plane);
1011 intel_plane->get_colorkey(plane, get);
1012
1013out_unlock:
a0e99e68 1014 drm_modeset_unlock_all(dev);
8ea30864
JB
1015 return ret;
1016}
1017
5e1bac2f
JB
1018void intel_plane_restore(struct drm_plane *plane)
1019{
1020 struct intel_plane *intel_plane = to_intel_plane(plane);
1021
1022 if (!plane->crtc || !plane->fb)
1023 return;
1024
1025 intel_update_plane(plane, plane->crtc, plane->fb,
1026 intel_plane->crtc_x, intel_plane->crtc_y,
1027 intel_plane->crtc_w, intel_plane->crtc_h,
1028 intel_plane->src_x, intel_plane->src_y,
1029 intel_plane->src_w, intel_plane->src_h);
1030}
1031
bb53d4ae
VS
1032void intel_plane_disable(struct drm_plane *plane)
1033{
1034 if (!plane->crtc || !plane->fb)
1035 return;
1036
1037 intel_disable_plane(plane);
1038}
1039
b840d907
JB
1040static const struct drm_plane_funcs intel_plane_funcs = {
1041 .update_plane = intel_update_plane,
1042 .disable_plane = intel_disable_plane,
1043 .destroy = intel_destroy_plane,
1044};
1045
d1686ae3
CW
1046static uint32_t ilk_plane_formats[] = {
1047 DRM_FORMAT_XRGB8888,
1048 DRM_FORMAT_YUYV,
1049 DRM_FORMAT_YVYU,
1050 DRM_FORMAT_UYVY,
1051 DRM_FORMAT_VYUY,
1052};
1053
b840d907
JB
1054static uint32_t snb_plane_formats[] = {
1055 DRM_FORMAT_XBGR8888,
1056 DRM_FORMAT_XRGB8888,
1057 DRM_FORMAT_YUYV,
1058 DRM_FORMAT_YVYU,
1059 DRM_FORMAT_UYVY,
1060 DRM_FORMAT_VYUY,
1061};
1062
7f1f3851
JB
1063static uint32_t vlv_plane_formats[] = {
1064 DRM_FORMAT_RGB565,
1065 DRM_FORMAT_ABGR8888,
1066 DRM_FORMAT_ARGB8888,
1067 DRM_FORMAT_XBGR8888,
1068 DRM_FORMAT_XRGB8888,
1069 DRM_FORMAT_XBGR2101010,
1070 DRM_FORMAT_ABGR2101010,
1071 DRM_FORMAT_YUYV,
1072 DRM_FORMAT_YVYU,
1073 DRM_FORMAT_UYVY,
1074 DRM_FORMAT_VYUY,
1075};
1076
b840d907 1077int
7f1f3851 1078intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
b840d907
JB
1079{
1080 struct intel_plane *intel_plane;
1081 unsigned long possible_crtcs;
d1686ae3
CW
1082 const uint32_t *plane_formats;
1083 int num_plane_formats;
b840d907
JB
1084 int ret;
1085
d1686ae3 1086 if (INTEL_INFO(dev)->gen < 5)
b840d907 1087 return -ENODEV;
b840d907 1088
b14c5679 1089 intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
b840d907
JB
1090 if (!intel_plane)
1091 return -ENOMEM;
1092
d1686ae3
CW
1093 switch (INTEL_INFO(dev)->gen) {
1094 case 5:
1095 case 6:
2d354c34 1096 intel_plane->can_scale = true;
b840d907 1097 intel_plane->max_downscale = 16;
d1686ae3
CW
1098 intel_plane->update_plane = ilk_update_plane;
1099 intel_plane->disable_plane = ilk_disable_plane;
1100 intel_plane->update_colorkey = ilk_update_colorkey;
1101 intel_plane->get_colorkey = ilk_get_colorkey;
1102
1103 if (IS_GEN6(dev)) {
1104 plane_formats = snb_plane_formats;
1105 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1106 } else {
1107 plane_formats = ilk_plane_formats;
1108 num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
1109 }
1110 break;
1111
1112 case 7:
4e0bbc31 1113 case 8:
d49f7091 1114 if (IS_IVYBRIDGE(dev)) {
2d354c34 1115 intel_plane->can_scale = true;
d49f7091
DL
1116 intel_plane->max_downscale = 2;
1117 } else {
1118 intel_plane->can_scale = false;
1119 intel_plane->max_downscale = 1;
1120 }
7f1f3851
JB
1121
1122 if (IS_VALLEYVIEW(dev)) {
7f1f3851
JB
1123 intel_plane->update_plane = vlv_update_plane;
1124 intel_plane->disable_plane = vlv_disable_plane;
1125 intel_plane->update_colorkey = vlv_update_colorkey;
1126 intel_plane->get_colorkey = vlv_get_colorkey;
1127
1128 plane_formats = vlv_plane_formats;
1129 num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1130 } else {
7f1f3851
JB
1131 intel_plane->update_plane = ivb_update_plane;
1132 intel_plane->disable_plane = ivb_disable_plane;
1133 intel_plane->update_colorkey = ivb_update_colorkey;
1134 intel_plane->get_colorkey = ivb_get_colorkey;
1135
1136 plane_formats = snb_plane_formats;
1137 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1138 }
d1686ae3
CW
1139 break;
1140
1141 default:
a8b0bbab 1142 kfree(intel_plane);
d1686ae3 1143 return -ENODEV;
b840d907
JB
1144 }
1145
1146 intel_plane->pipe = pipe;
7f1f3851 1147 intel_plane->plane = plane;
b840d907
JB
1148 possible_crtcs = (1 << pipe);
1149 ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
d1686ae3
CW
1150 &intel_plane_funcs,
1151 plane_formats, num_plane_formats,
1152 false);
b840d907
JB
1153 if (ret)
1154 kfree(intel_plane);
1155
1156 return ret;
1157}
This page took 0.237721 seconds and 5 git commands to generate.