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