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