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