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