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