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