xref: /dragonfly/sys/dev/drm/i915/intel_overlay.c (revision 3a25be87)
1 /*
2  * Copyright © 2009
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  *    Daniel Vetter <daniel@ffwll.ch>
25  *
26  * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
27  */
28 
29 #include <drm/drmP.h>
30 #include <drm/i915_drm.h>
31 #include "i915_drv.h"
32 #include "i915_reg.h"
33 #include "intel_drv.h"
34 
35 /* Limits for overlay size. According to intel doc, the real limits are:
36  * Y width: 4095, UV width (planar): 2047, Y height: 2047,
37  * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use
38  * the mininum of both.  */
39 #define IMAGE_MAX_WIDTH		2048
40 #define IMAGE_MAX_HEIGHT	2046 /* 2 * 1023 */
41 /* on 830 and 845 these large limits result in the card hanging */
42 #define IMAGE_MAX_WIDTH_LEGACY	1024
43 #define IMAGE_MAX_HEIGHT_LEGACY	1088
44 
45 /* overlay register definitions */
46 /* OCMD register */
47 #define OCMD_TILED_SURFACE	(0x1<<19)
48 #define OCMD_MIRROR_MASK	(0x3<<17)
49 #define OCMD_MIRROR_MODE	(0x3<<17)
50 #define OCMD_MIRROR_HORIZONTAL	(0x1<<17)
51 #define OCMD_MIRROR_VERTICAL	(0x2<<17)
52 #define OCMD_MIRROR_BOTH	(0x3<<17)
53 #define OCMD_BYTEORDER_MASK	(0x3<<14) /* zero for YUYV or FOURCC YUY2 */
54 #define OCMD_UV_SWAP		(0x1<<14) /* YVYU */
55 #define OCMD_Y_SWAP		(0x2<<14) /* UYVY or FOURCC UYVY */
56 #define OCMD_Y_AND_UV_SWAP	(0x3<<14) /* VYUY */
57 #define OCMD_SOURCE_FORMAT_MASK (0xf<<10)
58 #define OCMD_RGB_888		(0x1<<10) /* not in i965 Intel docs */
59 #define OCMD_RGB_555		(0x2<<10) /* not in i965 Intel docs */
60 #define OCMD_RGB_565		(0x3<<10) /* not in i965 Intel docs */
61 #define OCMD_YUV_422_PACKED	(0x8<<10)
62 #define OCMD_YUV_411_PACKED	(0x9<<10) /* not in i965 Intel docs */
63 #define OCMD_YUV_420_PLANAR	(0xc<<10)
64 #define OCMD_YUV_422_PLANAR	(0xd<<10)
65 #define OCMD_YUV_410_PLANAR	(0xe<<10) /* also 411 */
66 #define OCMD_TVSYNCFLIP_PARITY	(0x1<<9)
67 #define OCMD_TVSYNCFLIP_ENABLE	(0x1<<7)
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)
79 
80 /* OCONFIG register */
81 #define OCONF_PIPE_MASK		(0x1<<18)
82 #define OCONF_PIPE_A		(0x0<<18)
83 #define OCONF_PIPE_B		(0x1<<18)
84 #define OCONF_GAMMA2_ENABLE	(0x1<<16)
85 #define OCONF_CSC_MODE_BT601	(0x0<<5)
86 #define OCONF_CSC_MODE_BT709	(0x1<<5)
87 #define OCONF_CSC_BYPASS	(0x1<<4)
88 #define OCONF_CC_OUT_8BIT	(0x1<<3)
89 #define OCONF_TEST_MODE		(0x1<<2)
90 #define OCONF_THREE_LINE_BUFFER	(0x1<<0)
91 #define OCONF_TWO_LINE_BUFFER	(0x0<<0)
92 
93 /* DCLRKM (dst-key) register */
94 #define DST_KEY_ENABLE		(0x1<<31)
95 #define CLK_RGB24_MASK		0x0
96 #define CLK_RGB16_MASK		0x070307
97 #define CLK_RGB15_MASK		0x070707
98 #define CLK_RGB8I_MASK		0xffffff
99 
100 #define RGB16_TO_COLORKEY(c) \
101 	(((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
102 #define RGB15_TO_COLORKEY(c) \
103 	(((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
104 
105 /* overlay flip addr flag */
106 #define OFC_UPDATE		0x1
107 
108 /* polyphase filter coefficients */
109 #define N_HORIZ_Y_TAPS          5
110 #define N_VERT_Y_TAPS           3
111 #define N_HORIZ_UV_TAPS         3
112 #define N_VERT_UV_TAPS          3
113 #define N_PHASES                17
114 #define MAX_TAPS                5
115 
116 /* memory bufferd overlay registers */
117 struct overlay_registers {
118 	u32 OBUF_0Y;
119 	u32 OBUF_1Y;
120 	u32 OBUF_0U;
121 	u32 OBUF_0V;
122 	u32 OBUF_1U;
123 	u32 OBUF_1V;
124 	u32 OSTRIDE;
125 	u32 YRGB_VPH;
126 	u32 UV_VPH;
127 	u32 HORZ_PH;
128 	u32 INIT_PHS;
129 	u32 DWINPOS;
130 	u32 DWINSZ;
131 	u32 SWIDTH;
132 	u32 SWIDTHSW;
133 	u32 SHEIGHT;
134 	u32 YRGBSCALE;
135 	u32 UVSCALE;
136 	u32 OCLRC0;
137 	u32 OCLRC1;
138 	u32 DCLRKV;
139 	u32 DCLRKM;
140 	u32 SCLRKVH;
141 	u32 SCLRKVL;
142 	u32 SCLRKEN;
143 	u32 OCONFIG;
144 	u32 OCMD;
145 	u32 RESERVED1; /* 0x6C */
146 	u32 OSTART_0Y;
147 	u32 OSTART_1Y;
148 	u32 OSTART_0U;
149 	u32 OSTART_0V;
150 	u32 OSTART_1U;
151 	u32 OSTART_1V;
152 	u32 OTILEOFF_0Y;
153 	u32 OTILEOFF_1Y;
154 	u32 OTILEOFF_0U;
155 	u32 OTILEOFF_0V;
156 	u32 OTILEOFF_1U;
157 	u32 OTILEOFF_1V;
158 	u32 FASTHSCALE; /* 0xA0 */
159 	u32 UVSCALEV; /* 0xA4 */
160 	u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
161 	u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
162 	u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
163 	u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
164 	u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
165 	u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
166 	u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
167 	u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
168 	u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
169 };
170 
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;
176 	int active;
177 	int pfit_active;
178 	u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
179 	u32 color_key;
180 	u32 brightness, contrast, saturation;
181 	u32 old_xscale, old_yscale;
182 	/* register access */
183 	u32 flip_addr;
184 	struct drm_i915_gem_object *reg_bo;
185 	/* flip handling */
186 	uint32_t last_flip_req;
187 	void (*flip_tail)(struct intel_overlay *);
188 };
189 
190 static struct overlay_registers *
191 intel_overlay_map_regs(struct intel_overlay *overlay)
192 {
193 	struct overlay_registers *regs;
194 
195 	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) {
196 		regs = overlay->reg_bo->phys_obj->handle->vaddr;
197 	} else {
198 		regs = pmap_mapdev_attr(overlay->dev->agp->base +
199 		    overlay->reg_bo->gtt_offset, PAGE_SIZE,
200 		    PAT_WRITE_COMBINING);
201 	}
202 	return (regs);
203 }
204 
205 static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
206 				     struct overlay_registers *regs)
207 {
208 	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
209 		pmap_unmapdev((vm_offset_t)regs, PAGE_SIZE);
210 }
211 
212 static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
213 					 void (*tail)(struct intel_overlay *))
214 {
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];
218 	int ret;
219 
220 	BUG_ON(overlay->last_flip_req);
221 	ret = i915_add_request(ring, NULL, &overlay->last_flip_req);
222 	if (ret)
223 		return ret;
224 
225 	overlay->flip_tail = tail;
226 	ret = i915_wait_seqno(ring, overlay->last_flip_req);
227 	if (ret)
228 		return ret;
229 	i915_gem_retire_requests(dev);
230 
231 	overlay->last_flip_req = 0;
232 	return 0;
233 }
234 
235 /* overlay needs to be disable in OCMD reg */
236 static int intel_overlay_on(struct intel_overlay *overlay)
237 {
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];
241 	int ret;
242 
243 	BUG_ON(overlay->active);
244 	overlay->active = 1;
245 
246 	WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE));
247 
248 	ret = intel_ring_begin(ring, 4);
249 	if (ret)
250 		return ret;
251 
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);
257 
258 	return intel_overlay_do_wait_request(overlay, NULL);
259 }
260 
261 /* overlay needs to be enabled in OCMD reg */
262 static int intel_overlay_continue(struct intel_overlay *overlay,
263 				  bool load_polyphase_filter)
264 {
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;
269 	u32 tmp;
270 	int ret;
271 
272 	BUG_ON(!overlay->active);
273 
274 	if (load_polyphase_filter)
275 		flip_addr |= OFC_UPDATE;
276 
277 	/* check for underruns */
278 	tmp = I915_READ(DOVSTA);
279 	if (tmp & (1 << 17))
280 		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
281 
282 	ret = intel_ring_begin(ring, 2);
283 	if (ret)
284 		return ret;
285 
286 	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
287 	intel_ring_emit(ring, flip_addr);
288 	intel_ring_advance(ring);
289 
290 	return i915_add_request(ring, NULL, &overlay->last_flip_req);
291 }
292 
293 static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
294 {
295 	struct drm_i915_gem_object *obj = overlay->old_vid_bo;
296 
297 	i915_gem_object_unpin(obj);
298 	drm_gem_object_unreference(&obj->base);
299 
300 	overlay->old_vid_bo = NULL;
301 }
302 
303 static void intel_overlay_off_tail(struct intel_overlay *overlay)
304 {
305 	struct drm_i915_gem_object *obj = overlay->vid_bo;
306 
307 	/* never have the overlay hw on without showing a frame */
308 	KASSERT(overlay->vid_bo != NULL, ("No vid_bo"));
309 
310 	i915_gem_object_unpin(obj);
311 	drm_gem_object_unreference(&obj->base);
312 	overlay->vid_bo = NULL;
313 
314 	overlay->crtc->overlay = NULL;
315 	overlay->crtc = NULL;
316 	overlay->active = 0;
317 }
318 
319 /* overlay needs to be disabled in OCMD reg */
320 static int intel_overlay_off(struct intel_overlay *overlay)
321 {
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;
326 	int ret;
327 
328 	BUG_ON(!overlay->active);
329 
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;
335 
336 	ret = intel_ring_begin(ring, 6);
337 	if (ret)
338 		return ret;
339 
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 */
345 	if (IS_I830(dev)) {
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);
351 	} else {
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);
355 	}
356 	intel_ring_advance(ring);
357 
358 	return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
359 }
360 
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)
364 {
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];
368 	int ret;
369 
370 	if (overlay->last_flip_req == 0)
371 		return 0;
372 
373 	ret = i915_wait_seqno(ring, overlay->last_flip_req);
374 	if (ret)
375 		return ret;
376 	i915_gem_retire_requests(dev);
377 
378 	if (overlay->flip_tail)
379 		overlay->flip_tail(overlay);
380 
381 	overlay->last_flip_req = 0;
382 	return 0;
383 }
384 
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
388  */
389 static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
390 {
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];
394 	int ret;
395 
396 	/* Only wait if there is actually an old frame to release to
397 	 * guarantee forward progress.
398 	 */
399 	if (!overlay->old_vid_bo)
400 		return 0;
401 
402 	if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
403 		/* synchronous slowpath */
404 		ret = intel_ring_begin(ring, 2);
405 		if (ret)
406 			return ret;
407 
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);
411 
412 		ret = intel_overlay_do_wait_request(overlay,
413 						    intel_overlay_release_old_vid_tail);
414 		if (ret)
415 			return ret;
416 	}
417 
418 	intel_overlay_release_old_vid_tail(overlay);
419 	return 0;
420 }
421 
422 struct put_image_params {
423 	int format;
424 	short dst_x;
425 	short dst_y;
426 	short dst_w;
427 	short dst_h;
428 	short src_w;
429 	short src_scan_h;
430 	short src_scan_w;
431 	short src_h;
432 	short stride_Y;
433 	short stride_UV;
434 	int offset_Y;
435 	int offset_U;
436 	int offset_V;
437 };
438 
439 static int packed_depth_bytes(u32 format)
440 {
441 	switch (format & I915_OVERLAY_DEPTH_MASK) {
442 	case I915_OVERLAY_YUV422:
443 		return 4;
444 	case I915_OVERLAY_YUV411:
445 		/* return 6; not implemented */
446 	default:
447 		return -EINVAL;
448 	}
449 }
450 
451 static int packed_width_bytes(u32 format, short width)
452 {
453 	switch (format & I915_OVERLAY_DEPTH_MASK) {
454 	case I915_OVERLAY_YUV422:
455 		return width << 1;
456 	default:
457 		return -EINVAL;
458 	}
459 }
460 
461 static int uv_hsubsampling(u32 format)
462 {
463 	switch (format & I915_OVERLAY_DEPTH_MASK) {
464 	case I915_OVERLAY_YUV422:
465 	case I915_OVERLAY_YUV420:
466 		return 2;
467 	case I915_OVERLAY_YUV411:
468 	case I915_OVERLAY_YUV410:
469 		return 4;
470 	default:
471 		return -EINVAL;
472 	}
473 }
474 
475 static int uv_vsubsampling(u32 format)
476 {
477 	switch (format & I915_OVERLAY_DEPTH_MASK) {
478 	case I915_OVERLAY_YUV420:
479 	case I915_OVERLAY_YUV410:
480 		return 2;
481 	case I915_OVERLAY_YUV422:
482 	case I915_OVERLAY_YUV411:
483 		return 1;
484 	default:
485 		return -EINVAL;
486 	}
487 }
488 
489 static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
490 {
491 	u32 mask, shift, ret;
492 	if (IS_GEN2(dev)) {
493 		mask = 0x1f;
494 		shift = 5;
495 	} else {
496 		mask = 0x3f;
497 		shift = 6;
498 	}
499 	ret = ((offset + width + mask) >> shift) - (offset >> shift);
500 	if (!IS_GEN2(dev))
501 		ret <<= 1;
502 	ret -= 1;
503 	return ret << 2;
504 }
505 
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
524 };
525 
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
536 };
537 
538 static void update_polyphase_filter(struct overlay_registers *regs)
539 {
540 	memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
541 	memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
542 }
543 
544 static bool update_scaling_factors(struct intel_overlay *overlay,
545 				   struct overlay_registers *regs,
546 				   struct put_image_params *params)
547 {
548 	/* fixed point with a 12 bit shift */
549 	u32 xscale, yscale, xscale_UV, yscale_UV;
550 #define FP_SHIFT 12
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);
555 
556 	if (params->dst_w > 1)
557 		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
558 			/(params->dst_w);
559 	else
560 		xscale = 1 << FP_SHIFT;
561 
562 	if (params->dst_h > 1)
563 		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
564 			/(params->dst_h);
565 	else
566 		yscale = 1 << FP_SHIFT;
567 
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;
574 	/*} else {
575 	  xscale_UV = 0;
576 	  yscale_UV = 0;
577 	  }*/
578 
579 	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
580 		scale_changed = true;
581 	overlay->old_xscale = xscale;
582 	overlay->old_yscale = yscale;
583 
584 	regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) |
585 			   ((xscale >> FP_SHIFT)  << 16) |
586 			   ((xscale & FRACT_MASK) << 3));
587 
588 	regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) |
589 			 ((xscale_UV >> FP_SHIFT)  << 16) |
590 			 ((xscale_UV & FRACT_MASK) << 3));
591 
592 	regs->UVSCALEV = ((((yscale    >> FP_SHIFT) << 16) |
593 			   ((yscale_UV >> FP_SHIFT) << 0)));
594 
595 	if (scale_changed)
596 		update_polyphase_filter(regs);
597 
598 	return scale_changed;
599 }
600 
601 static void update_colorkey(struct intel_overlay *overlay,
602 			    struct overlay_registers *regs)
603 {
604 	u32 key = overlay->color_key;
605 
606 	switch (overlay->crtc->base.fb->bits_per_pixel) {
607 	case 8:
608 		regs->DCLRKV = 0;
609 		regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
610 		break;
611 
612 	case 16:
613 		if (overlay->crtc->base.fb->depth == 15) {
614 			regs->DCLRKV = RGB15_TO_COLORKEY(key);
615 			regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
616 		} else {
617 			regs->DCLRKV = RGB16_TO_COLORKEY(key);
618 			regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
619 		}
620 		break;
621 
622 	case 24:
623 	case 32:
624 		regs->DCLRKV = key;
625 		regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
626 		break;
627 	}
628 }
629 
630 static u32 overlay_cmd_reg(struct put_image_params *params)
631 {
632 	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
633 
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;
638 			break;
639 		case I915_OVERLAY_YUV420:
640 			cmd |= OCMD_YUV_420_PLANAR;
641 			break;
642 		case I915_OVERLAY_YUV411:
643 		case I915_OVERLAY_YUV410:
644 			cmd |= OCMD_YUV_410_PLANAR;
645 			break;
646 		}
647 	} else { /* YUV packed */
648 		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
649 		case I915_OVERLAY_YUV422:
650 			cmd |= OCMD_YUV_422_PACKED;
651 			break;
652 		case I915_OVERLAY_YUV411:
653 			cmd |= OCMD_YUV_411_PACKED;
654 			break;
655 		}
656 
657 		switch (params->format & I915_OVERLAY_SWAP_MASK) {
658 		case I915_OVERLAY_NO_SWAP:
659 			break;
660 		case I915_OVERLAY_UV_SWAP:
661 			cmd |= OCMD_UV_SWAP;
662 			break;
663 		case I915_OVERLAY_Y_SWAP:
664 			cmd |= OCMD_Y_SWAP;
665 			break;
666 		case I915_OVERLAY_Y_AND_UV_SWAP:
667 			cmd |= OCMD_Y_AND_UV_SWAP;
668 			break;
669 		}
670 	}
671 
672 	return cmd;
673 }
674 
675 static u32
676 max_u32(u32 a, u32 b)
677 {
678 
679 	return (a > b ? a : b);
680 }
681 
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)
685 {
686 	int ret, tmp_width;
687 	struct overlay_registers *regs;
688 	bool scale_changed = false;
689 
690 	KASSERT(overlay != NULL, ("No overlay ?"));
691 	DRM_LOCK_ASSERT(overlay->dev);
692 
693 	ret = intel_overlay_release_old_vid(overlay);
694 	if (ret != 0)
695 		return ret;
696 
697 	ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL);
698 	if (ret != 0)
699 		goto out_unpin;
700 
701 	ret = i915_gem_object_put_fence(new_bo);
702 	if (ret)
703 		goto out_unpin;
704 
705 	if (!overlay->active) {
706 		regs = intel_overlay_map_regs(overlay);
707 		if (!regs) {
708 			ret = -ENOMEM;
709 			goto out_unpin;
710 		}
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);
717 
718 		ret = intel_overlay_on(overlay);
719 		if (ret != 0)
720 			goto out_unpin;
721 	}
722 
723 	regs = intel_overlay_map_regs(overlay);
724 	if (!regs) {
725 		ret = -ENOMEM;
726 		goto out_unpin;
727 	}
728 
729 	regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
730 	regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
731 
732 	if (params->format & I915_OVERLAY_YUV_PACKED)
733 		tmp_width = packed_width_bytes(params->format, params->src_w);
734 	else
735 		tmp_width = params->src_w;
736 
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;
743 
744 	if (params->format & I915_OVERLAY_YUV_PLANAR) {
745 		int uv_hscale = uv_hsubsampling(params->format);
746 		int uv_vscale = uv_vsubsampling(params->format);
747 		u32 tmp_U, tmp_V;
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;
758 	}
759 
760 	scale_changed = update_scaling_factors(overlay, regs, params);
761 
762 	update_colorkey(overlay, regs);
763 
764 	regs->OCMD = overlay_cmd_reg(params);
765 
766 	intel_overlay_unmap_regs(overlay, regs);
767 
768 	ret = intel_overlay_continue(overlay, scale_changed);
769 	if (ret)
770 		goto out_unpin;
771 
772 	overlay->old_vid_bo = overlay->vid_bo;
773 	overlay->vid_bo = new_bo;
774 
775 	return 0;
776 
777 out_unpin:
778 	i915_gem_object_unpin(new_bo);
779 	return ret;
780 }
781 
782 int intel_overlay_switch_off(struct intel_overlay *overlay)
783 {
784 	struct overlay_registers *regs;
785 	int ret;
786 
787 	DRM_LOCK_ASSERT(overlay->dev);
788 
789 	ret = intel_overlay_recover_from_interrupt(overlay);
790 	if (ret != 0)
791 		return ret;
792 
793 	if (!overlay->active)
794 		return 0;
795 
796 	ret = intel_overlay_release_old_vid(overlay);
797 	if (ret != 0)
798 		return ret;
799 
800 	regs = intel_overlay_map_regs(overlay);
801 	regs->OCMD = 0;
802 	intel_overlay_unmap_regs(overlay, regs);
803 
804 	ret = intel_overlay_off(overlay);
805 	if (ret != 0)
806 		return ret;
807 
808 	intel_overlay_off_tail(overlay);
809 	return 0;
810 }
811 
812 static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
813 					  struct intel_crtc *crtc)
814 {
815 	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
816 
817 	if (!crtc->active)
818 		return -EINVAL;
819 
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)
823 		return -EINVAL;
824 
825 	return 0;
826 }
827 
828 static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
829 {
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);
833 	u32 ratio;
834 
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
837 	 */
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;
841 	} else {
842 		if (pfit_control & VERT_AUTO_SCALE)
843 			ratio = I915_READ(PFIT_AUTO_RATIOS);
844 		else
845 			ratio = I915_READ(PFIT_PGM_RATIOS);
846 		ratio >>= PFIT_VERT_SCALE_SHIFT;
847 	}
848 
849 	overlay->pfit_vscale_ratio = ratio;
850 }
851 
852 static int check_overlay_dst(struct intel_overlay *overlay,
853 			     struct drm_intel_overlay_put_image *rec)
854 {
855 	struct drm_display_mode *mode = &overlay->crtc->base.mode;
856 
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)
861 		return 0;
862 	else
863 		return -EINVAL;
864 }
865 
866 static int check_overlay_scaling(struct put_image_params *rec)
867 {
868 	u32 tmp;
869 
870 	/* downscaling limit is 8.0 */
871 	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
872 	if (tmp > 7)
873 		return -EINVAL;
874 	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
875 	if (tmp > 7)
876 		return -EINVAL;
877 
878 	return 0;
879 }
880 
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)
884 {
885 	int uv_hscale = uv_hsubsampling(rec->flags);
886 	int uv_vscale = uv_vsubsampling(rec->flags);
887 	u32 stride_mask;
888 	int depth;
889 	u32 tmp;
890 
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)
895 			return -EINVAL;
896 	} else {
897 		if (rec->src_height > IMAGE_MAX_HEIGHT ||
898 		    rec->src_width  > IMAGE_MAX_WIDTH)
899 			return -EINVAL;
900 	}
901 
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)
905 		return -EINVAL;
906 
907 	/* check alignment constraints */
908 	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
909 	case I915_OVERLAY_RGB:
910 		/* not implemented */
911 		return -EINVAL;
912 
913 	case I915_OVERLAY_YUV_PACKED:
914 		if (uv_vscale != 1)
915 			return -EINVAL;
916 
917 		depth = packed_depth_bytes(rec->flags);
918 		if (depth < 0)
919 			return depth;
920 
921 		/* ignore UV planes */
922 		rec->stride_UV = 0;
923 		rec->offset_U = 0;
924 		rec->offset_V = 0;
925 		/* check pixel alignment */
926 		if (rec->offset_Y % depth)
927 			return -EINVAL;
928 		break;
929 
930 	case I915_OVERLAY_YUV_PLANAR:
931 		if (uv_vscale < 0 || uv_hscale < 0)
932 			return -EINVAL;
933 		/* no offset restrictions for planar formats */
934 		break;
935 
936 	default:
937 		return -EINVAL;
938 	}
939 
940 	if (rec->src_width % uv_hscale)
941 		return -EINVAL;
942 
943 	/* stride checking */
944 	if (IS_I830(dev) || IS_845G(dev))
945 		stride_mask = 255;
946 	else
947 		stride_mask = 63;
948 
949 	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
950 		return -EINVAL;
951 	if (IS_GEN4(dev) && rec->stride_Y < 512)
952 		return -EINVAL;
953 
954 	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
955 		4096 : 8192;
956 	if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
957 		return -EINVAL;
958 
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)
965 			return -EINVAL;
966 
967 		tmp = rec->stride_Y*rec->src_height;
968 		if (rec->offset_Y + tmp > new_bo->base.size)
969 			return -EINVAL;
970 		break;
971 
972 	case I915_OVERLAY_YUV_PLANAR:
973 		if (rec->src_width > rec->stride_Y)
974 			return -EINVAL;
975 		if (rec->src_width/uv_hscale > rec->stride_UV)
976 			return -EINVAL;
977 
978 		tmp = rec->stride_Y * rec->src_height;
979 		if (rec->offset_Y + tmp > new_bo->base.size)
980 			return -EINVAL;
981 
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)
985 			return -EINVAL;
986 		break;
987 	}
988 
989 	return 0;
990 }
991 
992 /**
993  * Return the pipe currently connected to the panel fitter,
994  * or -1 if the panel fitter is not present or not in use
995  */
996 static int intel_panel_fitter_pipe(struct drm_device *dev)
997 {
998 	struct drm_i915_private *dev_priv = dev->dev_private;
999 	u32  pfit_control;
1000 
1001 	/* i830 doesn't have a panel fitter */
1002 	if (IS_I830(dev))
1003 		return -1;
1004 
1005 	pfit_control = I915_READ(PFIT_CONTROL);
1006 
1007 	/* See if the panel fitter is in use */
1008 	if ((pfit_control & PFIT_ENABLE) == 0)
1009 		return -1;
1010 
1011 	/* 965 can place panel fitter on either pipe */
1012 	if (IS_GEN4(dev))
1013 		return (pfit_control >> 29) & 0x3;
1014 
1015 	/* older chips can only use pipe 1 */
1016 	return 1;
1017 }
1018 
1019 int intel_overlay_put_image(struct drm_device *dev, void *data,
1020 			    struct drm_file *file_priv)
1021 {
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;
1029 	int ret;
1030 
1031 	if (!dev_priv) {
1032 		DRM_ERROR("called with no initialization\n");
1033 		return -EINVAL;
1034 	}
1035 
1036 	overlay = dev_priv->overlay;
1037 	if (!overlay) {
1038 		DRM_DEBUG("userspace bug: no overlay\n");
1039 		return -ENODEV;
1040 	}
1041 
1042 	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
1043 		lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
1044 		DRM_LOCK(dev);
1045 
1046 		ret = intel_overlay_switch_off(overlay);
1047 
1048 		DRM_UNLOCK(dev);
1049 		lockmgr(&dev->mode_config.mutex, LK_RELEASE);
1050 
1051 		return ret;
1052 	}
1053 
1054 	params = kmalloc(sizeof(struct put_image_params), DRM_I915_GEM,
1055 	    M_WAITOK | M_ZERO);
1056 
1057 	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
1058 					   DRM_MODE_OBJECT_CRTC);
1059 	if (!drmmode_obj) {
1060 		ret = -ENOENT;
1061 		goto out_free;
1062 	}
1063 	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
1064 
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) {
1068 		ret = -ENOENT;
1069 		goto out_free;
1070 	}
1071 
1072 	lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
1073 	DRM_LOCK(dev);
1074 
1075 	if (new_bo->tiling_mode) {
1076 		DRM_ERROR("buffer used for overlay image can not be tiled\n");
1077 		ret = -EINVAL;
1078 		goto out_unlock;
1079 	}
1080 
1081 	ret = intel_overlay_recover_from_interrupt(overlay);
1082 	if (ret != 0)
1083 		goto out_unlock;
1084 
1085 	if (overlay->crtc != crtc) {
1086 		struct drm_display_mode *mode = &crtc->base.mode;
1087 		ret = intel_overlay_switch_off(overlay);
1088 		if (ret != 0)
1089 			goto out_unlock;
1090 
1091 		ret = check_overlay_possible_on_crtc(overlay, crtc);
1092 		if (ret != 0)
1093 			goto out_unlock;
1094 
1095 		overlay->crtc = crtc;
1096 		crtc->overlay = overlay;
1097 
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);
1103 		} else
1104 			overlay->pfit_active = 0;
1105 	}
1106 
1107 	ret = check_overlay_dst(overlay, put_image_rec);
1108 	if (ret != 0)
1109 		goto out_unlock;
1110 
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;
1117 	} else {
1118 		params->dst_y = put_image_rec->dst_y;
1119 		params->dst_h = put_image_rec->dst_height;
1120 	}
1121 	params->dst_x = put_image_rec->dst_x;
1122 	params->dst_w = put_image_rec->dst_width;
1123 
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) {
1130 		ret = -EINVAL;
1131 		goto out_unlock;
1132 	}
1133 
1134 	ret = check_overlay_src(dev, put_image_rec, new_bo);
1135 	if (ret != 0)
1136 		goto out_unlock;
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;
1143 
1144 	/* Check scaling after src size to prevent a divide-by-zero. */
1145 	ret = check_overlay_scaling(params);
1146 	if (ret != 0)
1147 		goto out_unlock;
1148 
1149 	ret = intel_overlay_do_put_image(overlay, new_bo, params);
1150 	if (ret != 0)
1151 		goto out_unlock;
1152 
1153 	DRM_UNLOCK(dev);
1154 	lockmgr(&dev->mode_config.mutex, LK_RELEASE);
1155 
1156 	drm_free(params, DRM_I915_GEM);
1157 
1158 	return 0;
1159 
1160 out_unlock:
1161 	DRM_UNLOCK(dev);
1162 	lockmgr(&dev->mode_config.mutex, LK_RELEASE);
1163 	drm_gem_object_unreference_unlocked(&new_bo->base);
1164 out_free:
1165 	drm_free(params, DRM_I915_GEM);
1166 
1167 	return ret;
1168 }
1169 
1170 static void update_reg_attrs(struct intel_overlay *overlay,
1171 			     struct overlay_registers *regs)
1172 {
1173 	regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
1174 	regs->OCLRC1 = overlay->saturation;
1175 }
1176 
1177 static bool check_gamma_bounds(u32 gamma1, u32 gamma2)
1178 {
1179 	int i;
1180 
1181 	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
1182 		return false;
1183 
1184 	for (i = 0; i < 3; i++) {
1185 		if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
1186 			return false;
1187 	}
1188 
1189 	return true;
1190 }
1191 
1192 static bool check_gamma5_errata(u32 gamma5)
1193 {
1194 	int i;
1195 
1196 	for (i = 0; i < 3; i++) {
1197 		if (((gamma5 >> i*8) & 0xff) == 0x80)
1198 			return false;
1199 	}
1200 
1201 	return true;
1202 }
1203 
1204 static int check_gamma(struct drm_intel_overlay_attrs *attrs)
1205 {
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))
1213 		return -EINVAL;
1214 
1215 	if (!check_gamma5_errata(attrs->gamma5))
1216 		return -EINVAL;
1217 
1218 	return 0;
1219 }
1220 
1221 int intel_overlay_attrs(struct drm_device *dev, void *data,
1222 			struct drm_file *file_priv)
1223 {
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;
1228 	int ret;
1229 
1230 	if (!dev_priv) {
1231 		DRM_ERROR("called with no initialization\n");
1232 		return -EINVAL;
1233 	}
1234 
1235 	overlay = dev_priv->overlay;
1236 	if (!overlay) {
1237 		DRM_DEBUG("userspace bug: no overlay\n");
1238 		return -ENODEV;
1239 	}
1240 
1241 	lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
1242 	DRM_LOCK(dev);
1243 
1244 	ret = -EINVAL;
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;
1250 
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);
1258 		}
1259 	} else {
1260 		if (attrs->brightness < -128 || attrs->brightness > 127)
1261 			goto out_unlock;
1262 		if (attrs->contrast > 255)
1263 			goto out_unlock;
1264 		if (attrs->saturation > 1023)
1265 			goto out_unlock;
1266 
1267 		overlay->color_key  = attrs->color_key;
1268 		overlay->brightness = attrs->brightness;
1269 		overlay->contrast   = attrs->contrast;
1270 		overlay->saturation = attrs->saturation;
1271 
1272 		regs = intel_overlay_map_regs(overlay);
1273 		if (!regs) {
1274 			ret = -ENOMEM;
1275 			goto out_unlock;
1276 		}
1277 
1278 		update_reg_attrs(overlay, regs);
1279 
1280 		intel_overlay_unmap_regs(overlay, regs);
1281 
1282 		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
1283 			if (IS_GEN2(dev))
1284 				goto out_unlock;
1285 
1286 			if (overlay->active) {
1287 				ret = -EBUSY;
1288 				goto out_unlock;
1289 			}
1290 
1291 			ret = check_gamma(attrs);
1292 			if (ret)
1293 				goto out_unlock;
1294 
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);
1301 		}
1302 	}
1303 
1304 	ret = 0;
1305 out_unlock:
1306 	DRM_UNLOCK(dev);
1307 	lockmgr(&dev->mode_config.mutex, LK_RELEASE);
1308 
1309 	return ret;
1310 }
1311 
1312 void intel_setup_overlay(struct drm_device *dev)
1313 {
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;
1318 	int ret;
1319 
1320 	if (!HAS_OVERLAY(dev))
1321 		return;
1322 
1323 	overlay = kmalloc(sizeof(struct intel_overlay), DRM_I915_GEM,
1324 	    M_WAITOK | M_ZERO);
1325 	DRM_LOCK(dev);
1326 	if (dev_priv->overlay != NULL)
1327 		goto out_free;
1328 	overlay->dev = dev;
1329 
1330 	reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
1331 	if (!reg_bo)
1332 		goto out_free;
1333 	overlay->reg_bo = reg_bo;
1334 
1335 	if (OVERLAY_NEEDS_PHYSICAL(dev)) {
1336 		ret = i915_gem_attach_phys_object(dev, reg_bo,
1337 						  I915_GEM_PHYS_OVERLAY_REGS,
1338 						  PAGE_SIZE);
1339 		if (ret) {
1340 			DRM_ERROR("failed to attach phys overlay regs\n");
1341 			goto out_free_bo;
1342 		}
1343 		overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
1344 	} else {
1345 		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
1346 		if (ret) {
1347 			DRM_ERROR("failed to pin overlay register bo\n");
1348 			goto out_free_bo;
1349 		}
1350 		overlay->flip_addr = reg_bo->gtt_offset;
1351 
1352 		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
1353 		if (ret) {
1354 			DRM_ERROR("failed to move overlay register bo into the GTT\n");
1355 			goto out_unpin_bo;
1356 		}
1357 	}
1358 
1359 	/* init all values */
1360 	overlay->color_key = 0x0101fe;
1361 	overlay->brightness = -19;
1362 	overlay->contrast = 75;
1363 	overlay->saturation = 146;
1364 
1365 	regs = intel_overlay_map_regs(overlay);
1366 	if (!regs)
1367 		goto out_unpin_bo;
1368 
1369 	memset(regs, 0, sizeof(struct overlay_registers));
1370 	update_polyphase_filter(regs);
1371 	update_reg_attrs(overlay, regs);
1372 
1373 	intel_overlay_unmap_regs(overlay, regs);
1374 
1375 	dev_priv->overlay = overlay;
1376 	DRM_INFO("initialized overlay support\n");
1377 	DRM_UNLOCK(dev);
1378 	return;
1379 
1380 out_unpin_bo:
1381 	if (!OVERLAY_NEEDS_PHYSICAL(dev))
1382 		i915_gem_object_unpin(reg_bo);
1383 out_free_bo:
1384 	drm_gem_object_unreference(&reg_bo->base);
1385 out_free:
1386 	DRM_UNLOCK(dev);
1387 	drm_free(overlay, DRM_I915_GEM);
1388 	return;
1389 }
1390 
1391 void intel_cleanup_overlay(struct drm_device *dev)
1392 {
1393 	drm_i915_private_t *dev_priv = dev->dev_private;
1394 
1395 	if (!dev_priv->overlay)
1396 		return;
1397 
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"));
1402 
1403 	drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
1404 	drm_free(dev_priv->overlay, DRM_I915_GEM);
1405 }
1406 
1407 #ifdef CONFIG_DEBUG_FS
1408 #include <linux/seq_file.h>
1409 
1410 struct intel_overlay_error_state {
1411 	struct overlay_registers regs;
1412 	unsigned long base;
1413 	u32 dovsta;
1414 	u32 isr;
1415 };
1416 
1417 struct intel_overlay_error_state *
1418 intel_overlay_capture_error_state(struct drm_device *dev)
1419 {
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;
1424 
1425 	if (!overlay || !overlay->active)
1426 		return NULL;
1427 
1428 	error = kmalloc(sizeof(*error), DRM_I915_GEM, M_NOWAIT);
1429 	if (error == NULL)
1430 		return NULL;
1431 
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;
1436 	else
1437 		error->base = (long) overlay->reg_bo->gtt_offset;
1438 
1439 	regs = intel_overlay_map_regs(overlay);
1440 	if (!regs)
1441 		goto err;
1442 
1443 	memcpy(&error->regs, regs, sizeof(struct overlay_registers));
1444 	intel_overlay_unmap_regs(overlay, regs);
1445 
1446 	return (error);
1447 
1448 err:
1449 	drm_free(error, DRM_I915_GEM);
1450 	return (NULL);
1451 }
1452 
1453 void
1454 intel_overlay_print_error_state(struct sbuf *m,
1455     struct intel_overlay_error_state *error)
1456 {
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",
1460 	    error->base);
1461 
1462 #define P(x) sbuf_printf(m, "    " #x ":	0x%08x\n", error->regs.x)
1463 	P(OBUF_0Y);
1464 	P(OBUF_1Y);
1465 	P(OBUF_0U);
1466 	P(OBUF_0V);
1467 	P(OBUF_1U);
1468 	P(OBUF_1V);
1469 	P(OSTRIDE);
1470 	P(YRGB_VPH);
1471 	P(UV_VPH);
1472 	P(HORZ_PH);
1473 	P(INIT_PHS);
1474 	P(DWINPOS);
1475 	P(DWINSZ);
1476 	P(SWIDTH);
1477 	P(SWIDTHSW);
1478 	P(SHEIGHT);
1479 	P(YRGBSCALE);
1480 	P(UVSCALE);
1481 	P(OCLRC0);
1482 	P(OCLRC1);
1483 	P(DCLRKV);
1484 	P(DCLRKM);
1485 	P(SCLRKVH);
1486 	P(SCLRKVL);
1487 	P(SCLRKEN);
1488 	P(OCONFIG);
1489 	P(OCMD);
1490 	P(OSTART_0Y);
1491 	P(OSTART_1Y);
1492 	P(OSTART_0U);
1493 	P(OSTART_0V);
1494 	P(OSTART_1U);
1495 	P(OSTART_1V);
1496 	P(OTILEOFF_0Y);
1497 	P(OTILEOFF_1Y);
1498 	P(OTILEOFF_0U);
1499 	P(OTILEOFF_0V);
1500 	P(OTILEOFF_1U);
1501 	P(OTILEOFF_1V);
1502 	P(FASTHSCALE);
1503 	P(UVSCALEV);
1504 #undef P
1505 }
1506 #endif
1507