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