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