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