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