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