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