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