1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#include <linux/seq_file.h>
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
38
39
40
41#define IMAGE_MAX_WIDTH 2048
42#define IMAGE_MAX_HEIGHT 2046
43
44#define IMAGE_MAX_WIDTH_LEGACY 1024
45#define IMAGE_MAX_HEIGHT_LEGACY 1088
46
47
48
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)
56#define OCMD_UV_SWAP (0x1<<14)
57#define OCMD_Y_SWAP (0x2<<14)
58#define OCMD_Y_AND_UV_SWAP (0x3<<14)
59#define OCMD_SOURCE_FORMAT_MASK (0xf<<10)
60#define OCMD_RGB_888 (0x1<<10)
61#define OCMD_RGB_555 (0x2<<10)
62#define OCMD_RGB_565 (0x3<<10)
63#define OCMD_YUV_422_PACKED (0x8<<10)
64#define OCMD_YUV_411_PACKED (0x9<<10)
65#define OCMD_YUV_420_PLANAR (0xc<<10)
66#define OCMD_YUV_422_PLANAR (0xd<<10)
67#define OCMD_YUV_410_PLANAR (0xe<<10)
68#define OCMD_TVSYNCFLIP_PARITY (0x1<<9)
69#define OCMD_TVSYNCFLIP_ENABLE (0x1<<7)
70#define OCMD_BUF_TYPE_MASK (0x1<<5)
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
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
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
108#define OFC_UPDATE 0x1
109
110
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
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;
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;
161 u32 UVSCALEV;
162 u32 RESERVEDC[(0x200 - 0xA8) / 4];
163 u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES];
164 u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
165 u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES];
166 u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
167 u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES];
168 u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
169 u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES];
170 u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
171};
172
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;
181 u32 color_key;
182 u32 brightness, contrast, saturation;
183 u32 old_xscale, old_yscale;
184
185 u32 flip_addr;
186 struct drm_i915_gem_object *reg_bo;
187
188 uint32_t last_flip_req;
189 void (*flip_tail)(struct intel_overlay *);
190};
191
192static struct overlay_registers *
193intel_overlay_map_regs(struct intel_overlay *overlay)
194{
195 drm_i915_private_t *dev_priv = overlay->dev->dev_private;
196 struct overlay_registers *regs;
197
198 if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
199 regs = overlay->reg_bo->phys_obj->handle->vaddr;
200 else
201 regs = io_mapping_map_wc(dev_priv->mm.gtt_mapping,
202 overlay->reg_bo->gtt_offset);
203
204 return regs;
205}
206
207static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
208 struct overlay_registers *regs)
209{
210 if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
211 io_mapping_unmap(regs);
212}
213
214static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
215 struct drm_i915_gem_request *request,
216 bool interruptible,
217 void (*tail)(struct intel_overlay *))
218{
219 struct drm_device *dev = overlay->dev;
220 drm_i915_private_t *dev_priv = dev->dev_private;
221 int ret;
222
223 BUG_ON(overlay->last_flip_req);
224 ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv));
225 if (ret) {
226 kfree(request);
227 return ret;
228 }
229 overlay->last_flip_req = request->seqno;
230 overlay->flip_tail = tail;
231 ret = i915_do_wait_request(dev,
232 overlay->last_flip_req, true,
233 LP_RING(dev_priv));
234 if (ret)
235 return ret;
236
237 overlay->last_flip_req = 0;
238 return 0;
239}
240
241
242static int
243i830_activate_pipe_a(struct drm_device *dev)
244{
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;
257
258
259 if (I915_READ(PIPEACONF) & PIPECONF_ENABLE)
260 return 0;
261
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);
287}
288
289
290static int intel_overlay_on(struct intel_overlay *overlay)
291{
292 struct drm_device *dev = overlay->dev;
293 struct drm_i915_private *dev_priv = dev->dev_private;
294 struct drm_i915_gem_request *request;
295 int pipe_a_quirk = 0;
296 int ret;
297
298 BUG_ON(overlay->active);
299 overlay->active = 1;
300
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
307 request = kzalloc(sizeof(*request), GFP_KERNEL);
308 if (request == NULL) {
309 ret = -ENOMEM;
310 goto out;
311 }
312
313 ret = BEGIN_LP_RING(4);
314 if (ret) {
315 kfree(request);
316 goto out;
317 }
318
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
325 ret = intel_overlay_do_wait_request(overlay, request, true, NULL);
326out:
327 if (pipe_a_quirk)
328 i830_deactivate_pipe_a(dev);
329
330 return ret;
331}
332
333
334static int intel_overlay_continue(struct intel_overlay *overlay,
335 bool load_polyphase_filter)
336{
337 struct drm_device *dev = overlay->dev;
338 drm_i915_private_t *dev_priv = dev->dev_private;
339 struct drm_i915_gem_request *request;
340 u32 flip_addr = overlay->flip_addr;
341 u32 tmp;
342 int ret;
343
344 BUG_ON(!overlay->active);
345
346 request = kzalloc(sizeof(*request), GFP_KERNEL);
347 if (request == NULL)
348 return -ENOMEM;
349
350 if (load_polyphase_filter)
351 flip_addr |= OFC_UPDATE;
352
353
354 tmp = I915_READ(DOVSTA);
355 if (tmp & (1 << 17))
356 DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
357
358 ret = BEGIN_LP_RING(2);
359 if (ret) {
360 kfree(request);
361 return ret;
362 }
363 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
364 OUT_RING(flip_addr);
365 ADVANCE_LP_RING();
366
367 ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv));
368 if (ret) {
369 kfree(request);
370 return ret;
371 }
372
373 overlay->last_flip_req = request->seqno;
374 return 0;
375}
376
377static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
378{
379 struct drm_i915_gem_object *obj = overlay->old_vid_bo;
380
381 i915_gem_object_unpin(obj);
382 drm_gem_object_unreference(&obj->base);
383
384 overlay->old_vid_bo = NULL;
385}
386
387static void intel_overlay_off_tail(struct intel_overlay *overlay)
388{
389 struct drm_i915_gem_object *obj = overlay->vid_bo;
390
391
392 BUG_ON(!overlay->vid_bo);
393
394 i915_gem_object_unpin(obj);
395 drm_gem_object_unreference(&obj->base);
396 overlay->vid_bo = NULL;
397
398 overlay->crtc->overlay = NULL;
399 overlay->crtc = NULL;
400 overlay->active = 0;
401}
402
403
404static int intel_overlay_off(struct intel_overlay *overlay,
405 bool interruptible)
406{
407 struct drm_device *dev = overlay->dev;
408 struct drm_i915_private *dev_priv = dev->dev_private;
409 u32 flip_addr = overlay->flip_addr;
410 struct drm_i915_gem_request *request;
411 int ret;
412
413 BUG_ON(!overlay->active);
414
415 request = kzalloc(sizeof(*request), GFP_KERNEL);
416 if (request == NULL)
417 return -ENOMEM;
418
419
420
421
422
423 flip_addr |= OFC_UPDATE;
424
425 ret = BEGIN_LP_RING(6);
426 if (ret) {
427 kfree(request);
428 return ret;
429 }
430
431 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
432 OUT_RING(flip_addr);
433 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
434
435 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
436 OUT_RING(flip_addr);
437 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
438 ADVANCE_LP_RING();
439
440 return intel_overlay_do_wait_request(overlay, request, interruptible,
441 intel_overlay_off_tail);
442}
443
444
445
446static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
447 bool interruptible)
448{
449 struct drm_device *dev = overlay->dev;
450 drm_i915_private_t *dev_priv = dev->dev_private;
451 int ret;
452
453 if (overlay->last_flip_req == 0)
454 return 0;
455
456 ret = i915_do_wait_request(dev, overlay->last_flip_req,
457 interruptible, LP_RING(dev_priv));
458 if (ret)
459 return ret;
460
461 if (overlay->flip_tail)
462 overlay->flip_tail(overlay);
463
464 overlay->last_flip_req = 0;
465 return 0;
466}
467
468
469
470
471
472static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
473{
474 struct drm_device *dev = overlay->dev;
475 drm_i915_private_t *dev_priv = dev->dev_private;
476 int ret;
477
478
479
480
481 if (!overlay->old_vid_bo)
482 return 0;
483
484 if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
485 struct drm_i915_gem_request *request;
486
487
488 request = kzalloc(sizeof(*request), GFP_KERNEL);
489 if (request == NULL)
490 return -ENOMEM;
491
492 ret = BEGIN_LP_RING(2);
493 if (ret) {
494 kfree(request);
495 return ret;
496 }
497
498 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
499 OUT_RING(MI_NOOP);
500 ADVANCE_LP_RING();
501
502 ret = intel_overlay_do_wait_request(overlay, request, true,
503 intel_overlay_release_old_vid_tail);
504 if (ret)
505 return ret;
506 }
507
508 intel_overlay_release_old_vid_tail(overlay);
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) {
532 case I915_OVERLAY_YUV422:
533 return 4;
534 case I915_OVERLAY_YUV411:
535
536 default:
537 return -EINVAL;
538 }
539}
540
541static int packed_width_bytes(u32 format, short width)
542{
543 switch (format & I915_OVERLAY_DEPTH_MASK) {
544 case I915_OVERLAY_YUV422:
545 return width << 1;
546 default:
547 return -EINVAL;
548 }
549}
550
551static int uv_hsubsampling(u32 format)
552{
553 switch (format & I915_OVERLAY_DEPTH_MASK) {
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;
562 }
563}
564
565static int uv_vsubsampling(u32 format)
566{
567 switch (format & I915_OVERLAY_DEPTH_MASK) {
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;
576 }
577}
578
579static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
580{
581 u32 mask, shift, ret;
582 if (IS_GEN2(dev)) {
583 mask = 0x1f;
584 shift = 5;
585 } else {
586 mask = 0x3f;
587 shift = 6;
588 }
589 ret = ((offset + width + mask) >> shift) - (offset >> shift);
590 if (!IS_GEN2(dev))
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,
613 0xb000, 0x3000, 0x0800, 0x3000, 0xb000
614};
615
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,
625 0x3000, 0x0800, 0x3000
626};
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
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
659 xscale_UV = xscale/uv_hscale;
660 yscale_UV = yscale/uv_vscale;
661
662 xscale = xscale_UV * uv_hscale;
663 yscale = yscale_UV * uv_vscale;
664
665
666
667
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
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)));
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;
695
696 switch (overlay->crtc->base.fb->bits_per_pixel) {
697 case 8:
698 regs->DCLRKV = 0;
699 regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
700 break;
701
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 }
710 break;
711
712 case 24:
713 case 32:
714 regs->DCLRKV = key;
715 regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
716 break;
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) {
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;
736 }
737 } else {
738 switch (params->format & I915_OVERLAY_DEPTH_MASK) {
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;
745 }
746
747 switch (params->format & I915_OVERLAY_SWAP_MASK) {
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;
759 }
760 }
761
762 return cmd;
763}
764
765static int intel_overlay_do_put_image(struct intel_overlay *overlay,
766 struct drm_i915_gem_object *new_bo,
767 struct put_image_params *params)
768{
769 int ret, tmp_width;
770 struct overlay_registers *regs;
771 bool scale_changed = false;
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
778 ret = intel_overlay_release_old_vid(overlay);
779 if (ret != 0)
780 return ret;
781
782 ret = i915_gem_object_pin(new_bo, PAGE_SIZE, true);
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
790 ret = i915_gem_object_put_fence(new_bo);
791 if (ret)
792 goto out_unpin;
793
794 if (!overlay->active) {
795 regs = intel_overlay_map_regs(overlay);
796 if (!regs) {
797 ret = -ENOMEM;
798 goto out_unpin;
799 }
800 regs->OCONFIG = OCONF_CC_OUT_8BIT;
801 if (IS_GEN4(overlay->dev))
802 regs->OCONFIG |= OCONF_CSC_MODE_BT709;
803 regs->OCONFIG |= overlay->crtc->pipe == 0 ?
804 OCONF_PIPE_A : OCONF_PIPE_B;
805 intel_overlay_unmap_regs(overlay, regs);
806
807 ret = intel_overlay_on(overlay);
808 if (ret != 0)
809 goto out_unpin;
810 }
811
812 regs = intel_overlay_map_regs(overlay);
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,
828 params->offset_Y, tmp_width);
829 regs->SHEIGHT = params->src_h;
830 regs->OBUF_0Y = new_bo->gtt_offset + params-> offset_Y;
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,
839 params->src_w/uv_hscale);
840 tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
841 params->src_w/uv_hscale);
842 regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
843 regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
844 regs->OBUF_0U = new_bo->gtt_offset + params->offset_U;
845 regs->OBUF_0V = new_bo->gtt_offset + params->offset_V;
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
855 intel_overlay_unmap_regs(overlay, regs);
856
857 ret = intel_overlay_continue(overlay, scale_changed);
858 if (ret)
859 goto out_unpin;
860
861 overlay->old_vid_bo = overlay->vid_bo;
862 overlay->vid_bo = new_bo;
863
864 return 0;
865
866out_unpin:
867 i915_gem_object_unpin(new_bo);
868 return ret;
869}
870
871int intel_overlay_switch_off(struct intel_overlay *overlay,
872 bool interruptible)
873{
874 struct overlay_registers *regs;
875 struct drm_device *dev = overlay->dev;
876 int ret;
877
878 BUG_ON(!mutex_is_locked(&dev->struct_mutex));
879 BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
880
881 ret = intel_overlay_recover_from_interrupt(overlay, interruptible);
882 if (ret != 0)
883 return ret;
884
885 if (!overlay->active)
886 return 0;
887
888 ret = intel_overlay_release_old_vid(overlay);
889 if (ret != 0)
890 return ret;
891
892 regs = intel_overlay_map_regs(overlay);
893 regs->OCMD = 0;
894 intel_overlay_unmap_regs(overlay, regs);
895
896 ret = intel_overlay_off(overlay, interruptible);
897 if (ret != 0)
898 return ret;
899
900 intel_overlay_off_tail(overlay);
901 return 0;
902}
903
904static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
905 struct intel_crtc *crtc)
906{
907 drm_i915_private_t *dev_priv = overlay->dev->dev_private;
908
909 if (!crtc->active)
910 return -EINVAL;
911
912
913 if (INTEL_INFO(overlay->dev)->gen < 4 &&
914 (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE)
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;
923 drm_i915_private_t *dev_priv = dev->dev_private;
924 u32 pfit_control = I915_READ(PFIT_CONTROL);
925 u32 ratio;
926
927
928
929
930 if (INTEL_INFO(dev)->gen >= 4) {
931
932 ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
933 } else {
934 if (pfit_control & VERT_AUTO_SCALE)
935 ratio = I915_READ(PFIT_AUTO_RATIOS);
936 else
937 ratio = I915_READ(PFIT_PGM_RATIOS);
938 ratio >>= PFIT_VERT_SCALE_SHIFT;
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
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)
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
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,
975 struct drm_i915_gem_object *new_bo)
976{
977 int uv_hscale = uv_hsubsampling(rec->flags);
978 int uv_vscale = uv_vsubsampling(rec->flags);
979 u32 stride_mask;
980 int depth;
981 u32 tmp;
982
983
984 if (IS_845G(dev) || IS_I830(dev)) {
985 if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
986 rec->src_width > IMAGE_MAX_WIDTH_LEGACY)
987 return -EINVAL;
988 } else {
989 if (rec->src_height > IMAGE_MAX_HEIGHT ||
990 rec->src_width > IMAGE_MAX_WIDTH)
991 return -EINVAL;
992 }
993
994
995 if (rec->src_height < N_VERT_Y_TAPS*4 ||
996 rec->src_width < N_HORIZ_Y_TAPS*4)
997 return -EINVAL;
998
999
1000 switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1001 case I915_OVERLAY_RGB:
1002
1003 return -EINVAL;
1004
1005 case I915_OVERLAY_YUV_PACKED:
1006 if (uv_vscale != 1)
1007 return -EINVAL;
1008
1009 depth = packed_depth_bytes(rec->flags);
1010 if (depth < 0)
1011 return depth;
1012
1013
1014 rec->stride_UV = 0;
1015 rec->offset_U = 0;
1016 rec->offset_V = 0;
1017
1018 if (rec->offset_Y % depth)
1019 return -EINVAL;
1020 break;
1021
1022 case I915_OVERLAY_YUV_PLANAR:
1023 if (uv_vscale < 0 || uv_hscale < 0)
1024 return -EINVAL;
1025
1026 break;
1027
1028 default:
1029 return -EINVAL;
1030 }
1031
1032 if (rec->src_width % uv_hscale)
1033 return -EINVAL;
1034
1035
1036 if (IS_I830(dev) || IS_845G(dev))
1037 stride_mask = 255;
1038 else
1039 stride_mask = 63;
1040
1041 if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
1042 return -EINVAL;
1043 if (IS_GEN4(dev) && rec->stride_Y < 512)
1044 return -EINVAL;
1045
1046 tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
1047 4096 : 8192;
1048 if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
1049 return -EINVAL;
1050
1051
1052 switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1053 case I915_OVERLAY_RGB:
1054 case I915_OVERLAY_YUV_PACKED:
1055
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;
1060 if (rec->offset_Y + tmp > new_bo->base.size)
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
1070 tmp = rec->stride_Y * rec->src_height;
1071 if (rec->offset_Y + tmp > new_bo->base.size)
1072 return -EINVAL;
1073
1074 tmp = rec->stride_UV * (rec->src_height / uv_vscale);
1075 if (rec->offset_U + tmp > new_bo->base.size ||
1076 rec->offset_V + tmp > new_bo->base.size)
1077 return -EINVAL;
1078 break;
1079 }
1080
1081 return 0;
1082}
1083
1084
1085
1086
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
1094 if (IS_I830(dev))
1095 return -1;
1096
1097 pfit_control = I915_READ(PFIT_CONTROL);
1098
1099
1100 if ((pfit_control & PFIT_ENABLE) == 0)
1101 return -1;
1102
1103
1104 if (IS_GEN4(dev))
1105 return (pfit_control >> 29) & 0x3;
1106
1107
1108 return 1;
1109}
1110
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;
1119 struct drm_i915_gem_object *new_bo;
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
1138 ret = intel_overlay_switch_off(overlay, true);
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,
1151 DRM_MODE_OBJECT_CRTC);
1152 if (!drmmode_obj) {
1153 ret = -ENOENT;
1154 goto out_free;
1155 }
1156 crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
1157
1158 new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
1159 put_image_rec->bo_handle));
1160 if (!new_bo) {
1161 ret = -ENOENT;
1162 goto out_free;
1163 }
1164
1165 mutex_lock(&dev->mode_config.mutex);
1166 mutex_lock(&dev->struct_mutex);
1167
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
1174 ret = intel_overlay_recover_from_interrupt(overlay, true);
1175 if (ret != 0)
1176 goto out_unlock;
1177
1178 if (overlay->crtc != crtc) {
1179 struct drm_display_mode *mode = &crtc->base.mode;
1180 ret = intel_overlay_switch_off(overlay, true);
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
1191
1192 if (mode->hdisplay > 1024 &&
1193 intel_panel_fitter_pipe(dev) == crtc->pipe) {
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) /
1206 overlay->pfit_vscale_ratio);
1207
1208 params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
1209 overlay->pfit_vscale_ratio) + 1;
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;
1221 if (params->src_scan_h > params->src_h ||
1222 params->src_scan_w > params->src_w) {
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
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);
1256 drm_gem_object_unreference_unlocked(&new_bo->base);
1257out_free:
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++) {
1278 if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
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{
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))
1306 return -EINVAL;
1307
1308 if (!check_gamma5_errata(attrs->gamma5))
1309 return -EINVAL;
1310
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
1337 ret = -EINVAL;
1338 if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
1339 attrs->color_key = overlay->color_key;
1340 attrs->brightness = overlay->brightness;
1341 attrs->contrast = overlay->contrast;
1342 attrs->saturation = overlay->saturation;
1343
1344 if (!IS_GEN2(dev)) {
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 }
1352 } else {
1353 if (attrs->brightness < -128 || attrs->brightness > 127)
1354 goto out_unlock;
1355 if (attrs->contrast > 255)
1356 goto out_unlock;
1357 if (attrs->saturation > 1023)
1358 goto out_unlock;
1359
1360 overlay->color_key = attrs->color_key;
1361 overlay->brightness = attrs->brightness;
1362 overlay->contrast = attrs->contrast;
1363 overlay->saturation = attrs->saturation;
1364
1365 regs = intel_overlay_map_regs(overlay);
1366 if (!regs) {
1367 ret = -ENOMEM;
1368 goto out_unlock;
1369 }
1370
1371 update_reg_attrs(overlay, regs);
1372
1373 intel_overlay_unmap_regs(overlay, regs);
1374
1375 if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
1376 if (IS_GEN2(dev))
1377 goto out_unlock;
1378
1379 if (overlay->active) {
1380 ret = -EBUSY;
1381 goto out_unlock;
1382 }
1383
1384 ret = check_gamma(attrs);
1385 if (ret)
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 }
1395 }
1396
1397 ret = 0;
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;
1409 struct drm_i915_gem_object *reg_bo;
1410 struct overlay_registers *regs;
1411 int ret;
1412
1413 if (!HAS_OVERLAY(dev))
1414 return;
1415
1416 overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
1417 if (!overlay)
1418 return;
1419 overlay->dev = dev;
1420
1421 reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
1422 if (!reg_bo)
1423 goto out_free;
1424 overlay->reg_bo = reg_bo;
1425
1426 if (OVERLAY_NEEDS_PHYSICAL(dev)) {
1427 ret = i915_gem_attach_phys_object(dev, reg_bo,
1428 I915_GEM_PHYS_OVERLAY_REGS,
1429 PAGE_SIZE);
1430 if (ret) {
1431 DRM_ERROR("failed to attach phys overlay regs\n");
1432 goto out_free_bo;
1433 }
1434 overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
1435 } else {
1436 ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
1437 if (ret) {
1438 DRM_ERROR("failed to pin overlay register bo\n");
1439 goto out_free_bo;
1440 }
1441 overlay->flip_addr = reg_bo->gtt_offset;
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 }
1448 }
1449
1450
1451 overlay->color_key = 0x0101fe;
1452 overlay->brightness = -19;
1453 overlay->contrast = 75;
1454 overlay->saturation = 146;
1455
1456 regs = intel_overlay_map_regs(overlay);
1457 if (!regs)
1458 goto out_free_bo;
1459
1460 memset(regs, 0, sizeof(struct overlay_registers));
1461 update_polyphase_filter(regs);
1462 update_reg_attrs(overlay, regs);
1463
1464 intel_overlay_unmap_regs(overlay, regs);
1465
1466 dev_priv->overlay = overlay;
1467 DRM_INFO("initialized overlay support\n");
1468 return;
1469
1470out_unpin_bo:
1471 i915_gem_object_unpin(reg_bo);
1472out_free_bo:
1473 drm_gem_object_unreference(®_bo->base);
1474out_free:
1475 kfree(overlay);
1476 return;
1477}
1478
1479void intel_cleanup_overlay(struct drm_device *dev)
1480{
1481 drm_i915_private_t *dev_priv = dev->dev_private;
1482
1483 if (!dev_priv->overlay)
1484 return;
1485
1486
1487
1488
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);
1493}
1494
1495#ifdef CONFIG_DEBUG_FS
1496#include <linux/seq_file.h>
1497
1498struct intel_overlay_error_state {
1499 struct overlay_registers regs;
1500 unsigned long base;
1501 u32 dovsta;
1502 u32 isr;
1503};
1504
1505static struct overlay_registers *
1506intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
1507{
1508 drm_i915_private_t *dev_priv = overlay->dev->dev_private;
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,
1515 overlay->reg_bo->gtt_offset);
1516
1517 return regs;
1518}
1519
1520static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
1521 struct overlay_registers *regs)
1522{
1523 if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1524 io_mapping_unmap_atomic(regs);
1525}
1526
1527
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);
1545 if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1546 error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;
1547 else
1548 error->base = (long) overlay->reg_bo->gtt_offset;
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));
1555 intel_overlay_unmap_regs_atomic(overlay, regs);
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}
1616#endif
1617