intel_overlay.c revision 282199
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 282199 2015-04-28 19:35:05Z dumbbell $");
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
778	ret = intel_overlay_release_old_vid(overlay);
779	if (ret != 0)
780		return ret;
781
782	ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL);
783	if (ret != 0)
784		goto out_unpin;
785
786	ret = i915_gem_object_put_fence(new_bo);
787	if (ret)
788		goto out_unpin;
789
790	if (!overlay->active) {
791		u32 oconfig;
792		regs = intel_overlay_map_regs(overlay);
793		if (!regs) {
794			ret = -ENOMEM;
795			goto out_unpin;
796		}
797		oconfig = OCONF_CC_OUT_8BIT;
798		if (IS_GEN4(overlay->dev))
799			oconfig |= OCONF_CSC_MODE_BT709;
800		oconfig |= overlay->crtc->pipe == 0 ?
801			OCONF_PIPE_A : OCONF_PIPE_B;
802		regs->OCONFIG = oconfig;
803		intel_overlay_unmap_regs(overlay, regs);
804
805		ret = intel_overlay_on(overlay);
806		if (ret != 0)
807			goto out_unpin;
808	}
809
810	regs = intel_overlay_map_regs(overlay);
811	if (!regs) {
812		ret = -ENOMEM;
813		goto out_unpin;
814	}
815
816	regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
817	regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
818
819	if (params->format & I915_OVERLAY_YUV_PACKED)
820		tmp_width = packed_width_bytes(params->format, params->src_w);
821	else
822		tmp_width = params->src_w;
823
824	swidth = params->src_w;
825	swidthsw = calc_swidthsw(overlay->dev, params->offset_Y, tmp_width);
826	sheight = params->src_h;
827	regs->OBUF_0Y = new_bo->gtt_offset + params->offset_Y;
828	ostride = params->stride_Y;
829
830	if (params->format & I915_OVERLAY_YUV_PLANAR) {
831		int uv_hscale = uv_hsubsampling(params->format);
832		int uv_vscale = uv_vsubsampling(params->format);
833		u32 tmp_U, tmp_V;
834		swidth |= (params->src_w/uv_hscale) << 16;
835		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
836				      params->src_w/uv_hscale);
837		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
838				      params->src_w/uv_hscale);
839		swidthsw |= max_u32(tmp_U, tmp_V) << 16;
840		sheight |= (params->src_h/uv_vscale) << 16;
841		regs->OBUF_0U = new_bo->gtt_offset + params->offset_U;
842		regs->OBUF_0V = new_bo->gtt_offset + params->offset_V;
843		ostride |= params->stride_UV << 16;
844	}
845
846	regs->SWIDTH = swidth;
847	regs->SWIDTHSW = swidthsw;
848	regs->SHEIGHT = sheight;
849	regs->OSTRIDE = ostride;
850
851	scale_changed = update_scaling_factors(overlay, regs, params);
852
853	update_colorkey(overlay, regs);
854
855	regs->OCMD = overlay_cmd_reg(params);
856
857	intel_overlay_unmap_regs(overlay, regs);
858
859	ret = intel_overlay_continue(overlay, scale_changed);
860	if (ret)
861		goto out_unpin;
862
863	overlay->old_vid_bo = overlay->vid_bo;
864	overlay->vid_bo = new_bo;
865
866	return 0;
867
868out_unpin:
869	i915_gem_object_unpin(new_bo);
870	return ret;
871}
872
873int intel_overlay_switch_off(struct intel_overlay *overlay)
874{
875	struct overlay_registers *regs;
876	int ret;
877
878	DRM_LOCK_ASSERT(overlay->dev);
879
880	ret = intel_overlay_recover_from_interrupt(overlay);
881	if (ret != 0)
882		return ret;
883
884	if (!overlay->active)
885		return 0;
886
887	ret = intel_overlay_release_old_vid(overlay);
888	if (ret != 0)
889		return ret;
890
891	regs = intel_overlay_map_regs(overlay);
892	regs->OCMD = 0;
893	intel_overlay_unmap_regs(overlay, regs);
894
895	ret = intel_overlay_off(overlay);
896	if (ret != 0)
897		return ret;
898
899	intel_overlay_off_tail(overlay);
900	return 0;
901}
902
903static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
904					  struct intel_crtc *crtc)
905{
906	drm_i915_private_t *dev_priv = overlay->dev->dev_private;
907
908	if (!crtc->active)
909		return -EINVAL;
910
911	/* can't use the overlay with double wide pipe */
912	if (INTEL_INFO(overlay->dev)->gen < 4 &&
913	    (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE)
914		return -EINVAL;
915
916	return 0;
917}
918
919static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
920{
921	struct drm_device *dev = overlay->dev;
922	drm_i915_private_t *dev_priv = dev->dev_private;
923	u32 pfit_control = I915_READ(PFIT_CONTROL);
924	u32 ratio;
925
926	/* XXX: This is not the same logic as in the xorg driver, but more in
927	 * line with the intel documentation for the i965
928	 */
929	if (INTEL_INFO(dev)->gen >= 4) {
930		/* on i965 use the PGM reg to read out the autoscaler values */
931		ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
932	} else {
933		if (pfit_control & VERT_AUTO_SCALE)
934			ratio = I915_READ(PFIT_AUTO_RATIOS);
935		else
936			ratio = I915_READ(PFIT_PGM_RATIOS);
937		ratio >>= PFIT_VERT_SCALE_SHIFT;
938	}
939
940	overlay->pfit_vscale_ratio = ratio;
941}
942
943static int check_overlay_dst(struct intel_overlay *overlay,
944			     struct drm_intel_overlay_put_image *rec)
945{
946	struct drm_display_mode *mode = &overlay->crtc->base.mode;
947
948	if (rec->dst_x < mode->hdisplay &&
949	    rec->dst_x + rec->dst_width <= mode->hdisplay &&
950	    rec->dst_y < mode->vdisplay &&
951	    rec->dst_y + rec->dst_height <= mode->vdisplay)
952		return 0;
953	else
954		return -EINVAL;
955}
956
957static int check_overlay_scaling(struct put_image_params *rec)
958{
959	u32 tmp;
960
961	/* downscaling limit is 8.0 */
962	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
963	if (tmp > 7)
964		return -EINVAL;
965	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
966	if (tmp > 7)
967		return -EINVAL;
968
969	return 0;
970}
971
972static int check_overlay_src(struct drm_device *dev,
973			     struct drm_intel_overlay_put_image *rec,
974			     struct drm_i915_gem_object *new_bo)
975{
976	int uv_hscale = uv_hsubsampling(rec->flags);
977	int uv_vscale = uv_vsubsampling(rec->flags);
978	u32 stride_mask;
979	int depth;
980	u32 tmp;
981
982	/* check src dimensions */
983	if (IS_845G(dev) || IS_I830(dev)) {
984		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
985		    rec->src_width  > IMAGE_MAX_WIDTH_LEGACY)
986			return -EINVAL;
987	} else {
988		if (rec->src_height > IMAGE_MAX_HEIGHT ||
989		    rec->src_width  > IMAGE_MAX_WIDTH)
990			return -EINVAL;
991	}
992
993	/* better safe than sorry, use 4 as the maximal subsampling ratio */
994	if (rec->src_height < N_VERT_Y_TAPS*4 ||
995	    rec->src_width  < N_HORIZ_Y_TAPS*4)
996		return -EINVAL;
997
998	/* check alignment constraints */
999	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1000	case I915_OVERLAY_RGB:
1001		/* not implemented */
1002		return -EINVAL;
1003
1004	case I915_OVERLAY_YUV_PACKED:
1005		if (uv_vscale != 1)
1006			return -EINVAL;
1007
1008		depth = packed_depth_bytes(rec->flags);
1009		if (depth < 0)
1010			return depth;
1011
1012		/* ignore UV planes */
1013		rec->stride_UV = 0;
1014		rec->offset_U = 0;
1015		rec->offset_V = 0;
1016		/* check pixel alignment */
1017		if (rec->offset_Y % depth)
1018			return -EINVAL;
1019		break;
1020
1021	case I915_OVERLAY_YUV_PLANAR:
1022		if (uv_vscale < 0 || uv_hscale < 0)
1023			return -EINVAL;
1024		/* no offset restrictions for planar formats */
1025		break;
1026
1027	default:
1028		return -EINVAL;
1029	}
1030
1031	if (rec->src_width % uv_hscale)
1032		return -EINVAL;
1033
1034	/* stride checking */
1035	if (IS_I830(dev) || IS_845G(dev))
1036		stride_mask = 255;
1037	else
1038		stride_mask = 63;
1039
1040	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
1041		return -EINVAL;
1042	if (IS_GEN4(dev) && rec->stride_Y < 512)
1043		return -EINVAL;
1044
1045	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
1046		4096 : 8192;
1047	if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
1048		return -EINVAL;
1049
1050	/* check buffer dimensions */
1051	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1052	case I915_OVERLAY_RGB:
1053	case I915_OVERLAY_YUV_PACKED:
1054		/* always 4 Y values per depth pixels */
1055		if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
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		break;
1062
1063	case I915_OVERLAY_YUV_PLANAR:
1064		if (rec->src_width > rec->stride_Y)
1065			return -EINVAL;
1066		if (rec->src_width/uv_hscale > rec->stride_UV)
1067			return -EINVAL;
1068
1069		tmp = rec->stride_Y * rec->src_height;
1070		if (rec->offset_Y + tmp > new_bo->base.size)
1071			return -EINVAL;
1072
1073		tmp = rec->stride_UV * (rec->src_height / uv_vscale);
1074		if (rec->offset_U + tmp > new_bo->base.size ||
1075		    rec->offset_V + tmp > new_bo->base.size)
1076			return -EINVAL;
1077		break;
1078	}
1079
1080	return 0;
1081}
1082
1083/**
1084 * Return the pipe currently connected to the panel fitter,
1085 * or -1 if the panel fitter is not present or not in use
1086 */
1087static int intel_panel_fitter_pipe(struct drm_device *dev)
1088{
1089	struct drm_i915_private *dev_priv = dev->dev_private;
1090	u32  pfit_control;
1091
1092	/* i830 doesn't have a panel fitter */
1093	if (IS_I830(dev))
1094		return -1;
1095
1096	pfit_control = I915_READ(PFIT_CONTROL);
1097
1098	/* See if the panel fitter is in use */
1099	if ((pfit_control & PFIT_ENABLE) == 0)
1100		return -1;
1101
1102	/* 965 can place panel fitter on either pipe */
1103	if (IS_GEN4(dev))
1104		return (pfit_control >> 29) & 0x3;
1105
1106	/* older chips can only use pipe 1 */
1107	return 1;
1108}
1109
1110int intel_overlay_put_image(struct drm_device *dev, void *data,
1111			    struct drm_file *file_priv)
1112{
1113	struct drm_intel_overlay_put_image *put_image_rec = data;
1114	drm_i915_private_t *dev_priv = dev->dev_private;
1115	struct intel_overlay *overlay;
1116	struct drm_mode_object *drmmode_obj;
1117	struct intel_crtc *crtc;
1118	struct drm_i915_gem_object *new_bo;
1119	struct put_image_params *params;
1120	int ret;
1121
1122	/* No need to check for DRIVER_MODESET - we don't set it up then. */
1123	overlay = dev_priv->overlay;
1124	if (!overlay) {
1125		DRM_DEBUG("userspace bug: no overlay\n");
1126		return -ENODEV;
1127	}
1128
1129	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
1130		sx_xlock(&dev->mode_config.mutex);
1131		DRM_LOCK(dev);
1132
1133		ret = intel_overlay_switch_off(overlay);
1134
1135		DRM_UNLOCK(dev);
1136		sx_xunlock(&dev->mode_config.mutex);
1137
1138		return ret;
1139	}
1140
1141	params = malloc(sizeof(struct put_image_params), DRM_I915_GEM,
1142	    M_WAITOK | M_ZERO);
1143
1144	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
1145					   DRM_MODE_OBJECT_CRTC);
1146	if (!drmmode_obj) {
1147		ret = -ENOENT;
1148		goto out_free;
1149	}
1150	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
1151
1152	new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
1153						   put_image_rec->bo_handle));
1154	if (&new_bo->base == NULL) {
1155		ret = -ENOENT;
1156		goto out_free;
1157	}
1158
1159	sx_xlock(&dev->mode_config.mutex);
1160	DRM_LOCK(dev);
1161
1162	if (new_bo->tiling_mode) {
1163		DRM_ERROR("buffer used for overlay image can not be tiled\n");
1164		ret = -EINVAL;
1165		goto out_unlock;
1166	}
1167
1168	ret = intel_overlay_recover_from_interrupt(overlay);
1169	if (ret != 0)
1170		goto out_unlock;
1171
1172	if (overlay->crtc != crtc) {
1173		struct drm_display_mode *mode = &crtc->base.mode;
1174		ret = intel_overlay_switch_off(overlay);
1175		if (ret != 0)
1176			goto out_unlock;
1177
1178		ret = check_overlay_possible_on_crtc(overlay, crtc);
1179		if (ret != 0)
1180			goto out_unlock;
1181
1182		overlay->crtc = crtc;
1183		crtc->overlay = overlay;
1184
1185		/* line too wide, i.e. one-line-mode */
1186		if (mode->hdisplay > 1024 &&
1187		    intel_panel_fitter_pipe(dev) == crtc->pipe) {
1188			overlay->pfit_active = 1;
1189			update_pfit_vscale_ratio(overlay);
1190		} else
1191			overlay->pfit_active = 0;
1192	}
1193
1194	ret = check_overlay_dst(overlay, put_image_rec);
1195	if (ret != 0)
1196		goto out_unlock;
1197
1198	if (overlay->pfit_active) {
1199		params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
1200				 overlay->pfit_vscale_ratio);
1201		/* shifting right rounds downwards, so add 1 */
1202		params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
1203				 overlay->pfit_vscale_ratio) + 1;
1204	} else {
1205		params->dst_y = put_image_rec->dst_y;
1206		params->dst_h = put_image_rec->dst_height;
1207	}
1208	params->dst_x = put_image_rec->dst_x;
1209	params->dst_w = put_image_rec->dst_width;
1210
1211	params->src_w = put_image_rec->src_width;
1212	params->src_h = put_image_rec->src_height;
1213	params->src_scan_w = put_image_rec->src_scan_width;
1214	params->src_scan_h = put_image_rec->src_scan_height;
1215	if (params->src_scan_h > params->src_h ||
1216	    params->src_scan_w > params->src_w) {
1217		ret = -EINVAL;
1218		goto out_unlock;
1219	}
1220
1221	ret = check_overlay_src(dev, put_image_rec, new_bo);
1222	if (ret != 0)
1223		goto out_unlock;
1224	params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
1225	params->stride_Y = put_image_rec->stride_Y;
1226	params->stride_UV = put_image_rec->stride_UV;
1227	params->offset_Y = put_image_rec->offset_Y;
1228	params->offset_U = put_image_rec->offset_U;
1229	params->offset_V = put_image_rec->offset_V;
1230
1231	/* Check scaling after src size to prevent a divide-by-zero. */
1232	ret = check_overlay_scaling(params);
1233	if (ret != 0)
1234		goto out_unlock;
1235
1236	ret = intel_overlay_do_put_image(overlay, new_bo, params);
1237	if (ret != 0)
1238		goto out_unlock;
1239
1240	DRM_UNLOCK(dev);
1241	sx_xunlock(&dev->mode_config.mutex);
1242
1243	free(params, DRM_I915_GEM);
1244
1245	return 0;
1246
1247out_unlock:
1248	DRM_UNLOCK(dev);
1249	sx_xunlock(&dev->mode_config.mutex);
1250	drm_gem_object_unreference_unlocked(&new_bo->base);
1251out_free:
1252	free(params, DRM_I915_GEM);
1253
1254	return ret;
1255}
1256
1257static void update_reg_attrs(struct intel_overlay *overlay,
1258			     struct overlay_registers *regs)
1259{
1260	regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
1261	regs->OCLRC1 = overlay->saturation;
1262}
1263
1264static bool check_gamma_bounds(u32 gamma1, u32 gamma2)
1265{
1266	int i;
1267
1268	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
1269		return false;
1270
1271	for (i = 0; i < 3; i++) {
1272		if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
1273			return false;
1274	}
1275
1276	return true;
1277}
1278
1279static bool check_gamma5_errata(u32 gamma5)
1280{
1281	int i;
1282
1283	for (i = 0; i < 3; i++) {
1284		if (((gamma5 >> i*8) & 0xff) == 0x80)
1285			return false;
1286	}
1287
1288	return true;
1289}
1290
1291static int check_gamma(struct drm_intel_overlay_attrs *attrs)
1292{
1293	if (!check_gamma_bounds(0, attrs->gamma0) ||
1294	    !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1295	    !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1296	    !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1297	    !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1298	    !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1299	    !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
1300		return -EINVAL;
1301
1302	if (!check_gamma5_errata(attrs->gamma5))
1303		return -EINVAL;
1304
1305	return 0;
1306}
1307
1308int intel_overlay_attrs(struct drm_device *dev, void *data,
1309			struct drm_file *file_priv)
1310{
1311	struct drm_intel_overlay_attrs *attrs = data;
1312	drm_i915_private_t *dev_priv = dev->dev_private;
1313	struct intel_overlay *overlay;
1314	struct overlay_registers *regs;
1315	int ret;
1316
1317	/* No need to check for DRIVER_MODESET - we don't set it up then. */
1318	overlay = dev_priv->overlay;
1319	if (!overlay) {
1320		DRM_DEBUG("userspace bug: no overlay\n");
1321		return -ENODEV;
1322	}
1323
1324	sx_xlock(&dev->mode_config.mutex);
1325	DRM_LOCK(dev);
1326
1327	ret = -EINVAL;
1328	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
1329		attrs->color_key  = overlay->color_key;
1330		attrs->brightness = overlay->brightness;
1331		attrs->contrast   = overlay->contrast;
1332		attrs->saturation = overlay->saturation;
1333
1334		if (!IS_GEN2(dev)) {
1335			attrs->gamma0 = I915_READ(OGAMC0);
1336			attrs->gamma1 = I915_READ(OGAMC1);
1337			attrs->gamma2 = I915_READ(OGAMC2);
1338			attrs->gamma3 = I915_READ(OGAMC3);
1339			attrs->gamma4 = I915_READ(OGAMC4);
1340			attrs->gamma5 = I915_READ(OGAMC5);
1341		}
1342	} else {
1343		if (attrs->brightness < -128 || attrs->brightness > 127)
1344			goto out_unlock;
1345		if (attrs->contrast > 255)
1346			goto out_unlock;
1347		if (attrs->saturation > 1023)
1348			goto out_unlock;
1349
1350		overlay->color_key  = attrs->color_key;
1351		overlay->brightness = attrs->brightness;
1352		overlay->contrast   = attrs->contrast;
1353		overlay->saturation = attrs->saturation;
1354
1355		regs = intel_overlay_map_regs(overlay);
1356		if (!regs) {
1357			ret = -ENOMEM;
1358			goto out_unlock;
1359		}
1360
1361		update_reg_attrs(overlay, regs);
1362
1363		intel_overlay_unmap_regs(overlay, regs);
1364
1365		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
1366			if (IS_GEN2(dev))
1367				goto out_unlock;
1368
1369			if (overlay->active) {
1370				ret = -EBUSY;
1371				goto out_unlock;
1372			}
1373
1374			ret = check_gamma(attrs);
1375			if (ret)
1376				goto out_unlock;
1377
1378			I915_WRITE(OGAMC0, attrs->gamma0);
1379			I915_WRITE(OGAMC1, attrs->gamma1);
1380			I915_WRITE(OGAMC2, attrs->gamma2);
1381			I915_WRITE(OGAMC3, attrs->gamma3);
1382			I915_WRITE(OGAMC4, attrs->gamma4);
1383			I915_WRITE(OGAMC5, attrs->gamma5);
1384		}
1385	}
1386
1387	ret = 0;
1388out_unlock:
1389	DRM_UNLOCK(dev);
1390	sx_xunlock(&dev->mode_config.mutex);
1391
1392	return ret;
1393}
1394
1395void intel_setup_overlay(struct drm_device *dev)
1396{
1397	drm_i915_private_t *dev_priv = dev->dev_private;
1398	struct intel_overlay *overlay;
1399	struct drm_i915_gem_object *reg_bo;
1400	struct overlay_registers *regs;
1401	int ret;
1402
1403	if (!HAS_OVERLAY(dev))
1404		return;
1405
1406	overlay = malloc(sizeof(struct intel_overlay), DRM_I915_GEM,
1407	    M_WAITOK | M_ZERO);
1408	DRM_LOCK(dev);
1409	if (dev_priv->overlay != NULL)
1410		goto out_free;
1411	overlay->dev = dev;
1412
1413	reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
1414	if (!reg_bo)
1415		goto out_free;
1416	overlay->reg_bo = reg_bo;
1417
1418	if (OVERLAY_NEEDS_PHYSICAL(dev)) {
1419		ret = i915_gem_attach_phys_object(dev, reg_bo,
1420						  I915_GEM_PHYS_OVERLAY_REGS,
1421						  PAGE_SIZE);
1422		if (ret) {
1423			DRM_ERROR("failed to attach phys overlay regs\n");
1424			goto out_free_bo;
1425		}
1426		overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
1427	} else {
1428		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
1429		if (ret) {
1430			DRM_ERROR("failed to pin overlay register bo\n");
1431			goto out_free_bo;
1432		}
1433		overlay->flip_addr = reg_bo->gtt_offset;
1434
1435		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
1436		if (ret) {
1437			DRM_ERROR("failed to move overlay register bo into the GTT\n");
1438			goto out_unpin_bo;
1439		}
1440	}
1441
1442	/* init all values */
1443	overlay->color_key = 0x0101fe;
1444	overlay->brightness = -19;
1445	overlay->contrast = 75;
1446	overlay->saturation = 146;
1447
1448	regs = intel_overlay_map_regs(overlay);
1449	if (!regs)
1450		goto out_unpin_bo;
1451
1452	memset(regs, 0, sizeof(struct overlay_registers));
1453	update_polyphase_filter(regs);
1454	update_reg_attrs(overlay, regs);
1455
1456	intel_overlay_unmap_regs(overlay, regs);
1457
1458	dev_priv->overlay = overlay;
1459	DRM_UNLOCK(dev);
1460	DRM_INFO("initialized overlay support\n");
1461	return;
1462
1463out_unpin_bo:
1464	if (!OVERLAY_NEEDS_PHYSICAL(dev))
1465		i915_gem_object_unpin(reg_bo);
1466out_free_bo:
1467	drm_gem_object_unreference(&reg_bo->base);
1468out_free:
1469	DRM_UNLOCK(dev);
1470	free(overlay, DRM_I915_GEM);
1471	return;
1472}
1473
1474void intel_cleanup_overlay(struct drm_device *dev)
1475{
1476	drm_i915_private_t *dev_priv = dev->dev_private;
1477
1478	if (!dev_priv->overlay)
1479		return;
1480
1481	/* The bo's should be free'd by the generic code already.
1482	 * Furthermore modesetting teardown happens beforehand so the
1483	 * hardware should be off already */
1484	KASSERT(!dev_priv->overlay->active, ("Overlay still active"));
1485
1486	drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
1487	free(dev_priv->overlay, DRM_I915_GEM);
1488}
1489
1490struct intel_overlay_error_state {
1491	struct overlay_registers regs;
1492	unsigned long base;
1493	u32 dovsta;
1494	u32 isr;
1495};
1496
1497struct intel_overlay_error_state *
1498intel_overlay_capture_error_state(struct drm_device *dev)
1499{
1500	drm_i915_private_t *dev_priv = dev->dev_private;
1501	struct intel_overlay *overlay = dev_priv->overlay;
1502	struct intel_overlay_error_state *error;
1503	struct overlay_registers __iomem *regs;
1504
1505	if (!overlay || !overlay->active)
1506		return NULL;
1507
1508	error = malloc(sizeof(*error), DRM_I915_GEM, M_NOWAIT);
1509	if (error == NULL)
1510		return NULL;
1511
1512	error->dovsta = I915_READ(DOVSTA);
1513	error->isr = I915_READ(ISR);
1514	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1515		error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;
1516	else
1517		error->base = (long) overlay->reg_bo->gtt_offset;
1518
1519	regs = intel_overlay_map_regs(overlay);
1520	if (!regs)
1521		goto err;
1522
1523	memcpy(&error->regs, regs, sizeof(struct overlay_registers));
1524	intel_overlay_unmap_regs(overlay, regs);
1525
1526	return (error);
1527
1528err:
1529	free(error, DRM_I915_GEM);
1530	return (NULL);
1531}
1532
1533void
1534intel_overlay_print_error_state(struct sbuf *m,
1535    struct intel_overlay_error_state *error)
1536{
1537	sbuf_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
1538	    error->dovsta, error->isr);
1539	sbuf_printf(m, "  Register file at 0x%08lx:\n",
1540	    error->base);
1541
1542#define P(x) sbuf_printf(m, "    " #x ":	0x%08x\n", error->regs.x)
1543	P(OBUF_0Y);
1544	P(OBUF_1Y);
1545	P(OBUF_0U);
1546	P(OBUF_0V);
1547	P(OBUF_1U);
1548	P(OBUF_1V);
1549	P(OSTRIDE);
1550	P(YRGB_VPH);
1551	P(UV_VPH);
1552	P(HORZ_PH);
1553	P(INIT_PHS);
1554	P(DWINPOS);
1555	P(DWINSZ);
1556	P(SWIDTH);
1557	P(SWIDTHSW);
1558	P(SHEIGHT);
1559	P(YRGBSCALE);
1560	P(UVSCALE);
1561	P(OCLRC0);
1562	P(OCLRC1);
1563	P(DCLRKV);
1564	P(DCLRKM);
1565	P(SCLRKVH);
1566	P(SCLRKVL);
1567	P(SCLRKEN);
1568	P(OCONFIG);
1569	P(OCMD);
1570	P(OSTART_0Y);
1571	P(OSTART_1Y);
1572	P(OSTART_0U);
1573	P(OSTART_0V);
1574	P(OSTART_1U);
1575	P(OSTART_1V);
1576	P(OTILEOFF_0Y);
1577	P(OTILEOFF_1Y);
1578	P(OTILEOFF_0U);
1579	P(OTILEOFF_0V);
1580	P(OTILEOFF_1U);
1581	P(OTILEOFF_1V);
1582	P(FASTHSCALE);
1583	P(UVSCALEV);
1584#undef P
1585}
1586