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