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:
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
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
24 * Daniel Vetter <daniel@ffwll.ch>
26 * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
30 #include <drm/i915_drm.h>
33 #include "intel_drv.h"
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
45 /* overlay register definitions */
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)
68 #define OCMD_BUF_TYPE_MASK (0x1<<5)
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)
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)
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
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))
105 /* overlay flip addr flag */
106 #define OFC_UPDATE 0x1
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
116 /* memory bufferd overlay registers */
117 struct overlay_registers {
145 u32 RESERVED1; /* 0x6C */
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];
171 struct 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;
178 u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
180 u32 brightness, contrast, saturation;
181 u32 old_xscale, old_yscale;
182 /* register access */
184 struct drm_i915_gem_object *reg_bo;
186 uint32_t last_flip_req;
187 void (*flip_tail)(struct intel_overlay *);
190 static struct overlay_registers *
191 intel_overlay_map_regs(struct intel_overlay *overlay)
193 struct overlay_registers *regs;
195 if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) {
196 regs = overlay->reg_bo->phys_obj->handle->vaddr;
198 regs = pmap_mapdev_attr(overlay->dev->agp->base +
199 overlay->reg_bo->gtt_offset, PAGE_SIZE,
200 PAT_WRITE_COMBINING);
205 static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
206 struct overlay_registers *regs)
208 if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
209 pmap_unmapdev((vm_offset_t)regs, PAGE_SIZE);
212 static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
213 void (*tail)(struct intel_overlay *))
215 struct drm_device *dev = overlay->dev;
216 drm_i915_private_t *dev_priv = dev->dev_private;
217 struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
220 BUG_ON(overlay->last_flip_req);
221 ret = i915_add_request(ring, NULL, &overlay->last_flip_req);
225 overlay->flip_tail = tail;
226 ret = i915_wait_seqno(ring, overlay->last_flip_req);
229 i915_gem_retire_requests(dev);
231 overlay->last_flip_req = 0;
235 /* overlay needs to be disable in OCMD reg */
236 static int intel_overlay_on(struct intel_overlay *overlay)
238 struct drm_device *dev = overlay->dev;
239 struct drm_i915_private *dev_priv = dev->dev_private;
240 struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
243 BUG_ON(overlay->active);
246 WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE));
248 ret = intel_ring_begin(ring, 4);
252 intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
253 intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE);
254 intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
255 intel_ring_emit(ring, MI_NOOP);
256 intel_ring_advance(ring);
258 return intel_overlay_do_wait_request(overlay, NULL);
261 /* overlay needs to be enabled in OCMD reg */
262 static int intel_overlay_continue(struct intel_overlay *overlay,
263 bool load_polyphase_filter)
265 struct drm_device *dev = overlay->dev;
266 drm_i915_private_t *dev_priv = dev->dev_private;
267 struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
268 u32 flip_addr = overlay->flip_addr;
272 BUG_ON(!overlay->active);
274 if (load_polyphase_filter)
275 flip_addr |= OFC_UPDATE;
277 /* check for underruns */
278 tmp = I915_READ(DOVSTA);
280 DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
282 ret = intel_ring_begin(ring, 2);
286 intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
287 intel_ring_emit(ring, flip_addr);
288 intel_ring_advance(ring);
290 return i915_add_request(ring, NULL, &overlay->last_flip_req);
293 static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
295 struct drm_i915_gem_object *obj = overlay->old_vid_bo;
297 i915_gem_object_unpin(obj);
298 drm_gem_object_unreference(&obj->base);
300 overlay->old_vid_bo = NULL;
303 static void intel_overlay_off_tail(struct intel_overlay *overlay)
305 struct drm_i915_gem_object *obj = overlay->vid_bo;
307 /* never have the overlay hw on without showing a frame */
308 KASSERT(overlay->vid_bo != NULL, ("No vid_bo"));
310 i915_gem_object_unpin(obj);
311 drm_gem_object_unreference(&obj->base);
312 overlay->vid_bo = NULL;
314 overlay->crtc->overlay = NULL;
315 overlay->crtc = NULL;
319 /* overlay needs to be disabled in OCMD reg */
320 static int intel_overlay_off(struct intel_overlay *overlay)
322 struct drm_device *dev = overlay->dev;
323 struct drm_i915_private *dev_priv = dev->dev_private;
324 struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
325 u32 flip_addr = overlay->flip_addr;
328 BUG_ON(!overlay->active);
330 /* According to intel docs the overlay hw may hang (when switching
331 * off) without loading the filter coeffs. It is however unclear whether
332 * this applies to the disabling of the overlay or to the switching off
333 * of the hw. Do it in both cases */
334 flip_addr |= OFC_UPDATE;
336 ret = intel_ring_begin(ring, 6);
340 /* wait for overlay to go idle */
341 intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
342 intel_ring_emit(ring, flip_addr);
343 intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
344 /* turn overlay off */
346 /* Workaround: Don't disable the overlay fully, since otherwise
347 * it dies on the next OVERLAY_ON cmd. */
348 intel_ring_emit(ring, MI_NOOP);
349 intel_ring_emit(ring, MI_NOOP);
350 intel_ring_emit(ring, MI_NOOP);
352 intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
353 intel_ring_emit(ring, flip_addr);
354 intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
356 intel_ring_advance(ring);
358 return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
361 /* recover from an interruption due to a signal
362 * We have to be careful not to repeat work forever an make forward progess. */
363 static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
365 struct drm_device *dev = overlay->dev;
366 drm_i915_private_t *dev_priv = dev->dev_private;
367 struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
370 if (overlay->last_flip_req == 0)
373 ret = i915_wait_seqno(ring, overlay->last_flip_req);
376 i915_gem_retire_requests(dev);
378 if (overlay->flip_tail)
379 overlay->flip_tail(overlay);
381 overlay->last_flip_req = 0;
385 /* Wait for pending overlay flip and release old frame.
386 * Needs to be called before the overlay register are changed
387 * via intel_overlay_(un)map_regs
389 static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
391 struct drm_device *dev = overlay->dev;
392 drm_i915_private_t *dev_priv = dev->dev_private;
393 struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
396 /* Only wait if there is actually an old frame to release to
397 * guarantee forward progress.
399 if (!overlay->old_vid_bo)
402 if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
403 /* synchronous slowpath */
404 ret = intel_ring_begin(ring, 2);
408 intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
409 intel_ring_emit(ring, MI_NOOP);
410 intel_ring_advance(ring);
412 ret = intel_overlay_do_wait_request(overlay,
413 intel_overlay_release_old_vid_tail);
418 intel_overlay_release_old_vid_tail(overlay);
422 struct put_image_params {
439 static int packed_depth_bytes(u32 format)
441 switch (format & I915_OVERLAY_DEPTH_MASK) {
442 case I915_OVERLAY_YUV422:
444 case I915_OVERLAY_YUV411:
445 /* return 6; not implemented */
451 static int packed_width_bytes(u32 format, short width)
453 switch (format & I915_OVERLAY_DEPTH_MASK) {
454 case I915_OVERLAY_YUV422:
461 static int uv_hsubsampling(u32 format)
463 switch (format & I915_OVERLAY_DEPTH_MASK) {
464 case I915_OVERLAY_YUV422:
465 case I915_OVERLAY_YUV420:
467 case I915_OVERLAY_YUV411:
468 case I915_OVERLAY_YUV410:
475 static int uv_vsubsampling(u32 format)
477 switch (format & I915_OVERLAY_DEPTH_MASK) {
478 case I915_OVERLAY_YUV420:
479 case I915_OVERLAY_YUV410:
481 case I915_OVERLAY_YUV422:
482 case I915_OVERLAY_YUV411:
489 static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
491 u32 mask, shift, ret;
499 ret = ((offset + width + mask) >> shift) - (offset >> shift);
506 static const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
507 0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
508 0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
509 0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
510 0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
511 0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
512 0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
513 0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
514 0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
515 0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
516 0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
517 0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
518 0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
519 0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
520 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
521 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
522 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
523 0xb000, 0x3000, 0x0800, 0x3000, 0xb000
526 static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
527 0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
528 0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
529 0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
530 0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
531 0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
532 0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
533 0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
534 0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
535 0x3000, 0x0800, 0x3000
538 static void update_polyphase_filter(struct overlay_registers *regs)
540 memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
541 memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
544 static bool update_scaling_factors(struct intel_overlay *overlay,
545 struct overlay_registers *regs,
546 struct put_image_params *params)
548 /* fixed point with a 12 bit shift */
549 u32 xscale, yscale, xscale_UV, yscale_UV;
551 #define FRACT_MASK 0xfff
552 bool scale_changed = false;
553 int uv_hscale = uv_hsubsampling(params->format);
554 int uv_vscale = uv_vsubsampling(params->format);
556 if (params->dst_w > 1)
557 xscale = ((params->src_scan_w - 1) << FP_SHIFT)
560 xscale = 1 << FP_SHIFT;
562 if (params->dst_h > 1)
563 yscale = ((params->src_scan_h - 1) << FP_SHIFT)
566 yscale = 1 << FP_SHIFT;
568 /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
569 xscale_UV = xscale/uv_hscale;
570 yscale_UV = yscale/uv_vscale;
571 /* make the Y scale to UV scale ratio an exact multiply */
572 xscale = xscale_UV * uv_hscale;
573 yscale = yscale_UV * uv_vscale;
579 if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
580 scale_changed = true;
581 overlay->old_xscale = xscale;
582 overlay->old_yscale = yscale;
584 regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) |
585 ((xscale >> FP_SHIFT) << 16) |
586 ((xscale & FRACT_MASK) << 3));
588 regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) |
589 ((xscale_UV >> FP_SHIFT) << 16) |
590 ((xscale_UV & FRACT_MASK) << 3));
592 regs->UVSCALEV = ((((yscale >> FP_SHIFT) << 16) |
593 ((yscale_UV >> FP_SHIFT) << 0)));
596 update_polyphase_filter(regs);
598 return scale_changed;
601 static void update_colorkey(struct intel_overlay *overlay,
602 struct overlay_registers *regs)
604 u32 key = overlay->color_key;
606 switch (overlay->crtc->base.fb->bits_per_pixel) {
609 regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
613 if (overlay->crtc->base.fb->depth == 15) {
614 regs->DCLRKV = RGB15_TO_COLORKEY(key);
615 regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
617 regs->DCLRKV = RGB16_TO_COLORKEY(key);
618 regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
625 regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
630 static u32 overlay_cmd_reg(struct put_image_params *params)
632 u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
634 if (params->format & I915_OVERLAY_YUV_PLANAR) {
635 switch (params->format & I915_OVERLAY_DEPTH_MASK) {
636 case I915_OVERLAY_YUV422:
637 cmd |= OCMD_YUV_422_PLANAR;
639 case I915_OVERLAY_YUV420:
640 cmd |= OCMD_YUV_420_PLANAR;
642 case I915_OVERLAY_YUV411:
643 case I915_OVERLAY_YUV410:
644 cmd |= OCMD_YUV_410_PLANAR;
647 } else { /* YUV packed */
648 switch (params->format & I915_OVERLAY_DEPTH_MASK) {
649 case I915_OVERLAY_YUV422:
650 cmd |= OCMD_YUV_422_PACKED;
652 case I915_OVERLAY_YUV411:
653 cmd |= OCMD_YUV_411_PACKED;
657 switch (params->format & I915_OVERLAY_SWAP_MASK) {
658 case I915_OVERLAY_NO_SWAP:
660 case I915_OVERLAY_UV_SWAP:
663 case I915_OVERLAY_Y_SWAP:
666 case I915_OVERLAY_Y_AND_UV_SWAP:
667 cmd |= OCMD_Y_AND_UV_SWAP;
676 max_u32(u32 a, u32 b)
679 return (a > b ? a : b);
682 static int intel_overlay_do_put_image(struct intel_overlay *overlay,
683 struct drm_i915_gem_object *new_bo,
684 struct put_image_params *params)
687 struct overlay_registers *regs;
688 bool scale_changed = false;
690 KASSERT(overlay != NULL, ("No overlay ?"));
691 DRM_LOCK_ASSERT(overlay->dev);
693 ret = intel_overlay_release_old_vid(overlay);
697 ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL);
701 ret = i915_gem_object_put_fence(new_bo);
705 if (!overlay->active) {
706 regs = intel_overlay_map_regs(overlay);
711 regs->OCONFIG = OCONF_CC_OUT_8BIT;
712 if (IS_GEN4(overlay->dev))
713 regs->OCONFIG |= OCONF_CSC_MODE_BT709;
714 regs->OCONFIG |= overlay->crtc->pipe == 0 ?
715 OCONF_PIPE_A : OCONF_PIPE_B;
716 intel_overlay_unmap_regs(overlay, regs);
718 ret = intel_overlay_on(overlay);
723 regs = intel_overlay_map_regs(overlay);
729 regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
730 regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
732 if (params->format & I915_OVERLAY_YUV_PACKED)
733 tmp_width = packed_width_bytes(params->format, params->src_w);
735 tmp_width = params->src_w;
737 regs->SWIDTH = params->src_w;
738 regs->SWIDTHSW = calc_swidthsw(overlay->dev,
739 params->offset_Y, tmp_width);
740 regs->SHEIGHT = params->src_h;
741 regs->OBUF_0Y = new_bo->gtt_offset + params->offset_Y;
742 regs->OSTRIDE = params->stride_Y;
744 if (params->format & I915_OVERLAY_YUV_PLANAR) {
745 int uv_hscale = uv_hsubsampling(params->format);
746 int uv_vscale = uv_vsubsampling(params->format);
748 regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
749 tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
750 params->src_w/uv_hscale);
751 tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
752 params->src_w/uv_hscale);
753 regs->SWIDTHSW |= max_u32(tmp_U, tmp_V) << 16;
754 regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
755 regs->OBUF_0U = new_bo->gtt_offset + params->offset_U;
756 regs->OBUF_0V = new_bo->gtt_offset + params->offset_V;
757 regs->OSTRIDE |= params->stride_UV << 16;
760 scale_changed = update_scaling_factors(overlay, regs, params);
762 update_colorkey(overlay, regs);
764 regs->OCMD = overlay_cmd_reg(params);
766 intel_overlay_unmap_regs(overlay, regs);
768 ret = intel_overlay_continue(overlay, scale_changed);
772 overlay->old_vid_bo = overlay->vid_bo;
773 overlay->vid_bo = new_bo;
778 i915_gem_object_unpin(new_bo);
782 int intel_overlay_switch_off(struct intel_overlay *overlay)
784 struct overlay_registers *regs;
787 DRM_LOCK_ASSERT(overlay->dev);
789 ret = intel_overlay_recover_from_interrupt(overlay);
793 if (!overlay->active)
796 ret = intel_overlay_release_old_vid(overlay);
800 regs = intel_overlay_map_regs(overlay);
802 intel_overlay_unmap_regs(overlay, regs);
804 ret = intel_overlay_off(overlay);
808 intel_overlay_off_tail(overlay);
812 static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
813 struct intel_crtc *crtc)
815 drm_i915_private_t *dev_priv = overlay->dev->dev_private;
820 /* can't use the overlay with double wide pipe */
821 if (INTEL_INFO(overlay->dev)->gen < 4 &&
822 (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE)
828 static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
830 struct drm_device *dev = overlay->dev;
831 drm_i915_private_t *dev_priv = dev->dev_private;
832 u32 pfit_control = I915_READ(PFIT_CONTROL);
835 /* XXX: This is not the same logic as in the xorg driver, but more in
836 * line with the intel documentation for the i965
838 if (INTEL_INFO(dev)->gen >= 4) {
839 /* on i965 use the PGM reg to read out the autoscaler values */
840 ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
842 if (pfit_control & VERT_AUTO_SCALE)
843 ratio = I915_READ(PFIT_AUTO_RATIOS);
845 ratio = I915_READ(PFIT_PGM_RATIOS);
846 ratio >>= PFIT_VERT_SCALE_SHIFT;
849 overlay->pfit_vscale_ratio = ratio;
852 static int check_overlay_dst(struct intel_overlay *overlay,
853 struct drm_intel_overlay_put_image *rec)
855 struct drm_display_mode *mode = &overlay->crtc->base.mode;
857 if (rec->dst_x < mode->hdisplay &&
858 rec->dst_x + rec->dst_width <= mode->hdisplay &&
859 rec->dst_y < mode->vdisplay &&
860 rec->dst_y + rec->dst_height <= mode->vdisplay)
866 static int check_overlay_scaling(struct put_image_params *rec)
870 /* downscaling limit is 8.0 */
871 tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
874 tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
881 static int check_overlay_src(struct drm_device *dev,
882 struct drm_intel_overlay_put_image *rec,
883 struct drm_i915_gem_object *new_bo)
885 int uv_hscale = uv_hsubsampling(rec->flags);
886 int uv_vscale = uv_vsubsampling(rec->flags);
891 /* check src dimensions */
892 if (IS_845G(dev) || IS_I830(dev)) {
893 if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
894 rec->src_width > IMAGE_MAX_WIDTH_LEGACY)
897 if (rec->src_height > IMAGE_MAX_HEIGHT ||
898 rec->src_width > IMAGE_MAX_WIDTH)
902 /* better safe than sorry, use 4 as the maximal subsampling ratio */
903 if (rec->src_height < N_VERT_Y_TAPS*4 ||
904 rec->src_width < N_HORIZ_Y_TAPS*4)
907 /* check alignment constraints */
908 switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
909 case I915_OVERLAY_RGB:
910 /* not implemented */
913 case I915_OVERLAY_YUV_PACKED:
917 depth = packed_depth_bytes(rec->flags);
921 /* ignore UV planes */
925 /* check pixel alignment */
926 if (rec->offset_Y % depth)
930 case I915_OVERLAY_YUV_PLANAR:
931 if (uv_vscale < 0 || uv_hscale < 0)
933 /* no offset restrictions for planar formats */
940 if (rec->src_width % uv_hscale)
943 /* stride checking */
944 if (IS_I830(dev) || IS_845G(dev))
949 if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
951 if (IS_GEN4(dev) && rec->stride_Y < 512)
954 tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
956 if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
959 /* check buffer dimensions */
960 switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
961 case I915_OVERLAY_RGB:
962 case I915_OVERLAY_YUV_PACKED:
963 /* always 4 Y values per depth pixels */
964 if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
967 tmp = rec->stride_Y*rec->src_height;
968 if (rec->offset_Y + tmp > new_bo->base.size)
972 case I915_OVERLAY_YUV_PLANAR:
973 if (rec->src_width > rec->stride_Y)
975 if (rec->src_width/uv_hscale > rec->stride_UV)
978 tmp = rec->stride_Y * rec->src_height;
979 if (rec->offset_Y + tmp > new_bo->base.size)
982 tmp = rec->stride_UV * (rec->src_height / uv_vscale);
983 if (rec->offset_U + tmp > new_bo->base.size ||
984 rec->offset_V + tmp > new_bo->base.size)
993 * Return the pipe currently connected to the panel fitter,
994 * or -1 if the panel fitter is not present or not in use
996 static int intel_panel_fitter_pipe(struct drm_device *dev)
998 struct drm_i915_private *dev_priv = dev->dev_private;
1001 /* i830 doesn't have a panel fitter */
1005 pfit_control = I915_READ(PFIT_CONTROL);
1007 /* See if the panel fitter is in use */
1008 if ((pfit_control & PFIT_ENABLE) == 0)
1011 /* 965 can place panel fitter on either pipe */
1013 return (pfit_control >> 29) & 0x3;
1015 /* older chips can only use pipe 1 */
1019 int intel_overlay_put_image(struct drm_device *dev, void *data,
1020 struct drm_file *file_priv)
1022 struct drm_intel_overlay_put_image *put_image_rec = data;
1023 drm_i915_private_t *dev_priv = dev->dev_private;
1024 struct intel_overlay *overlay;
1025 struct drm_mode_object *drmmode_obj;
1026 struct intel_crtc *crtc;
1027 struct drm_i915_gem_object *new_bo;
1028 struct put_image_params *params;
1032 DRM_ERROR("called with no initialization\n");
1036 overlay = dev_priv->overlay;
1038 DRM_DEBUG("userspace bug: no overlay\n");
1042 if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
1043 lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
1046 ret = intel_overlay_switch_off(overlay);
1049 lockmgr(&dev->mode_config.mutex, LK_RELEASE);
1054 params = kmalloc(sizeof(struct put_image_params), DRM_I915_GEM,
1057 drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
1058 DRM_MODE_OBJECT_CRTC);
1063 crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
1065 new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
1066 put_image_rec->bo_handle));
1067 if (&new_bo->base == NULL) {
1072 lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
1075 if (new_bo->tiling_mode) {
1076 DRM_ERROR("buffer used for overlay image can not be tiled\n");
1081 ret = intel_overlay_recover_from_interrupt(overlay);
1085 if (overlay->crtc != crtc) {
1086 struct drm_display_mode *mode = &crtc->base.mode;
1087 ret = intel_overlay_switch_off(overlay);
1091 ret = check_overlay_possible_on_crtc(overlay, crtc);
1095 overlay->crtc = crtc;
1096 crtc->overlay = overlay;
1098 /* line too wide, i.e. one-line-mode */
1099 if (mode->hdisplay > 1024 &&
1100 intel_panel_fitter_pipe(dev) == crtc->pipe) {
1101 overlay->pfit_active = 1;
1102 update_pfit_vscale_ratio(overlay);
1104 overlay->pfit_active = 0;
1107 ret = check_overlay_dst(overlay, put_image_rec);
1111 if (overlay->pfit_active) {
1112 params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
1113 overlay->pfit_vscale_ratio);
1114 /* shifting right rounds downwards, so add 1 */
1115 params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
1116 overlay->pfit_vscale_ratio) + 1;
1118 params->dst_y = put_image_rec->dst_y;
1119 params->dst_h = put_image_rec->dst_height;
1121 params->dst_x = put_image_rec->dst_x;
1122 params->dst_w = put_image_rec->dst_width;
1124 params->src_w = put_image_rec->src_width;
1125 params->src_h = put_image_rec->src_height;
1126 params->src_scan_w = put_image_rec->src_scan_width;
1127 params->src_scan_h = put_image_rec->src_scan_height;
1128 if (params->src_scan_h > params->src_h ||
1129 params->src_scan_w > params->src_w) {
1134 ret = check_overlay_src(dev, put_image_rec, new_bo);
1137 params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
1138 params->stride_Y = put_image_rec->stride_Y;
1139 params->stride_UV = put_image_rec->stride_UV;
1140 params->offset_Y = put_image_rec->offset_Y;
1141 params->offset_U = put_image_rec->offset_U;
1142 params->offset_V = put_image_rec->offset_V;
1144 /* Check scaling after src size to prevent a divide-by-zero. */
1145 ret = check_overlay_scaling(params);
1149 ret = intel_overlay_do_put_image(overlay, new_bo, params);
1154 lockmgr(&dev->mode_config.mutex, LK_RELEASE);
1156 drm_free(params, DRM_I915_GEM);
1162 lockmgr(&dev->mode_config.mutex, LK_RELEASE);
1163 drm_gem_object_unreference_unlocked(&new_bo->base);
1165 drm_free(params, DRM_I915_GEM);
1170 static void update_reg_attrs(struct intel_overlay *overlay,
1171 struct overlay_registers *regs)
1173 regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
1174 regs->OCLRC1 = overlay->saturation;
1177 static bool check_gamma_bounds(u32 gamma1, u32 gamma2)
1181 if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
1184 for (i = 0; i < 3; i++) {
1185 if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
1192 static bool check_gamma5_errata(u32 gamma5)
1196 for (i = 0; i < 3; i++) {
1197 if (((gamma5 >> i*8) & 0xff) == 0x80)
1204 static int check_gamma(struct drm_intel_overlay_attrs *attrs)
1206 if (!check_gamma_bounds(0, attrs->gamma0) ||
1207 !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1208 !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1209 !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1210 !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1211 !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1212 !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
1215 if (!check_gamma5_errata(attrs->gamma5))
1221 int intel_overlay_attrs(struct drm_device *dev, void *data,
1222 struct drm_file *file_priv)
1224 struct drm_intel_overlay_attrs *attrs = data;
1225 drm_i915_private_t *dev_priv = dev->dev_private;
1226 struct intel_overlay *overlay;
1227 struct overlay_registers *regs;
1231 DRM_ERROR("called with no initialization\n");
1235 overlay = dev_priv->overlay;
1237 DRM_DEBUG("userspace bug: no overlay\n");
1241 lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
1245 if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
1246 attrs->color_key = overlay->color_key;
1247 attrs->brightness = overlay->brightness;
1248 attrs->contrast = overlay->contrast;
1249 attrs->saturation = overlay->saturation;
1251 if (!IS_GEN2(dev)) {
1252 attrs->gamma0 = I915_READ(OGAMC0);
1253 attrs->gamma1 = I915_READ(OGAMC1);
1254 attrs->gamma2 = I915_READ(OGAMC2);
1255 attrs->gamma3 = I915_READ(OGAMC3);
1256 attrs->gamma4 = I915_READ(OGAMC4);
1257 attrs->gamma5 = I915_READ(OGAMC5);
1260 if (attrs->brightness < -128 || attrs->brightness > 127)
1262 if (attrs->contrast > 255)
1264 if (attrs->saturation > 1023)
1267 overlay->color_key = attrs->color_key;
1268 overlay->brightness = attrs->brightness;
1269 overlay->contrast = attrs->contrast;
1270 overlay->saturation = attrs->saturation;
1272 regs = intel_overlay_map_regs(overlay);
1278 update_reg_attrs(overlay, regs);
1280 intel_overlay_unmap_regs(overlay, regs);
1282 if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
1286 if (overlay->active) {
1291 ret = check_gamma(attrs);
1295 I915_WRITE(OGAMC0, attrs->gamma0);
1296 I915_WRITE(OGAMC1, attrs->gamma1);
1297 I915_WRITE(OGAMC2, attrs->gamma2);
1298 I915_WRITE(OGAMC3, attrs->gamma3);
1299 I915_WRITE(OGAMC4, attrs->gamma4);
1300 I915_WRITE(OGAMC5, attrs->gamma5);
1307 lockmgr(&dev->mode_config.mutex, LK_RELEASE);
1312 void intel_setup_overlay(struct drm_device *dev)
1314 drm_i915_private_t *dev_priv = dev->dev_private;
1315 struct intel_overlay *overlay;
1316 struct drm_i915_gem_object *reg_bo;
1317 struct overlay_registers *regs;
1320 if (!HAS_OVERLAY(dev))
1323 overlay = kmalloc(sizeof(struct intel_overlay), DRM_I915_GEM,
1326 if (dev_priv->overlay != NULL)
1330 reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
1333 overlay->reg_bo = reg_bo;
1335 if (OVERLAY_NEEDS_PHYSICAL(dev)) {
1336 ret = i915_gem_attach_phys_object(dev, reg_bo,
1337 I915_GEM_PHYS_OVERLAY_REGS,
1340 DRM_ERROR("failed to attach phys overlay regs\n");
1343 overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
1345 ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
1347 DRM_ERROR("failed to pin overlay register bo\n");
1350 overlay->flip_addr = reg_bo->gtt_offset;
1352 ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
1354 DRM_ERROR("failed to move overlay register bo into the GTT\n");
1359 /* init all values */
1360 overlay->color_key = 0x0101fe;
1361 overlay->brightness = -19;
1362 overlay->contrast = 75;
1363 overlay->saturation = 146;
1365 regs = intel_overlay_map_regs(overlay);
1369 memset(regs, 0, sizeof(struct overlay_registers));
1370 update_polyphase_filter(regs);
1371 update_reg_attrs(overlay, regs);
1373 intel_overlay_unmap_regs(overlay, regs);
1375 dev_priv->overlay = overlay;
1376 DRM_INFO("initialized overlay support\n");
1381 if (!OVERLAY_NEEDS_PHYSICAL(dev))
1382 i915_gem_object_unpin(reg_bo);
1384 drm_gem_object_unreference(®_bo->base);
1387 drm_free(overlay, DRM_I915_GEM);
1391 void intel_cleanup_overlay(struct drm_device *dev)
1393 drm_i915_private_t *dev_priv = dev->dev_private;
1395 if (!dev_priv->overlay)
1398 /* The bo's should be free'd by the generic code already.
1399 * Furthermore modesetting teardown happens beforehand so the
1400 * hardware should be off already */
1401 KASSERT(!dev_priv->overlay->active, ("Overlay still active"));
1403 drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
1404 drm_free(dev_priv->overlay, DRM_I915_GEM);
1407 #ifdef CONFIG_DEBUG_FS
1408 #include <linux/seq_file.h>
1410 struct intel_overlay_error_state {
1411 struct overlay_registers regs;
1417 struct intel_overlay_error_state *
1418 intel_overlay_capture_error_state(struct drm_device *dev)
1420 drm_i915_private_t *dev_priv = dev->dev_private;
1421 struct intel_overlay *overlay = dev_priv->overlay;
1422 struct intel_overlay_error_state *error;
1423 struct overlay_registers __iomem *regs;
1425 if (!overlay || !overlay->active)
1428 error = kmalloc(sizeof(*error), DRM_I915_GEM, M_NOWAIT);
1432 error->dovsta = I915_READ(DOVSTA);
1433 error->isr = I915_READ(ISR);
1434 if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1435 error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;
1437 error->base = (long) overlay->reg_bo->gtt_offset;
1439 regs = intel_overlay_map_regs(overlay);
1443 memcpy(&error->regs, regs, sizeof(struct overlay_registers));
1444 intel_overlay_unmap_regs(overlay, regs);
1449 drm_free(error, DRM_I915_GEM);
1454 intel_overlay_print_error_state(struct sbuf *m,
1455 struct intel_overlay_error_state *error)
1457 sbuf_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
1458 error->dovsta, error->isr);
1459 sbuf_printf(m, " Register file at 0x%08lx:\n",
1462 #define P(x) sbuf_printf(m, " " #x ": 0x%08x\n", error->regs.x)