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