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