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