]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/gpu/drm/i915/intel_overlay.c
drm/i915: Fix race on unreferencing the wrong mmio-flip-request
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / i915 / intel_overlay.c
CommitLineData
02e792fb
DV
1/*
2 * Copyright © 2009
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 * Daniel Vetter <daniel@ffwll.ch>
25 *
26 * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
27 */
760285e7
DH
28#include <drm/drmP.h>
29#include <drm/i915_drm.h>
02e792fb
DV
30#include "i915_drv.h"
31#include "i915_reg.h"
32#include "intel_drv.h"
33
34/* Limits for overlay size. According to intel doc, the real limits are:
35 * Y width: 4095, UV width (planar): 2047, Y height: 2047,
36 * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use
37 * the mininum of both. */
38#define IMAGE_MAX_WIDTH 2048
39#define IMAGE_MAX_HEIGHT 2046 /* 2 * 1023 */
40/* on 830 and 845 these large limits result in the card hanging */
41#define IMAGE_MAX_WIDTH_LEGACY 1024
42#define IMAGE_MAX_HEIGHT_LEGACY 1088
43
44/* overlay register definitions */
45/* OCMD register */
46#define OCMD_TILED_SURFACE (0x1<<19)
47#define OCMD_MIRROR_MASK (0x3<<17)
48#define OCMD_MIRROR_MODE (0x3<<17)
49#define OCMD_MIRROR_HORIZONTAL (0x1<<17)
50#define OCMD_MIRROR_VERTICAL (0x2<<17)
51#define OCMD_MIRROR_BOTH (0x3<<17)
52#define OCMD_BYTEORDER_MASK (0x3<<14) /* zero for YUYV or FOURCC YUY2 */
53#define OCMD_UV_SWAP (0x1<<14) /* YVYU */
54#define OCMD_Y_SWAP (0x2<<14) /* UYVY or FOURCC UYVY */
55#define OCMD_Y_AND_UV_SWAP (0x3<<14) /* VYUY */
56#define OCMD_SOURCE_FORMAT_MASK (0xf<<10)
57#define OCMD_RGB_888 (0x1<<10) /* not in i965 Intel docs */
58#define OCMD_RGB_555 (0x2<<10) /* not in i965 Intel docs */
59#define OCMD_RGB_565 (0x3<<10) /* not in i965 Intel docs */
60#define OCMD_YUV_422_PACKED (0x8<<10)
61#define OCMD_YUV_411_PACKED (0x9<<10) /* not in i965 Intel docs */
62#define OCMD_YUV_420_PLANAR (0xc<<10)
63#define OCMD_YUV_422_PLANAR (0xd<<10)
64#define OCMD_YUV_410_PLANAR (0xe<<10) /* also 411 */
65#define OCMD_TVSYNCFLIP_PARITY (0x1<<9)
66#define OCMD_TVSYNCFLIP_ENABLE (0x1<<7)
d7961364 67#define OCMD_BUF_TYPE_MASK (0x1<<5)
02e792fb
DV
68#define OCMD_BUF_TYPE_FRAME (0x0<<5)
69#define OCMD_BUF_TYPE_FIELD (0x1<<5)
70#define OCMD_TEST_MODE (0x1<<4)
71#define OCMD_BUFFER_SELECT (0x3<<2)
72#define OCMD_BUFFER0 (0x0<<2)
73#define OCMD_BUFFER1 (0x1<<2)
74#define OCMD_FIELD_SELECT (0x1<<2)
75#define OCMD_FIELD0 (0x0<<1)
76#define OCMD_FIELD1 (0x1<<1)
77#define OCMD_ENABLE (0x1<<0)
78
79/* OCONFIG register */
80#define OCONF_PIPE_MASK (0x1<<18)
81#define OCONF_PIPE_A (0x0<<18)
82#define OCONF_PIPE_B (0x1<<18)
83#define OCONF_GAMMA2_ENABLE (0x1<<16)
84#define OCONF_CSC_MODE_BT601 (0x0<<5)
85#define OCONF_CSC_MODE_BT709 (0x1<<5)
86#define OCONF_CSC_BYPASS (0x1<<4)
87#define OCONF_CC_OUT_8BIT (0x1<<3)
88#define OCONF_TEST_MODE (0x1<<2)
89#define OCONF_THREE_LINE_BUFFER (0x1<<0)
90#define OCONF_TWO_LINE_BUFFER (0x0<<0)
91
92/* DCLRKM (dst-key) register */
93#define DST_KEY_ENABLE (0x1<<31)
94#define CLK_RGB24_MASK 0x0
95#define CLK_RGB16_MASK 0x070307
96#define CLK_RGB15_MASK 0x070707
97#define CLK_RGB8I_MASK 0xffffff
98
99#define RGB16_TO_COLORKEY(c) \
100 (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
101#define RGB15_TO_COLORKEY(c) \
102 (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
103
104/* overlay flip addr flag */
105#define OFC_UPDATE 0x1
106
107/* polyphase filter coefficients */
108#define N_HORIZ_Y_TAPS 5
109#define N_VERT_Y_TAPS 3
110#define N_HORIZ_UV_TAPS 3
111#define N_VERT_UV_TAPS 3
112#define N_PHASES 17
113#define MAX_TAPS 5
114
115/* memory bufferd overlay registers */
116struct overlay_registers {
0206e353
AJ
117 u32 OBUF_0Y;
118 u32 OBUF_1Y;
119 u32 OBUF_0U;
120 u32 OBUF_0V;
121 u32 OBUF_1U;
122 u32 OBUF_1V;
123 u32 OSTRIDE;
124 u32 YRGB_VPH;
125 u32 UV_VPH;
126 u32 HORZ_PH;
127 u32 INIT_PHS;
128 u32 DWINPOS;
129 u32 DWINSZ;
130 u32 SWIDTH;
131 u32 SWIDTHSW;
132 u32 SHEIGHT;
133 u32 YRGBSCALE;
134 u32 UVSCALE;
135 u32 OCLRC0;
136 u32 OCLRC1;
137 u32 DCLRKV;
138 u32 DCLRKM;
139 u32 SCLRKVH;
140 u32 SCLRKVL;
141 u32 SCLRKEN;
142 u32 OCONFIG;
143 u32 OCMD;
144 u32 RESERVED1; /* 0x6C */
145 u32 OSTART_0Y;
146 u32 OSTART_1Y;
147 u32 OSTART_0U;
148 u32 OSTART_0V;
149 u32 OSTART_1U;
150 u32 OSTART_1V;
151 u32 OTILEOFF_0Y;
152 u32 OTILEOFF_1Y;
153 u32 OTILEOFF_0U;
154 u32 OTILEOFF_0V;
155 u32 OTILEOFF_1U;
156 u32 OTILEOFF_1V;
157 u32 FASTHSCALE; /* 0xA0 */
158 u32 UVSCALEV; /* 0xA4 */
159 u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
160 u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
161 u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
162 u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
163 u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
164 u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
165 u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
166 u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
167 u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
02e792fb
DV
168};
169
23f09ce3
CW
170struct intel_overlay {
171 struct drm_device *dev;
172 struct intel_crtc *crtc;
173 struct drm_i915_gem_object *vid_bo;
174 struct drm_i915_gem_object *old_vid_bo;
209c2a5e
VS
175 bool active;
176 bool pfit_active;
23f09ce3 177 u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
ea9da4e4
CW
178 u32 color_key:24;
179 u32 color_key_enabled:1;
23f09ce3
CW
180 u32 brightness, contrast, saturation;
181 u32 old_xscale, old_yscale;
182 /* register access */
183 u32 flip_addr;
184 struct drm_i915_gem_object *reg_bo;
185 /* flip handling */
9bfc01a2 186 struct drm_i915_gem_request *last_flip_req;
b303cf95 187 void (*flip_tail)(struct intel_overlay *);
23f09ce3 188};
02e792fb 189
75020bc1 190static struct overlay_registers __iomem *
8d74f656 191intel_overlay_map_regs(struct intel_overlay *overlay)
02e792fb 192{
d5d45cc5 193 struct drm_i915_private *dev_priv = overlay->dev->dev_private;
75020bc1 194 struct overlay_registers __iomem *regs;
02e792fb 195
9bb2ff73 196 if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
00731155 197 regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr;
9bb2ff73 198 else
5d4545ae 199 regs = io_mapping_map_wc(dev_priv->gtt.mappable,
f343c5f6 200 i915_gem_obj_ggtt_offset(overlay->reg_bo));
02e792fb 201
9bb2ff73 202 return regs;
8d74f656 203}
02e792fb 204
9bb2ff73 205static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
75020bc1 206 struct overlay_registers __iomem *regs)
8d74f656
CW
207{
208 if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
9bb2ff73 209 io_mapping_unmap(regs);
02e792fb
DV
210}
211
b6c028e0 212static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
b303cf95 213 void (*tail)(struct intel_overlay *))
02e792fb
DV
214{
215 struct drm_device *dev = overlay->dev;
d5d45cc5 216 struct drm_i915_private *dev_priv = dev->dev_private;
a4872ba6 217 struct intel_engine_cs *ring = &dev_priv->ring[RCS];
b6c028e0 218 int ret;
02e792fb 219
77589f56 220 WARN_ON(overlay->last_flip_req);
9bfc01a2
JH
221 i915_gem_request_assign(&overlay->last_flip_req,
222 ring->outstanding_lazy_request);
9400ae5c 223 ret = i915_add_request(ring);
acb868d3
CW
224 if (ret)
225 return ret;
226
b303cf95 227 overlay->flip_tail = tail;
a4b3a571 228 ret = i915_wait_request(overlay->last_flip_req);
b6c028e0 229 if (ret)
03f77ea5 230 return ret;
b2da9fe5 231 i915_gem_retire_requests(dev);
02e792fb 232
9bfc01a2 233 i915_gem_request_assign(&overlay->last_flip_req, NULL);
02e792fb 234 return 0;
02e792fb
DV
235}
236
02e792fb
DV
237/* overlay needs to be disable in OCMD reg */
238static int intel_overlay_on(struct intel_overlay *overlay)
239{
240 struct drm_device *dev = overlay->dev;
e1f99ce6 241 struct drm_i915_private *dev_priv = dev->dev_private;
a4872ba6 242 struct intel_engine_cs *ring = &dev_priv->ring[RCS];
02e792fb 243 int ret;
02e792fb 244
77589f56 245 WARN_ON(overlay->active);
6306cb4f 246 WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE));
106dadac 247
6d90c952 248 ret = intel_ring_begin(ring, 4);
acb868d3
CW
249 if (ret)
250 return ret;
e1f99ce6 251
1c7c4301
VS
252 overlay->active = true;
253
6d90c952
DV
254 intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
255 intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE);
256 intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
257 intel_ring_emit(ring, MI_NOOP);
258 intel_ring_advance(ring);
02e792fb 259
acb868d3 260 return intel_overlay_do_wait_request(overlay, NULL);
02e792fb
DV
261}
262
263/* overlay needs to be enabled in OCMD reg */
8dc5d147
CW
264static int intel_overlay_continue(struct intel_overlay *overlay,
265 bool load_polyphase_filter)
02e792fb
DV
266{
267 struct drm_device *dev = overlay->dev;
d5d45cc5 268 struct drm_i915_private *dev_priv = dev->dev_private;
a4872ba6 269 struct intel_engine_cs *ring = &dev_priv->ring[RCS];
02e792fb
DV
270 u32 flip_addr = overlay->flip_addr;
271 u32 tmp;
e1f99ce6 272 int ret;
02e792fb 273
77589f56 274 WARN_ON(!overlay->active);
02e792fb
DV
275
276 if (load_polyphase_filter)
277 flip_addr |= OFC_UPDATE;
278
279 /* check for underruns */
280 tmp = I915_READ(DOVSTA);
281 if (tmp & (1 << 17))
282 DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
283
6d90c952 284 ret = intel_ring_begin(ring, 2);
acb868d3 285 if (ret)
e1f99ce6 286 return ret;
acb868d3 287
6d90c952
DV
288 intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
289 intel_ring_emit(ring, flip_addr);
290 intel_ring_advance(ring);
5a5a0c64 291
9bfc01a2
JH
292 WARN_ON(overlay->last_flip_req);
293 i915_gem_request_assign(&overlay->last_flip_req,
294 ring->outstanding_lazy_request);
9400ae5c 295 return i915_add_request(ring);
5a5a0c64
DV
296}
297
b303cf95 298static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
5a5a0c64 299{
05394f39 300 struct drm_i915_gem_object *obj = overlay->old_vid_bo;
5a5a0c64 301
d7f46fc4 302 i915_gem_object_ggtt_unpin(obj);
05394f39 303 drm_gem_object_unreference(&obj->base);
5a5a0c64 304
b303cf95
CW
305 overlay->old_vid_bo = NULL;
306}
03f77ea5 307
b303cf95
CW
308static void intel_overlay_off_tail(struct intel_overlay *overlay)
309{
05394f39 310 struct drm_i915_gem_object *obj = overlay->vid_bo;
02e792fb 311
b303cf95 312 /* never have the overlay hw on without showing a frame */
77589f56
VS
313 if (WARN_ON(!obj))
314 return;
02e792fb 315
d7f46fc4 316 i915_gem_object_ggtt_unpin(obj);
05394f39 317 drm_gem_object_unreference(&obj->base);
b303cf95 318 overlay->vid_bo = NULL;
03f77ea5 319
b303cf95
CW
320 overlay->crtc->overlay = NULL;
321 overlay->crtc = NULL;
209c2a5e 322 overlay->active = false;
02e792fb
DV
323}
324
325/* overlay needs to be disabled in OCMD reg */
ce453d81 326static int intel_overlay_off(struct intel_overlay *overlay)
02e792fb 327{
02e792fb 328 struct drm_device *dev = overlay->dev;
e1f99ce6 329 struct drm_i915_private *dev_priv = dev->dev_private;
a4872ba6 330 struct intel_engine_cs *ring = &dev_priv->ring[RCS];
8dc5d147 331 u32 flip_addr = overlay->flip_addr;
e1f99ce6 332 int ret;
02e792fb 333
77589f56 334 WARN_ON(!overlay->active);
02e792fb
DV
335
336 /* According to intel docs the overlay hw may hang (when switching
337 * off) without loading the filter coeffs. It is however unclear whether
338 * this applies to the disabling of the overlay or to the switching off
339 * of the hw. Do it in both cases */
340 flip_addr |= OFC_UPDATE;
341
6d90c952 342 ret = intel_ring_begin(ring, 6);
acb868d3 343 if (ret)
e1f99ce6 344 return ret;
acb868d3 345
02e792fb 346 /* wait for overlay to go idle */
6d90c952
DV
347 intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
348 intel_ring_emit(ring, flip_addr);
349 intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
02e792fb 350 /* turn overlay off */
a9193983
DV
351 if (IS_I830(dev)) {
352 /* Workaround: Don't disable the overlay fully, since otherwise
353 * it dies on the next OVERLAY_ON cmd. */
354 intel_ring_emit(ring, MI_NOOP);
355 intel_ring_emit(ring, MI_NOOP);
356 intel_ring_emit(ring, MI_NOOP);
357 } else {
358 intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
359 intel_ring_emit(ring, flip_addr);
360 intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
361 }
6d90c952 362 intel_ring_advance(ring);
02e792fb 363
acb868d3 364 return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
12ca45fe
DV
365}
366
03f77ea5
DV
367/* recover from an interruption due to a signal
368 * We have to be careful not to repeat work forever an make forward progess. */
ce453d81 369static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
03f77ea5 370{
03f77ea5 371 int ret;
03f77ea5 372
9bfc01a2 373 if (overlay->last_flip_req == NULL)
b303cf95 374 return 0;
03f77ea5 375
a4b3a571 376 ret = i915_wait_request(overlay->last_flip_req);
b6c028e0 377 if (ret)
03f77ea5 378 return ret;
a4b3a571 379 i915_gem_retire_requests(overlay->dev);
03f77ea5 380
b303cf95
CW
381 if (overlay->flip_tail)
382 overlay->flip_tail(overlay);
03f77ea5 383
9bfc01a2 384 i915_gem_request_assign(&overlay->last_flip_req, NULL);
03f77ea5
DV
385 return 0;
386}
387
5a5a0c64
DV
388/* Wait for pending overlay flip and release old frame.
389 * Needs to be called before the overlay register are changed
8d74f656
CW
390 * via intel_overlay_(un)map_regs
391 */
02e792fb
DV
392static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
393{
5cd68c98 394 struct drm_device *dev = overlay->dev;
d5d45cc5 395 struct drm_i915_private *dev_priv = dev->dev_private;
a4872ba6 396 struct intel_engine_cs *ring = &dev_priv->ring[RCS];
02e792fb 397 int ret;
02e792fb 398
1362b776
VS
399 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
400
5cd68c98
CW
401 /* Only wait if there is actually an old frame to release to
402 * guarantee forward progress.
403 */
03f77ea5
DV
404 if (!overlay->old_vid_bo)
405 return 0;
406
5cd68c98
CW
407 if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
408 /* synchronous slowpath */
6d90c952 409 ret = intel_ring_begin(ring, 2);
acb868d3 410 if (ret)
e1f99ce6 411 return ret;
e1f99ce6 412
6d90c952
DV
413 intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
414 intel_ring_emit(ring, MI_NOOP);
415 intel_ring_advance(ring);
5cd68c98 416
acb868d3 417 ret = intel_overlay_do_wait_request(overlay,
b303cf95 418 intel_overlay_release_old_vid_tail);
5cd68c98
CW
419 if (ret)
420 return ret;
421 }
02e792fb 422
5cd68c98 423 intel_overlay_release_old_vid_tail(overlay);
a071fa00
DV
424
425
426 i915_gem_track_fb(overlay->old_vid_bo, NULL,
427 INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
02e792fb
DV
428 return 0;
429}
430
1362b776
VS
431void intel_overlay_reset(struct drm_i915_private *dev_priv)
432{
433 struct intel_overlay *overlay = dev_priv->overlay;
434
435 if (!overlay)
436 return;
437
438 intel_overlay_release_old_vid(overlay);
439
440 overlay->last_flip_req = NULL;
441 overlay->old_xscale = 0;
442 overlay->old_yscale = 0;
443 overlay->crtc = NULL;
444 overlay->active = false;
445}
446
02e792fb
DV
447struct put_image_params {
448 int format;
449 short dst_x;
450 short dst_y;
451 short dst_w;
452 short dst_h;
453 short src_w;
454 short src_scan_h;
455 short src_scan_w;
456 short src_h;
457 short stride_Y;
458 short stride_UV;
459 int offset_Y;
460 int offset_U;
461 int offset_V;
462};
463
464static int packed_depth_bytes(u32 format)
465{
466 switch (format & I915_OVERLAY_DEPTH_MASK) {
722506f0
CW
467 case I915_OVERLAY_YUV422:
468 return 4;
469 case I915_OVERLAY_YUV411:
470 /* return 6; not implemented */
471 default:
472 return -EINVAL;
02e792fb
DV
473 }
474}
475
476static int packed_width_bytes(u32 format, short width)
477{
478 switch (format & I915_OVERLAY_DEPTH_MASK) {
722506f0
CW
479 case I915_OVERLAY_YUV422:
480 return width << 1;
481 default:
482 return -EINVAL;
02e792fb
DV
483 }
484}
485
486static int uv_hsubsampling(u32 format)
487{
488 switch (format & I915_OVERLAY_DEPTH_MASK) {
722506f0
CW
489 case I915_OVERLAY_YUV422:
490 case I915_OVERLAY_YUV420:
491 return 2;
492 case I915_OVERLAY_YUV411:
493 case I915_OVERLAY_YUV410:
494 return 4;
495 default:
496 return -EINVAL;
02e792fb
DV
497 }
498}
499
500static int uv_vsubsampling(u32 format)
501{
502 switch (format & I915_OVERLAY_DEPTH_MASK) {
722506f0
CW
503 case I915_OVERLAY_YUV420:
504 case I915_OVERLAY_YUV410:
505 return 2;
506 case I915_OVERLAY_YUV422:
507 case I915_OVERLAY_YUV411:
508 return 1;
509 default:
510 return -EINVAL;
02e792fb
DV
511 }
512}
513
514static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
515{
516 u32 mask, shift, ret;
a6c45cf0 517 if (IS_GEN2(dev)) {
02e792fb
DV
518 mask = 0x1f;
519 shift = 5;
a6c45cf0
CW
520 } else {
521 mask = 0x3f;
522 shift = 6;
02e792fb
DV
523 }
524 ret = ((offset + width + mask) >> shift) - (offset >> shift);
a6c45cf0 525 if (!IS_GEN2(dev))
02e792fb 526 ret <<= 1;
0206e353 527 ret -= 1;
02e792fb
DV
528 return ret << 2;
529}
530
531static const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
532 0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
533 0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
534 0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
535 0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
536 0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
537 0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
538 0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
539 0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
540 0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
541 0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
542 0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
543 0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
544 0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
545 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
546 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
547 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
722506f0
CW
548 0xb000, 0x3000, 0x0800, 0x3000, 0xb000
549};
550
02e792fb
DV
551static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
552 0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
553 0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
554 0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
555 0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
556 0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
557 0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
558 0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
559 0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
722506f0
CW
560 0x3000, 0x0800, 0x3000
561};
02e792fb 562
75020bc1 563static void update_polyphase_filter(struct overlay_registers __iomem *regs)
02e792fb 564{
75020bc1
BW
565 memcpy_toio(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
566 memcpy_toio(regs->UV_HCOEFS, uv_static_hcoeffs,
567 sizeof(uv_static_hcoeffs));
02e792fb
DV
568}
569
570static bool update_scaling_factors(struct intel_overlay *overlay,
75020bc1 571 struct overlay_registers __iomem *regs,
02e792fb
DV
572 struct put_image_params *params)
573{
574 /* fixed point with a 12 bit shift */
575 u32 xscale, yscale, xscale_UV, yscale_UV;
576#define FP_SHIFT 12
577#define FRACT_MASK 0xfff
578 bool scale_changed = false;
579 int uv_hscale = uv_hsubsampling(params->format);
580 int uv_vscale = uv_vsubsampling(params->format);
581
582 if (params->dst_w > 1)
583 xscale = ((params->src_scan_w - 1) << FP_SHIFT)
584 /(params->dst_w);
585 else
586 xscale = 1 << FP_SHIFT;
587
588 if (params->dst_h > 1)
589 yscale = ((params->src_scan_h - 1) << FP_SHIFT)
590 /(params->dst_h);
591 else
592 yscale = 1 << FP_SHIFT;
593
594 /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
722506f0
CW
595 xscale_UV = xscale/uv_hscale;
596 yscale_UV = yscale/uv_vscale;
597 /* make the Y scale to UV scale ratio an exact multiply */
598 xscale = xscale_UV * uv_hscale;
599 yscale = yscale_UV * uv_vscale;
02e792fb 600 /*} else {
722506f0
CW
601 xscale_UV = 0;
602 yscale_UV = 0;
603 }*/
02e792fb
DV
604
605 if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
606 scale_changed = true;
607 overlay->old_xscale = xscale;
608 overlay->old_yscale = yscale;
609
75020bc1
BW
610 iowrite32(((yscale & FRACT_MASK) << 20) |
611 ((xscale >> FP_SHIFT) << 16) |
612 ((xscale & FRACT_MASK) << 3),
613 &regs->YRGBSCALE);
722506f0 614
75020bc1
BW
615 iowrite32(((yscale_UV & FRACT_MASK) << 20) |
616 ((xscale_UV >> FP_SHIFT) << 16) |
617 ((xscale_UV & FRACT_MASK) << 3),
618 &regs->UVSCALE);
722506f0 619
75020bc1
BW
620 iowrite32((((yscale >> FP_SHIFT) << 16) |
621 ((yscale_UV >> FP_SHIFT) << 0)),
622 &regs->UVSCALEV);
02e792fb
DV
623
624 if (scale_changed)
625 update_polyphase_filter(regs);
626
627 return scale_changed;
628}
629
630static void update_colorkey(struct intel_overlay *overlay,
75020bc1 631 struct overlay_registers __iomem *regs)
02e792fb
DV
632{
633 u32 key = overlay->color_key;
ea9da4e4
CW
634 u32 flags;
635
636 flags = 0;
637 if (overlay->color_key_enabled)
638 flags |= DST_KEY_ENABLE;
6ba3ddd9 639
f4510a27 640 switch (overlay->crtc->base.primary->fb->bits_per_pixel) {
722506f0 641 case 8:
ea9da4e4
CW
642 key = 0;
643 flags |= CLK_RGB8I_MASK;
6ba3ddd9
CW
644 break;
645
722506f0 646 case 16:
f4510a27 647 if (overlay->crtc->base.primary->fb->depth == 15) {
ea9da4e4
CW
648 key = RGB15_TO_COLORKEY(key);
649 flags |= CLK_RGB15_MASK;
722506f0 650 } else {
ea9da4e4
CW
651 key = RGB16_TO_COLORKEY(key);
652 flags |= CLK_RGB16_MASK;
722506f0 653 }
6ba3ddd9
CW
654 break;
655
722506f0
CW
656 case 24:
657 case 32:
ea9da4e4 658 flags |= CLK_RGB24_MASK;
6ba3ddd9 659 break;
02e792fb 660 }
ea9da4e4
CW
661
662 iowrite32(key, &regs->DCLRKV);
663 iowrite32(flags, &regs->DCLRKM);
02e792fb
DV
664}
665
666static u32 overlay_cmd_reg(struct put_image_params *params)
667{
668 u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
669
670 if (params->format & I915_OVERLAY_YUV_PLANAR) {
671 switch (params->format & I915_OVERLAY_DEPTH_MASK) {
722506f0
CW
672 case I915_OVERLAY_YUV422:
673 cmd |= OCMD_YUV_422_PLANAR;
674 break;
675 case I915_OVERLAY_YUV420:
676 cmd |= OCMD_YUV_420_PLANAR;
677 break;
678 case I915_OVERLAY_YUV411:
679 case I915_OVERLAY_YUV410:
680 cmd |= OCMD_YUV_410_PLANAR;
681 break;
02e792fb
DV
682 }
683 } else { /* YUV packed */
684 switch (params->format & I915_OVERLAY_DEPTH_MASK) {
722506f0
CW
685 case I915_OVERLAY_YUV422:
686 cmd |= OCMD_YUV_422_PACKED;
687 break;
688 case I915_OVERLAY_YUV411:
689 cmd |= OCMD_YUV_411_PACKED;
690 break;
02e792fb
DV
691 }
692
693 switch (params->format & I915_OVERLAY_SWAP_MASK) {
722506f0
CW
694 case I915_OVERLAY_NO_SWAP:
695 break;
696 case I915_OVERLAY_UV_SWAP:
697 cmd |= OCMD_UV_SWAP;
698 break;
699 case I915_OVERLAY_Y_SWAP:
700 cmd |= OCMD_Y_SWAP;
701 break;
702 case I915_OVERLAY_Y_AND_UV_SWAP:
703 cmd |= OCMD_Y_AND_UV_SWAP;
704 break;
02e792fb
DV
705 }
706 }
707
708 return cmd;
709}
710
5fe82c5e 711static int intel_overlay_do_put_image(struct intel_overlay *overlay,
05394f39 712 struct drm_i915_gem_object *new_bo,
5fe82c5e 713 struct put_image_params *params)
02e792fb
DV
714{
715 int ret, tmp_width;
75020bc1 716 struct overlay_registers __iomem *regs;
02e792fb 717 bool scale_changed = false;
02e792fb 718 struct drm_device *dev = overlay->dev;
75020bc1 719 u32 swidth, swidthsw, sheight, ostride;
a071fa00 720 enum pipe pipe = overlay->crtc->pipe;
02e792fb 721
77589f56
VS
722 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
723 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
02e792fb 724
02e792fb
DV
725 ret = intel_overlay_release_old_vid(overlay);
726 if (ret != 0)
727 return ret;
728
e6617330
TU
729 ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL,
730 &i915_ggtt_view_normal);
02e792fb
DV
731 if (ret != 0)
732 return ret;
733
d9e86c0e
CW
734 ret = i915_gem_object_put_fence(new_bo);
735 if (ret)
736 goto out_unpin;
737
02e792fb 738 if (!overlay->active) {
75020bc1 739 u32 oconfig;
8d74f656 740 regs = intel_overlay_map_regs(overlay);
02e792fb
DV
741 if (!regs) {
742 ret = -ENOMEM;
743 goto out_unpin;
744 }
75020bc1 745 oconfig = OCONF_CC_OUT_8BIT;
a6c45cf0 746 if (IS_GEN4(overlay->dev))
75020bc1 747 oconfig |= OCONF_CSC_MODE_BT709;
a071fa00 748 oconfig |= pipe == 0 ?
02e792fb 749 OCONF_PIPE_A : OCONF_PIPE_B;
75020bc1 750 iowrite32(oconfig, &regs->OCONFIG);
9bb2ff73 751 intel_overlay_unmap_regs(overlay, regs);
02e792fb
DV
752
753 ret = intel_overlay_on(overlay);
754 if (ret != 0)
755 goto out_unpin;
756 }
757
8d74f656 758 regs = intel_overlay_map_regs(overlay);
02e792fb
DV
759 if (!regs) {
760 ret = -ENOMEM;
761 goto out_unpin;
762 }
763
75020bc1
BW
764 iowrite32((params->dst_y << 16) | params->dst_x, &regs->DWINPOS);
765 iowrite32((params->dst_h << 16) | params->dst_w, &regs->DWINSZ);
02e792fb
DV
766
767 if (params->format & I915_OVERLAY_YUV_PACKED)
768 tmp_width = packed_width_bytes(params->format, params->src_w);
769 else
770 tmp_width = params->src_w;
771
75020bc1
BW
772 swidth = params->src_w;
773 swidthsw = calc_swidthsw(overlay->dev, params->offset_Y, tmp_width);
774 sheight = params->src_h;
f343c5f6 775 iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_Y, &regs->OBUF_0Y);
75020bc1 776 ostride = params->stride_Y;
02e792fb
DV
777
778 if (params->format & I915_OVERLAY_YUV_PLANAR) {
779 int uv_hscale = uv_hsubsampling(params->format);
780 int uv_vscale = uv_vsubsampling(params->format);
781 u32 tmp_U, tmp_V;
75020bc1 782 swidth |= (params->src_w/uv_hscale) << 16;
02e792fb 783 tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
722506f0 784 params->src_w/uv_hscale);
02e792fb 785 tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
722506f0 786 params->src_w/uv_hscale);
75020bc1
BW
787 swidthsw |= max_t(u32, tmp_U, tmp_V) << 16;
788 sheight |= (params->src_h/uv_vscale) << 16;
f343c5f6
BW
789 iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_U, &regs->OBUF_0U);
790 iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_V, &regs->OBUF_0V);
75020bc1 791 ostride |= params->stride_UV << 16;
02e792fb
DV
792 }
793
75020bc1
BW
794 iowrite32(swidth, &regs->SWIDTH);
795 iowrite32(swidthsw, &regs->SWIDTHSW);
796 iowrite32(sheight, &regs->SHEIGHT);
797 iowrite32(ostride, &regs->OSTRIDE);
798
02e792fb
DV
799 scale_changed = update_scaling_factors(overlay, regs, params);
800
801 update_colorkey(overlay, regs);
802
75020bc1 803 iowrite32(overlay_cmd_reg(params), &regs->OCMD);
02e792fb 804
9bb2ff73 805 intel_overlay_unmap_regs(overlay, regs);
02e792fb 806
8dc5d147
CW
807 ret = intel_overlay_continue(overlay, scale_changed);
808 if (ret)
809 goto out_unpin;
02e792fb 810
a071fa00
DV
811 i915_gem_track_fb(overlay->vid_bo, new_bo,
812 INTEL_FRONTBUFFER_OVERLAY(pipe));
813
02e792fb 814 overlay->old_vid_bo = overlay->vid_bo;
05394f39 815 overlay->vid_bo = new_bo;
02e792fb 816
f99d7069
DV
817 intel_frontbuffer_flip(dev,
818 INTEL_FRONTBUFFER_OVERLAY(pipe));
819
02e792fb
DV
820 return 0;
821
822out_unpin:
d7f46fc4 823 i915_gem_object_ggtt_unpin(new_bo);
02e792fb
DV
824 return ret;
825}
826
ce453d81 827int intel_overlay_switch_off(struct intel_overlay *overlay)
02e792fb 828{
75020bc1 829 struct overlay_registers __iomem *regs;
02e792fb 830 struct drm_device *dev = overlay->dev;
5dcdbcb0 831 int ret;
02e792fb 832
77589f56
VS
833 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
834 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
02e792fb 835
ce453d81 836 ret = intel_overlay_recover_from_interrupt(overlay);
b303cf95
CW
837 if (ret != 0)
838 return ret;
9bedb974 839
02e792fb
DV
840 if (!overlay->active)
841 return 0;
842
02e792fb
DV
843 ret = intel_overlay_release_old_vid(overlay);
844 if (ret != 0)
845 return ret;
846
8d74f656 847 regs = intel_overlay_map_regs(overlay);
75020bc1 848 iowrite32(0, &regs->OCMD);
9bb2ff73 849 intel_overlay_unmap_regs(overlay, regs);
02e792fb 850
ce453d81 851 ret = intel_overlay_off(overlay);
03f77ea5
DV
852 if (ret != 0)
853 return ret;
854
12ca45fe 855 intel_overlay_off_tail(overlay);
02e792fb
DV
856 return 0;
857}
858
859static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
860 struct intel_crtc *crtc)
861{
f7abfe8b 862 if (!crtc->active)
02e792fb
DV
863 return -EINVAL;
864
02e792fb 865 /* can't use the overlay with double wide pipe */
6e3c9717 866 if (crtc->config->double_wide)
02e792fb
DV
867 return -EINVAL;
868
869 return 0;
870}
871
872static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
873{
874 struct drm_device *dev = overlay->dev;
d5d45cc5 875 struct drm_i915_private *dev_priv = dev->dev_private;
02e792fb 876 u32 pfit_control = I915_READ(PFIT_CONTROL);
446d2183 877 u32 ratio;
02e792fb
DV
878
879 /* XXX: This is not the same logic as in the xorg driver, but more in
446d2183
CW
880 * line with the intel documentation for the i965
881 */
a6c45cf0 882 if (INTEL_INFO(dev)->gen >= 4) {
0206e353 883 /* on i965 use the PGM reg to read out the autoscaler values */
a6c45cf0
CW
884 ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
885 } else {
446d2183
CW
886 if (pfit_control & VERT_AUTO_SCALE)
887 ratio = I915_READ(PFIT_AUTO_RATIOS);
02e792fb 888 else
446d2183
CW
889 ratio = I915_READ(PFIT_PGM_RATIOS);
890 ratio >>= PFIT_VERT_SCALE_SHIFT;
02e792fb
DV
891 }
892
893 overlay->pfit_vscale_ratio = ratio;
894}
895
896static int check_overlay_dst(struct intel_overlay *overlay,
897 struct drm_intel_overlay_put_image *rec)
898{
899 struct drm_display_mode *mode = &overlay->crtc->base.mode;
900
75c13993
DV
901 if (rec->dst_x < mode->hdisplay &&
902 rec->dst_x + rec->dst_width <= mode->hdisplay &&
903 rec->dst_y < mode->vdisplay &&
904 rec->dst_y + rec->dst_height <= mode->vdisplay)
02e792fb
DV
905 return 0;
906 else
907 return -EINVAL;
908}
909
910static int check_overlay_scaling(struct put_image_params *rec)
911{
912 u32 tmp;
913
914 /* downscaling limit is 8.0 */
915 tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
916 if (tmp > 7)
917 return -EINVAL;
918 tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
919 if (tmp > 7)
920 return -EINVAL;
921
922 return 0;
923}
924
925static int check_overlay_src(struct drm_device *dev,
926 struct drm_intel_overlay_put_image *rec,
05394f39 927 struct drm_i915_gem_object *new_bo)
02e792fb 928{
02e792fb
DV
929 int uv_hscale = uv_hsubsampling(rec->flags);
930 int uv_vscale = uv_vsubsampling(rec->flags);
8f28f54a
DC
931 u32 stride_mask;
932 int depth;
933 u32 tmp;
02e792fb
DV
934
935 /* check src dimensions */
936 if (IS_845G(dev) || IS_I830(dev)) {
722506f0 937 if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
9f7c3f44 938 rec->src_width > IMAGE_MAX_WIDTH_LEGACY)
02e792fb
DV
939 return -EINVAL;
940 } else {
722506f0 941 if (rec->src_height > IMAGE_MAX_HEIGHT ||
9f7c3f44 942 rec->src_width > IMAGE_MAX_WIDTH)
02e792fb
DV
943 return -EINVAL;
944 }
9f7c3f44 945
02e792fb 946 /* better safe than sorry, use 4 as the maximal subsampling ratio */
722506f0 947 if (rec->src_height < N_VERT_Y_TAPS*4 ||
9f7c3f44 948 rec->src_width < N_HORIZ_Y_TAPS*4)
02e792fb
DV
949 return -EINVAL;
950
a1efd14a 951 /* check alignment constraints */
02e792fb 952 switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
722506f0
CW
953 case I915_OVERLAY_RGB:
954 /* not implemented */
955 return -EINVAL;
9f7c3f44 956
722506f0 957 case I915_OVERLAY_YUV_PACKED:
722506f0 958 if (uv_vscale != 1)
02e792fb 959 return -EINVAL;
9f7c3f44
CW
960
961 depth = packed_depth_bytes(rec->flags);
722506f0
CW
962 if (depth < 0)
963 return depth;
9f7c3f44 964
722506f0
CW
965 /* ignore UV planes */
966 rec->stride_UV = 0;
967 rec->offset_U = 0;
968 rec->offset_V = 0;
969 /* check pixel alignment */
970 if (rec->offset_Y % depth)
971 return -EINVAL;
972 break;
9f7c3f44 973
722506f0
CW
974 case I915_OVERLAY_YUV_PLANAR:
975 if (uv_vscale < 0 || uv_hscale < 0)
02e792fb 976 return -EINVAL;
722506f0
CW
977 /* no offset restrictions for planar formats */
978 break;
9f7c3f44 979
722506f0
CW
980 default:
981 return -EINVAL;
02e792fb
DV
982 }
983
984 if (rec->src_width % uv_hscale)
985 return -EINVAL;
986
987 /* stride checking */
a1efd14a
CW
988 if (IS_I830(dev) || IS_845G(dev))
989 stride_mask = 255;
990 else
991 stride_mask = 63;
02e792fb
DV
992
993 if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
994 return -EINVAL;
a6c45cf0 995 if (IS_GEN4(dev) && rec->stride_Y < 512)
02e792fb
DV
996 return -EINVAL;
997
998 tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
9f7c3f44
CW
999 4096 : 8192;
1000 if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
02e792fb
DV
1001 return -EINVAL;
1002
1003 /* check buffer dimensions */
1004 switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
722506f0
CW
1005 case I915_OVERLAY_RGB:
1006 case I915_OVERLAY_YUV_PACKED:
1007 /* always 4 Y values per depth pixels */
1008 if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
1009 return -EINVAL;
1010
1011 tmp = rec->stride_Y*rec->src_height;
05394f39 1012 if (rec->offset_Y + tmp > new_bo->base.size)
722506f0
CW
1013 return -EINVAL;
1014 break;
1015
1016 case I915_OVERLAY_YUV_PLANAR:
1017 if (rec->src_width > rec->stride_Y)
1018 return -EINVAL;
1019 if (rec->src_width/uv_hscale > rec->stride_UV)
1020 return -EINVAL;
1021
9f7c3f44 1022 tmp = rec->stride_Y * rec->src_height;
05394f39 1023 if (rec->offset_Y + tmp > new_bo->base.size)
722506f0 1024 return -EINVAL;
9f7c3f44
CW
1025
1026 tmp = rec->stride_UV * (rec->src_height / uv_vscale);
05394f39
CW
1027 if (rec->offset_U + tmp > new_bo->base.size ||
1028 rec->offset_V + tmp > new_bo->base.size)
722506f0
CW
1029 return -EINVAL;
1030 break;
02e792fb
DV
1031 }
1032
1033 return 0;
1034}
1035
e9e331a8
CW
1036/**
1037 * Return the pipe currently connected to the panel fitter,
1038 * or -1 if the panel fitter is not present or not in use
1039 */
1040static int intel_panel_fitter_pipe(struct drm_device *dev)
1041{
1042 struct drm_i915_private *dev_priv = dev->dev_private;
1043 u32 pfit_control;
1044
1045 /* i830 doesn't have a panel fitter */
dc9e7dec 1046 if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev)))
e9e331a8
CW
1047 return -1;
1048
1049 pfit_control = I915_READ(PFIT_CONTROL);
1050
1051 /* See if the panel fitter is in use */
1052 if ((pfit_control & PFIT_ENABLE) == 0)
1053 return -1;
1054
1055 /* 965 can place panel fitter on either pipe */
a6c45cf0 1056 if (IS_GEN4(dev))
e9e331a8
CW
1057 return (pfit_control >> 29) & 0x3;
1058
1059 /* older chips can only use pipe 1 */
1060 return 1;
1061}
1062
02e792fb 1063int intel_overlay_put_image(struct drm_device *dev, void *data,
0206e353 1064 struct drm_file *file_priv)
02e792fb
DV
1065{
1066 struct drm_intel_overlay_put_image *put_image_rec = data;
d5d45cc5 1067 struct drm_i915_private *dev_priv = dev->dev_private;
02e792fb 1068 struct intel_overlay *overlay;
7707e653 1069 struct drm_crtc *drmmode_crtc;
02e792fb 1070 struct intel_crtc *crtc;
05394f39 1071 struct drm_i915_gem_object *new_bo;
02e792fb
DV
1072 struct put_image_params *params;
1073 int ret;
1074
02e792fb
DV
1075 overlay = dev_priv->overlay;
1076 if (!overlay) {
1077 DRM_DEBUG("userspace bug: no overlay\n");
1078 return -ENODEV;
1079 }
1080
1081 if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
a0e99e68 1082 drm_modeset_lock_all(dev);
02e792fb
DV
1083 mutex_lock(&dev->struct_mutex);
1084
ce453d81 1085 ret = intel_overlay_switch_off(overlay);
02e792fb
DV
1086
1087 mutex_unlock(&dev->struct_mutex);
a0e99e68 1088 drm_modeset_unlock_all(dev);
02e792fb
DV
1089
1090 return ret;
1091 }
1092
b14c5679 1093 params = kmalloc(sizeof(*params), GFP_KERNEL);
02e792fb
DV
1094 if (!params)
1095 return -ENOMEM;
1096
7707e653
RC
1097 drmmode_crtc = drm_crtc_find(dev, put_image_rec->crtc_id);
1098 if (!drmmode_crtc) {
915a428e
DC
1099 ret = -ENOENT;
1100 goto out_free;
1101 }
7707e653 1102 crtc = to_intel_crtc(drmmode_crtc);
02e792fb 1103
05394f39
CW
1104 new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
1105 put_image_rec->bo_handle));
c8725226 1106 if (&new_bo->base == NULL) {
915a428e
DC
1107 ret = -ENOENT;
1108 goto out_free;
1109 }
02e792fb 1110
a0e99e68 1111 drm_modeset_lock_all(dev);
02e792fb
DV
1112 mutex_lock(&dev->struct_mutex);
1113
d9e86c0e 1114 if (new_bo->tiling_mode) {
3b25b31f 1115 DRM_DEBUG_KMS("buffer used for overlay image can not be tiled\n");
d9e86c0e
CW
1116 ret = -EINVAL;
1117 goto out_unlock;
1118 }
1119
ce453d81 1120 ret = intel_overlay_recover_from_interrupt(overlay);
b303cf95
CW
1121 if (ret != 0)
1122 goto out_unlock;
03f77ea5 1123
02e792fb
DV
1124 if (overlay->crtc != crtc) {
1125 struct drm_display_mode *mode = &crtc->base.mode;
ce453d81 1126 ret = intel_overlay_switch_off(overlay);
02e792fb
DV
1127 if (ret != 0)
1128 goto out_unlock;
1129
1130 ret = check_overlay_possible_on_crtc(overlay, crtc);
1131 if (ret != 0)
1132 goto out_unlock;
1133
1134 overlay->crtc = crtc;
1135 crtc->overlay = overlay;
1136
e9e331a8
CW
1137 /* line too wide, i.e. one-line-mode */
1138 if (mode->hdisplay > 1024 &&
1139 intel_panel_fitter_pipe(dev) == crtc->pipe) {
209c2a5e 1140 overlay->pfit_active = true;
02e792fb
DV
1141 update_pfit_vscale_ratio(overlay);
1142 } else
209c2a5e 1143 overlay->pfit_active = false;
02e792fb
DV
1144 }
1145
1146 ret = check_overlay_dst(overlay, put_image_rec);
1147 if (ret != 0)
1148 goto out_unlock;
1149
1150 if (overlay->pfit_active) {
1151 params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
722506f0 1152 overlay->pfit_vscale_ratio);
02e792fb
DV
1153 /* shifting right rounds downwards, so add 1 */
1154 params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
722506f0 1155 overlay->pfit_vscale_ratio) + 1;
02e792fb
DV
1156 } else {
1157 params->dst_y = put_image_rec->dst_y;
1158 params->dst_h = put_image_rec->dst_height;
1159 }
1160 params->dst_x = put_image_rec->dst_x;
1161 params->dst_w = put_image_rec->dst_width;
1162
1163 params->src_w = put_image_rec->src_width;
1164 params->src_h = put_image_rec->src_height;
1165 params->src_scan_w = put_image_rec->src_scan_width;
1166 params->src_scan_h = put_image_rec->src_scan_height;
722506f0
CW
1167 if (params->src_scan_h > params->src_h ||
1168 params->src_scan_w > params->src_w) {
02e792fb
DV
1169 ret = -EINVAL;
1170 goto out_unlock;
1171 }
1172
1173 ret = check_overlay_src(dev, put_image_rec, new_bo);
1174 if (ret != 0)
1175 goto out_unlock;
1176 params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
1177 params->stride_Y = put_image_rec->stride_Y;
1178 params->stride_UV = put_image_rec->stride_UV;
1179 params->offset_Y = put_image_rec->offset_Y;
1180 params->offset_U = put_image_rec->offset_U;
1181 params->offset_V = put_image_rec->offset_V;
1182
1183 /* Check scaling after src size to prevent a divide-by-zero. */
1184 ret = check_overlay_scaling(params);
1185 if (ret != 0)
1186 goto out_unlock;
1187
1188 ret = intel_overlay_do_put_image(overlay, new_bo, params);
1189 if (ret != 0)
1190 goto out_unlock;
1191
1192 mutex_unlock(&dev->struct_mutex);
a0e99e68 1193 drm_modeset_unlock_all(dev);
02e792fb
DV
1194
1195 kfree(params);
1196
1197 return 0;
1198
1199out_unlock:
1200 mutex_unlock(&dev->struct_mutex);
a0e99e68 1201 drm_modeset_unlock_all(dev);
05394f39 1202 drm_gem_object_unreference_unlocked(&new_bo->base);
915a428e 1203out_free:
02e792fb
DV
1204 kfree(params);
1205
1206 return ret;
1207}
1208
1209static void update_reg_attrs(struct intel_overlay *overlay,
75020bc1 1210 struct overlay_registers __iomem *regs)
02e792fb 1211{
75020bc1
BW
1212 iowrite32((overlay->contrast << 18) | (overlay->brightness & 0xff),
1213 &regs->OCLRC0);
1214 iowrite32(overlay->saturation, &regs->OCLRC1);
02e792fb
DV
1215}
1216
1217static bool check_gamma_bounds(u32 gamma1, u32 gamma2)
1218{
1219 int i;
1220
1221 if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
1222 return false;
1223
1224 for (i = 0; i < 3; i++) {
722506f0 1225 if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
02e792fb
DV
1226 return false;
1227 }
1228
1229 return true;
1230}
1231
1232static bool check_gamma5_errata(u32 gamma5)
1233{
1234 int i;
1235
1236 for (i = 0; i < 3; i++) {
1237 if (((gamma5 >> i*8) & 0xff) == 0x80)
1238 return false;
1239 }
1240
1241 return true;
1242}
1243
1244static int check_gamma(struct drm_intel_overlay_attrs *attrs)
1245{
722506f0
CW
1246 if (!check_gamma_bounds(0, attrs->gamma0) ||
1247 !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1248 !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1249 !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1250 !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1251 !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1252 !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
02e792fb 1253 return -EINVAL;
722506f0 1254
02e792fb
DV
1255 if (!check_gamma5_errata(attrs->gamma5))
1256 return -EINVAL;
722506f0 1257
02e792fb
DV
1258 return 0;
1259}
1260
1261int intel_overlay_attrs(struct drm_device *dev, void *data,
0206e353 1262 struct drm_file *file_priv)
02e792fb
DV
1263{
1264 struct drm_intel_overlay_attrs *attrs = data;
d5d45cc5 1265 struct drm_i915_private *dev_priv = dev->dev_private;
02e792fb 1266 struct intel_overlay *overlay;
75020bc1 1267 struct overlay_registers __iomem *regs;
02e792fb
DV
1268 int ret;
1269
02e792fb
DV
1270 overlay = dev_priv->overlay;
1271 if (!overlay) {
1272 DRM_DEBUG("userspace bug: no overlay\n");
1273 return -ENODEV;
1274 }
1275
a0e99e68 1276 drm_modeset_lock_all(dev);
02e792fb
DV
1277 mutex_lock(&dev->struct_mutex);
1278
60fc332c 1279 ret = -EINVAL;
02e792fb 1280 if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
60fc332c 1281 attrs->color_key = overlay->color_key;
02e792fb 1282 attrs->brightness = overlay->brightness;
60fc332c 1283 attrs->contrast = overlay->contrast;
02e792fb
DV
1284 attrs->saturation = overlay->saturation;
1285
a6c45cf0 1286 if (!IS_GEN2(dev)) {
02e792fb
DV
1287 attrs->gamma0 = I915_READ(OGAMC0);
1288 attrs->gamma1 = I915_READ(OGAMC1);
1289 attrs->gamma2 = I915_READ(OGAMC2);
1290 attrs->gamma3 = I915_READ(OGAMC3);
1291 attrs->gamma4 = I915_READ(OGAMC4);
1292 attrs->gamma5 = I915_READ(OGAMC5);
1293 }
02e792fb 1294 } else {
60fc332c 1295 if (attrs->brightness < -128 || attrs->brightness > 127)
02e792fb 1296 goto out_unlock;
60fc332c 1297 if (attrs->contrast > 255)
02e792fb 1298 goto out_unlock;
60fc332c 1299 if (attrs->saturation > 1023)
02e792fb 1300 goto out_unlock;
02e792fb 1301
60fc332c
CW
1302 overlay->color_key = attrs->color_key;
1303 overlay->brightness = attrs->brightness;
1304 overlay->contrast = attrs->contrast;
1305 overlay->saturation = attrs->saturation;
02e792fb 1306
8d74f656 1307 regs = intel_overlay_map_regs(overlay);
02e792fb
DV
1308 if (!regs) {
1309 ret = -ENOMEM;
1310 goto out_unlock;
1311 }
1312
1313 update_reg_attrs(overlay, regs);
1314
9bb2ff73 1315 intel_overlay_unmap_regs(overlay, regs);
02e792fb
DV
1316
1317 if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
a6c45cf0 1318 if (IS_GEN2(dev))
02e792fb 1319 goto out_unlock;
02e792fb
DV
1320
1321 if (overlay->active) {
1322 ret = -EBUSY;
1323 goto out_unlock;
1324 }
1325
1326 ret = check_gamma(attrs);
60fc332c 1327 if (ret)
02e792fb
DV
1328 goto out_unlock;
1329
1330 I915_WRITE(OGAMC0, attrs->gamma0);
1331 I915_WRITE(OGAMC1, attrs->gamma1);
1332 I915_WRITE(OGAMC2, attrs->gamma2);
1333 I915_WRITE(OGAMC3, attrs->gamma3);
1334 I915_WRITE(OGAMC4, attrs->gamma4);
1335 I915_WRITE(OGAMC5, attrs->gamma5);
1336 }
02e792fb 1337 }
ea9da4e4 1338 overlay->color_key_enabled = (attrs->flags & I915_OVERLAY_DISABLE_DEST_COLORKEY) == 0;
02e792fb 1339
60fc332c 1340 ret = 0;
02e792fb
DV
1341out_unlock:
1342 mutex_unlock(&dev->struct_mutex);
a0e99e68 1343 drm_modeset_unlock_all(dev);
02e792fb
DV
1344
1345 return ret;
1346}
1347
1348void intel_setup_overlay(struct drm_device *dev)
1349{
d5d45cc5 1350 struct drm_i915_private *dev_priv = dev->dev_private;
02e792fb 1351 struct intel_overlay *overlay;
05394f39 1352 struct drm_i915_gem_object *reg_bo;
75020bc1 1353 struct overlay_registers __iomem *regs;
02e792fb
DV
1354 int ret;
1355
31578148 1356 if (!HAS_OVERLAY(dev))
02e792fb
DV
1357 return;
1358
b14c5679 1359 overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
02e792fb
DV
1360 if (!overlay)
1361 return;
79d24273
CW
1362
1363 mutex_lock(&dev->struct_mutex);
1364 if (WARN_ON(dev_priv->overlay))
1365 goto out_free;
1366
02e792fb
DV
1367 overlay->dev = dev;
1368
f63a484c
DV
1369 reg_bo = NULL;
1370 if (!OVERLAY_NEEDS_PHYSICAL(dev))
1371 reg_bo = i915_gem_object_create_stolen(dev, PAGE_SIZE);
80405138
CW
1372 if (reg_bo == NULL)
1373 reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
1374 if (reg_bo == NULL)
02e792fb 1375 goto out_free;
05394f39 1376 overlay->reg_bo = reg_bo;
02e792fb 1377
31578148 1378 if (OVERLAY_NEEDS_PHYSICAL(dev)) {
00731155 1379 ret = i915_gem_object_attach_phys(reg_bo, PAGE_SIZE);
0206e353
AJ
1380 if (ret) {
1381 DRM_ERROR("failed to attach phys overlay regs\n");
1382 goto out_free_bo;
1383 }
00731155 1384 overlay->flip_addr = reg_bo->phys_handle->busaddr;
31578148 1385 } else {
1ec9e26d 1386 ret = i915_gem_obj_ggtt_pin(reg_bo, PAGE_SIZE, PIN_MAPPABLE);
02e792fb 1387 if (ret) {
0206e353
AJ
1388 DRM_ERROR("failed to pin overlay register bo\n");
1389 goto out_free_bo;
1390 }
f343c5f6 1391 overlay->flip_addr = i915_gem_obj_ggtt_offset(reg_bo);
0ddc1289
CW
1392
1393 ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
1394 if (ret) {
0206e353
AJ
1395 DRM_ERROR("failed to move overlay register bo into the GTT\n");
1396 goto out_unpin_bo;
1397 }
02e792fb
DV
1398 }
1399
1400 /* init all values */
1401 overlay->color_key = 0x0101fe;
ea9da4e4 1402 overlay->color_key_enabled = true;
02e792fb
DV
1403 overlay->brightness = -19;
1404 overlay->contrast = 75;
1405 overlay->saturation = 146;
1406
8d74f656 1407 regs = intel_overlay_map_regs(overlay);
02e792fb 1408 if (!regs)
79d24273 1409 goto out_unpin_bo;
02e792fb 1410
75020bc1 1411 memset_io(regs, 0, sizeof(struct overlay_registers));
02e792fb 1412 update_polyphase_filter(regs);
02e792fb
DV
1413 update_reg_attrs(overlay, regs);
1414
9bb2ff73 1415 intel_overlay_unmap_regs(overlay, regs);
02e792fb
DV
1416
1417 dev_priv->overlay = overlay;
79d24273 1418 mutex_unlock(&dev->struct_mutex);
02e792fb
DV
1419 DRM_INFO("initialized overlay support\n");
1420 return;
1421
0ddc1289 1422out_unpin_bo:
79d24273 1423 if (!OVERLAY_NEEDS_PHYSICAL(dev))
d7f46fc4 1424 i915_gem_object_ggtt_unpin(reg_bo);
02e792fb 1425out_free_bo:
05394f39 1426 drm_gem_object_unreference(&reg_bo->base);
02e792fb 1427out_free:
79d24273 1428 mutex_unlock(&dev->struct_mutex);
02e792fb
DV
1429 kfree(overlay);
1430 return;
1431}
1432
1433void intel_cleanup_overlay(struct drm_device *dev)
1434{
d5d45cc5 1435 struct drm_i915_private *dev_priv = dev->dev_private;
02e792fb 1436
62cf4e6f
CW
1437 if (!dev_priv->overlay)
1438 return;
02e792fb 1439
62cf4e6f
CW
1440 /* The bo's should be free'd by the generic code already.
1441 * Furthermore modesetting teardown happens beforehand so the
1442 * hardware should be off already */
77589f56 1443 WARN_ON(dev_priv->overlay->active);
62cf4e6f
CW
1444
1445 drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
1446 kfree(dev_priv->overlay);
02e792fb 1447}
6ef3d427
CW
1448
1449struct intel_overlay_error_state {
1450 struct overlay_registers regs;
1451 unsigned long base;
1452 u32 dovsta;
1453 u32 isr;
1454};
1455
75020bc1 1456static struct overlay_registers __iomem *
c48c43e4 1457intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
3bd3c932 1458{
d5d45cc5 1459 struct drm_i915_private *dev_priv = overlay->dev->dev_private;
75020bc1 1460 struct overlay_registers __iomem *regs;
3bd3c932
CW
1461
1462 if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
75020bc1
BW
1463 /* Cast to make sparse happy, but it's wc memory anyway, so
1464 * equivalent to the wc io mapping on X86. */
1465 regs = (struct overlay_registers __iomem *)
00731155 1466 overlay->reg_bo->phys_handle->vaddr;
3bd3c932 1467 else
5d4545ae 1468 regs = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
f343c5f6 1469 i915_gem_obj_ggtt_offset(overlay->reg_bo));
3bd3c932
CW
1470
1471 return regs;
1472}
1473
1474static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
75020bc1 1475 struct overlay_registers __iomem *regs)
3bd3c932
CW
1476{
1477 if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
c48c43e4 1478 io_mapping_unmap_atomic(regs);
3bd3c932
CW
1479}
1480
1481
6ef3d427
CW
1482struct intel_overlay_error_state *
1483intel_overlay_capture_error_state(struct drm_device *dev)
1484{
d5d45cc5 1485 struct drm_i915_private *dev_priv = dev->dev_private;
6ef3d427
CW
1486 struct intel_overlay *overlay = dev_priv->overlay;
1487 struct intel_overlay_error_state *error;
1488 struct overlay_registers __iomem *regs;
1489
1490 if (!overlay || !overlay->active)
1491 return NULL;
1492
1493 error = kmalloc(sizeof(*error), GFP_ATOMIC);
1494 if (error == NULL)
1495 return NULL;
1496
1497 error->dovsta = I915_READ(DOVSTA);
1498 error->isr = I915_READ(ISR);
31578148 1499 if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
00731155 1500 error->base = (__force long)overlay->reg_bo->phys_handle->vaddr;
31578148 1501 else
f343c5f6 1502 error->base = i915_gem_obj_ggtt_offset(overlay->reg_bo);
6ef3d427
CW
1503
1504 regs = intel_overlay_map_regs_atomic(overlay);
1505 if (!regs)
1506 goto err;
1507
1508 memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
c48c43e4 1509 intel_overlay_unmap_regs_atomic(overlay, regs);
6ef3d427
CW
1510
1511 return error;
1512
1513err:
1514 kfree(error);
1515 return NULL;
1516}
1517
1518void
edc3d884
MK
1519intel_overlay_print_error_state(struct drm_i915_error_state_buf *m,
1520 struct intel_overlay_error_state *error)
6ef3d427 1521{
edc3d884
MK
1522 i915_error_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
1523 error->dovsta, error->isr);
1524 i915_error_printf(m, " Register file at 0x%08lx:\n",
1525 error->base);
6ef3d427 1526
edc3d884 1527#define P(x) i915_error_printf(m, " " #x ": 0x%08x\n", error->regs.x)
6ef3d427
CW
1528 P(OBUF_0Y);
1529 P(OBUF_1Y);
1530 P(OBUF_0U);
1531 P(OBUF_0V);
1532 P(OBUF_1U);
1533 P(OBUF_1V);
1534 P(OSTRIDE);
1535 P(YRGB_VPH);
1536 P(UV_VPH);
1537 P(HORZ_PH);
1538 P(INIT_PHS);
1539 P(DWINPOS);
1540 P(DWINSZ);
1541 P(SWIDTH);
1542 P(SWIDTHSW);
1543 P(SHEIGHT);
1544 P(YRGBSCALE);
1545 P(UVSCALE);
1546 P(OCLRC0);
1547 P(OCLRC1);
1548 P(DCLRKV);
1549 P(DCLRKM);
1550 P(SCLRKVH);
1551 P(SCLRKVL);
1552 P(SCLRKEN);
1553 P(OCONFIG);
1554 P(OCMD);
1555 P(OSTART_0Y);
1556 P(OSTART_1Y);
1557 P(OSTART_0U);
1558 P(OSTART_0V);
1559 P(OSTART_1U);
1560 P(OSTART_1V);
1561 P(OTILEOFF_0Y);
1562 P(OTILEOFF_1Y);
1563 P(OTILEOFF_0U);
1564 P(OTILEOFF_0V);
1565 P(OTILEOFF_1U);
1566 P(OTILEOFF_1V);
1567 P(FASTHSCALE);
1568 P(UVSCALEV);
1569#undef P
1570}