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