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