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