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