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: stable/9/sys/dev/drm2/i915/intel_overlay.c 235783 2012-05-22 11:07:44Z kib $");
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 *
intel_overlay_map_regs(struct intel_overlay * overlay)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 
intel_overlay_unmap_regs(struct intel_overlay * overlay,struct overlay_registers * regs)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 
intel_overlay_do_wait_request(struct intel_overlay * overlay,struct drm_i915_gem_request * request,void (* tail)(struct intel_overlay *))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
i830_activate_pipe_a(struct drm_device * dev)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
i830_deactivate_pipe_a(struct drm_device * dev)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 */
intel_overlay_on(struct intel_overlay * overlay)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 */
intel_overlay_continue(struct intel_overlay * overlay,bool load_polyphase_filter)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 
intel_overlay_release_old_vid_tail(struct intel_overlay * overlay)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 
intel_overlay_off_tail(struct intel_overlay * overlay)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 */
intel_overlay_off(struct intel_overlay * overlay)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. */
intel_overlay_recover_from_interrupt(struct intel_overlay * overlay)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  */
intel_overlay_release_old_vid(struct intel_overlay * overlay)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 
packed_depth_bytes(u32 format)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 
packed_width_bytes(u32 format,short width)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 
uv_hsubsampling(u32 format)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 
uv_vsubsampling(u32 format)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 
calc_swidthsw(struct drm_device * dev,u32 offset,u32 width)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 
update_polyphase_filter(struct overlay_registers * regs)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 
update_scaling_factors(struct intel_overlay * overlay,struct overlay_registers * regs,struct put_image_params * params)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 
update_colorkey(struct intel_overlay * overlay,struct overlay_registers * regs)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 
overlay_cmd_reg(struct put_image_params * params)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
max_u32(u32 a,u32 b)754 max_u32(u32 a, u32 b)
755 {
756 
757 	return (a > b ? a : b);
758 }
759 
intel_overlay_do_put_image(struct intel_overlay * overlay,struct drm_i915_gem_object * new_bo,struct put_image_params * params)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 
intel_overlay_switch_off(struct intel_overlay * overlay)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 
check_overlay_possible_on_crtc(struct intel_overlay * overlay,struct intel_crtc * crtc)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 
update_pfit_vscale_ratio(struct intel_overlay * overlay)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 
check_overlay_dst(struct intel_overlay * overlay,struct drm_intel_overlay_put_image * rec)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 
check_overlay_scaling(struct put_image_params * rec)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 
check_overlay_src(struct drm_device * dev,struct drm_intel_overlay_put_image * rec,struct drm_i915_gem_object * new_bo)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  */
intel_panel_fitter_pipe(struct drm_device * dev)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 
intel_overlay_put_image(struct drm_device * dev,void * data,struct drm_file * file_priv)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 
update_reg_attrs(struct intel_overlay * overlay,struct overlay_registers * regs)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 
check_gamma_bounds(u32 gamma1,u32 gamma2)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 
check_gamma5_errata(u32 gamma5)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 
check_gamma(struct drm_intel_overlay_attrs * attrs)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 
intel_overlay_attrs(struct drm_device * dev,void * data,struct drm_file * file_priv)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 
intel_setup_overlay(struct drm_device * dev)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 
intel_cleanup_overlay(struct drm_device * dev)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 *
intel_overlay_capture_error_state(struct drm_device * dev)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
intel_overlay_print_error_state(struct sbuf * m,struct intel_overlay_error_state * error)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 }
1583