intel_overlay.c 39.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * Copyright © 2009
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Authors:
 *    Daniel Vetter <daniel@ffwll.ch>
 *
 * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
 */
28 29
#include <drm/drmP.h>
#include <drm/i915_drm.h>
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_drv.h"

/* Limits for overlay size. According to intel doc, the real limits are:
 * Y width: 4095, UV width (planar): 2047, Y height: 2047,
 * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use
 * the mininum of both.  */
#define IMAGE_MAX_WIDTH		2048
#define IMAGE_MAX_HEIGHT	2046 /* 2 * 1023 */
/* on 830 and 845 these large limits result in the card hanging */
#define IMAGE_MAX_WIDTH_LEGACY	1024
#define IMAGE_MAX_HEIGHT_LEGACY	1088

/* overlay register definitions */
/* OCMD register */
#define OCMD_TILED_SURFACE	(0x1<<19)
#define OCMD_MIRROR_MASK	(0x3<<17)
#define OCMD_MIRROR_MODE	(0x3<<17)
#define OCMD_MIRROR_HORIZONTAL	(0x1<<17)
#define OCMD_MIRROR_VERTICAL	(0x2<<17)
#define OCMD_MIRROR_BOTH	(0x3<<17)
#define OCMD_BYTEORDER_MASK	(0x3<<14) /* zero for YUYV or FOURCC YUY2 */
#define OCMD_UV_SWAP		(0x1<<14) /* YVYU */
#define OCMD_Y_SWAP		(0x2<<14) /* UYVY or FOURCC UYVY */
#define OCMD_Y_AND_UV_SWAP	(0x3<<14) /* VYUY */
#define OCMD_SOURCE_FORMAT_MASK (0xf<<10)
#define OCMD_RGB_888		(0x1<<10) /* not in i965 Intel docs */
#define OCMD_RGB_555		(0x2<<10) /* not in i965 Intel docs */
#define OCMD_RGB_565		(0x3<<10) /* not in i965 Intel docs */
#define OCMD_YUV_422_PACKED	(0x8<<10)
#define OCMD_YUV_411_PACKED	(0x9<<10) /* not in i965 Intel docs */
#define OCMD_YUV_420_PLANAR	(0xc<<10)
#define OCMD_YUV_422_PLANAR	(0xd<<10)
#define OCMD_YUV_410_PLANAR	(0xe<<10) /* also 411 */
#define OCMD_TVSYNCFLIP_PARITY	(0x1<<9)
#define OCMD_TVSYNCFLIP_ENABLE	(0x1<<7)
67
#define OCMD_BUF_TYPE_MASK	(0x1<<5)
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
#define OCMD_BUF_TYPE_FRAME	(0x0<<5)
#define OCMD_BUF_TYPE_FIELD	(0x1<<5)
#define OCMD_TEST_MODE		(0x1<<4)
#define OCMD_BUFFER_SELECT	(0x3<<2)
#define OCMD_BUFFER0		(0x0<<2)
#define OCMD_BUFFER1		(0x1<<2)
#define OCMD_FIELD_SELECT	(0x1<<2)
#define OCMD_FIELD0		(0x0<<1)
#define OCMD_FIELD1		(0x1<<1)
#define OCMD_ENABLE		(0x1<<0)

/* OCONFIG register */
#define OCONF_PIPE_MASK		(0x1<<18)
#define OCONF_PIPE_A		(0x0<<18)
#define OCONF_PIPE_B		(0x1<<18)
#define OCONF_GAMMA2_ENABLE	(0x1<<16)
#define OCONF_CSC_MODE_BT601	(0x0<<5)
#define OCONF_CSC_MODE_BT709	(0x1<<5)
#define OCONF_CSC_BYPASS	(0x1<<4)
#define OCONF_CC_OUT_8BIT	(0x1<<3)
#define OCONF_TEST_MODE		(0x1<<2)
#define OCONF_THREE_LINE_BUFFER	(0x1<<0)
#define OCONF_TWO_LINE_BUFFER	(0x0<<0)

/* DCLRKM (dst-key) register */
#define DST_KEY_ENABLE		(0x1<<31)
#define CLK_RGB24_MASK		0x0
#define CLK_RGB16_MASK		0x070307
#define CLK_RGB15_MASK		0x070707
#define CLK_RGB8I_MASK		0xffffff

#define RGB16_TO_COLORKEY(c) \
	(((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
#define RGB15_TO_COLORKEY(c) \
	(((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))

/* overlay flip addr flag */
#define OFC_UPDATE		0x1

/* polyphase filter coefficients */
#define N_HORIZ_Y_TAPS          5
#define N_VERT_Y_TAPS           3
#define N_HORIZ_UV_TAPS         3
#define N_VERT_UV_TAPS          3
#define N_PHASES                17
#define MAX_TAPS                5

/* memory bufferd overlay registers */
struct overlay_registers {
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
	u32 OBUF_0Y;
	u32 OBUF_1Y;
	u32 OBUF_0U;
	u32 OBUF_0V;
	u32 OBUF_1U;
	u32 OBUF_1V;
	u32 OSTRIDE;
	u32 YRGB_VPH;
	u32 UV_VPH;
	u32 HORZ_PH;
	u32 INIT_PHS;
	u32 DWINPOS;
	u32 DWINSZ;
	u32 SWIDTH;
	u32 SWIDTHSW;
	u32 SHEIGHT;
	u32 YRGBSCALE;
	u32 UVSCALE;
	u32 OCLRC0;
	u32 OCLRC1;
	u32 DCLRKV;
	u32 DCLRKM;
	u32 SCLRKVH;
	u32 SCLRKVL;
	u32 SCLRKEN;
	u32 OCONFIG;
	u32 OCMD;
	u32 RESERVED1; /* 0x6C */
	u32 OSTART_0Y;
	u32 OSTART_1Y;
	u32 OSTART_0U;
	u32 OSTART_0V;
	u32 OSTART_1U;
	u32 OSTART_1V;
	u32 OTILEOFF_0Y;
	u32 OTILEOFF_1Y;
	u32 OTILEOFF_0U;
	u32 OTILEOFF_0V;
	u32 OTILEOFF_1U;
	u32 OTILEOFF_1V;
	u32 FASTHSCALE; /* 0xA0 */
	u32 UVSCALEV; /* 0xA4 */
	u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
	u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
	u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
	u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
	u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
	u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
	u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
	u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
	u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
168 169
};

170 171 172 173 174
struct intel_overlay {
	struct drm_device *dev;
	struct intel_crtc *crtc;
	struct drm_i915_gem_object *vid_bo;
	struct drm_i915_gem_object *old_vid_bo;
175 176
	bool active;
	bool pfit_active;
177
	u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
178 179
	u32 color_key:24;
	u32 color_key_enabled:1;
180 181 182 183 184 185
	u32 brightness, contrast, saturation;
	u32 old_xscale, old_yscale;
	/* register access */
	u32 flip_addr;
	struct drm_i915_gem_object *reg_bo;
	/* flip handling */
186
	struct drm_i915_gem_request *last_flip_req;
187
	void (*flip_tail)(struct intel_overlay *);
188
};
189

190
static struct overlay_registers __iomem *
191
intel_overlay_map_regs(struct intel_overlay *overlay)
192
{
193
	struct drm_i915_private *dev_priv = overlay->dev->dev_private;
194
	struct overlay_registers __iomem *regs;
195

196
	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
197
		regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr;
198
	else
B
Ben Widawsky 已提交
199
		regs = io_mapping_map_wc(dev_priv->gtt.mappable,
200
					 i915_gem_obj_ggtt_offset(overlay->reg_bo));
201

202
	return regs;
203
}
204

205
static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
206
				     struct overlay_registers __iomem *regs)
207 208
{
	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
209
		io_mapping_unmap(regs);
210 211
}

212
static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
213
					 void (*tail)(struct intel_overlay *))
214 215
{
	struct drm_device *dev = overlay->dev;
216
	struct drm_i915_private *dev_priv = dev->dev_private;
217
	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
218
	int ret;
219

220
	WARN_ON(overlay->last_flip_req);
221 222
	i915_gem_request_assign(&overlay->last_flip_req,
					     ring->outstanding_lazy_request);
223
	ret = i915_add_request(ring);
224 225 226
	if (ret)
		return ret;

227
	overlay->flip_tail = tail;
228
	ret = i915_wait_request(overlay->last_flip_req);
229
	if (ret)
230
		return ret;
231

232
	i915_gem_request_assign(&overlay->last_flip_req, NULL);
233 234 235 236 237 238 239
	return 0;
}

/* overlay needs to be disable in OCMD reg */
static int intel_overlay_on(struct intel_overlay *overlay)
{
	struct drm_device *dev = overlay->dev;
240
	struct drm_i915_private *dev_priv = dev->dev_private;
241
	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
242 243
	int ret;

244
	WARN_ON(overlay->active);
245
	WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE));
246

247
	ret = intel_ring_begin(ring, 4);
248 249
	if (ret)
		return ret;
250

251 252
	overlay->active = true;

253 254 255 256 257
	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
	intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE);
	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
	intel_ring_emit(ring, MI_NOOP);
	intel_ring_advance(ring);
258

259
	return intel_overlay_do_wait_request(overlay, NULL);
260 261 262
}

/* overlay needs to be enabled in OCMD reg */
C
Chris Wilson 已提交
263 264
static int intel_overlay_continue(struct intel_overlay *overlay,
				  bool load_polyphase_filter)
265 266
{
	struct drm_device *dev = overlay->dev;
267
	struct drm_i915_private *dev_priv = dev->dev_private;
268
	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
269 270
	u32 flip_addr = overlay->flip_addr;
	u32 tmp;
271
	int ret;
272

273
	WARN_ON(!overlay->active);
274 275 276 277 278 279 280 281 282

	if (load_polyphase_filter)
		flip_addr |= OFC_UPDATE;

	/* check for underruns */
	tmp = I915_READ(DOVSTA);
	if (tmp & (1 << 17))
		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);

283
	ret = intel_ring_begin(ring, 2);
284
	if (ret)
285
		return ret;
286

287 288 289
	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
	intel_ring_emit(ring, flip_addr);
	intel_ring_advance(ring);
290

291 292 293
	WARN_ON(overlay->last_flip_req);
	i915_gem_request_assign(&overlay->last_flip_req,
					     ring->outstanding_lazy_request);
294
	return i915_add_request(ring);
295 296
}

297
static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
298
{
299
	struct drm_i915_gem_object *obj = overlay->old_vid_bo;
300

B
Ben Widawsky 已提交
301
	i915_gem_object_ggtt_unpin(obj);
302
	drm_gem_object_unreference(&obj->base);
303

304 305
	overlay->old_vid_bo = NULL;
}
306

307 308
static void intel_overlay_off_tail(struct intel_overlay *overlay)
{
309
	struct drm_i915_gem_object *obj = overlay->vid_bo;
310

311
	/* never have the overlay hw on without showing a frame */
312 313
	if (WARN_ON(!obj))
		return;
314

B
Ben Widawsky 已提交
315
	i915_gem_object_ggtt_unpin(obj);
316
	drm_gem_object_unreference(&obj->base);
317
	overlay->vid_bo = NULL;
318

319 320
	overlay->crtc->overlay = NULL;
	overlay->crtc = NULL;
321
	overlay->active = false;
322 323 324
}

/* overlay needs to be disabled in OCMD reg */
325
static int intel_overlay_off(struct intel_overlay *overlay)
326 327
{
	struct drm_device *dev = overlay->dev;
328
	struct drm_i915_private *dev_priv = dev->dev_private;
329
	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
C
Chris Wilson 已提交
330
	u32 flip_addr = overlay->flip_addr;
331
	int ret;
332

333
	WARN_ON(!overlay->active);
334 335 336 337 338 339 340

	/* According to intel docs the overlay hw may hang (when switching
	 * off) without loading the filter coeffs. It is however unclear whether
	 * this applies to the disabling of the overlay or to the switching off
	 * of the hw. Do it in both cases */
	flip_addr |= OFC_UPDATE;

341
	ret = intel_ring_begin(ring, 6);
342
	if (ret)
343
		return ret;
344

345
	/* wait for overlay to go idle */
346 347 348
	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
	intel_ring_emit(ring, flip_addr);
	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
349
	/* turn overlay off */
D
Daniel Vetter 已提交
350 351 352 353 354 355 356 357 358 359 360
	if (IS_I830(dev)) {
		/* Workaround: Don't disable the overlay fully, since otherwise
		 * it dies on the next OVERLAY_ON cmd. */
		intel_ring_emit(ring, MI_NOOP);
		intel_ring_emit(ring, MI_NOOP);
		intel_ring_emit(ring, MI_NOOP);
	} else {
		intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
		intel_ring_emit(ring, flip_addr);
		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
	}
361
	intel_ring_advance(ring);
362

363
	return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
364 365
}

366 367
/* recover from an interruption due to a signal
 * We have to be careful not to repeat work forever an make forward progess. */
368
static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
369 370 371
{
	int ret;

372
	if (overlay->last_flip_req == NULL)
373
		return 0;
374

375
	ret = i915_wait_request(overlay->last_flip_req);
376
	if (ret)
377 378
		return ret;

379 380
	if (overlay->flip_tail)
		overlay->flip_tail(overlay);
381

382
	i915_gem_request_assign(&overlay->last_flip_req, NULL);
383 384 385
	return 0;
}

386 387
/* Wait for pending overlay flip and release old frame.
 * Needs to be called before the overlay register are changed
388 389
 * via intel_overlay_(un)map_regs
 */
390 391
static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
{
392
	struct drm_device *dev = overlay->dev;
393
	struct drm_i915_private *dev_priv = dev->dev_private;
394
	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
395 396
	int ret;

397 398
	WARN_ON(!mutex_is_locked(&dev->struct_mutex));

399 400 401
	/* Only wait if there is actually an old frame to release to
	 * guarantee forward progress.
	 */
402 403 404
	if (!overlay->old_vid_bo)
		return 0;

405 406
	if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
		/* synchronous slowpath */
407
		ret = intel_ring_begin(ring, 2);
408
		if (ret)
409 410
			return ret;

411 412 413
		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
		intel_ring_emit(ring, MI_NOOP);
		intel_ring_advance(ring);
414

415
		ret = intel_overlay_do_wait_request(overlay,
416
						    intel_overlay_release_old_vid_tail);
417 418 419
		if (ret)
			return ret;
	}
420

421
	intel_overlay_release_old_vid_tail(overlay);
422 423 424 425


	i915_gem_track_fb(overlay->old_vid_bo, NULL,
			  INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
426 427 428
	return 0;
}

429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
void intel_overlay_reset(struct drm_i915_private *dev_priv)
{
	struct intel_overlay *overlay = dev_priv->overlay;

	if (!overlay)
		return;

	intel_overlay_release_old_vid(overlay);

	overlay->last_flip_req = NULL;
	overlay->old_xscale = 0;
	overlay->old_yscale = 0;
	overlay->crtc = NULL;
	overlay->active = false;
}

445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
struct put_image_params {
	int format;
	short dst_x;
	short dst_y;
	short dst_w;
	short dst_h;
	short src_w;
	short src_scan_h;
	short src_scan_w;
	short src_h;
	short stride_Y;
	short stride_UV;
	int offset_Y;
	int offset_U;
	int offset_V;
};

static int packed_depth_bytes(u32 format)
{
	switch (format & I915_OVERLAY_DEPTH_MASK) {
C
Chris Wilson 已提交
465 466 467 468 469 470
	case I915_OVERLAY_YUV422:
		return 4;
	case I915_OVERLAY_YUV411:
		/* return 6; not implemented */
	default:
		return -EINVAL;
471 472 473 474 475 476
	}
}

static int packed_width_bytes(u32 format, short width)
{
	switch (format & I915_OVERLAY_DEPTH_MASK) {
C
Chris Wilson 已提交
477 478 479 480
	case I915_OVERLAY_YUV422:
		return width << 1;
	default:
		return -EINVAL;
481 482 483 484 485 486
	}
}

static int uv_hsubsampling(u32 format)
{
	switch (format & I915_OVERLAY_DEPTH_MASK) {
C
Chris Wilson 已提交
487 488 489 490 491 492 493 494
	case I915_OVERLAY_YUV422:
	case I915_OVERLAY_YUV420:
		return 2;
	case I915_OVERLAY_YUV411:
	case I915_OVERLAY_YUV410:
		return 4;
	default:
		return -EINVAL;
495 496 497 498 499 500
	}
}

static int uv_vsubsampling(u32 format)
{
	switch (format & I915_OVERLAY_DEPTH_MASK) {
C
Chris Wilson 已提交
501 502 503 504 505 506 507 508
	case I915_OVERLAY_YUV420:
	case I915_OVERLAY_YUV410:
		return 2;
	case I915_OVERLAY_YUV422:
	case I915_OVERLAY_YUV411:
		return 1;
	default:
		return -EINVAL;
509 510 511 512 513 514
	}
}

static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
{
	u32 mask, shift, ret;
515
	if (IS_GEN2(dev)) {
516 517
		mask = 0x1f;
		shift = 5;
518 519 520
	} else {
		mask = 0x3f;
		shift = 6;
521 522
	}
	ret = ((offset + width + mask) >> shift) - (offset >> shift);
523
	if (!IS_GEN2(dev))
524
		ret <<= 1;
525
	ret -= 1;
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
	return ret << 2;
}

static const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
	0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
	0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
	0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
	0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
	0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
	0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
	0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
	0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
	0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
	0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
	0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
	0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
	0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
	0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
	0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
	0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
C
Chris Wilson 已提交
546 547 548
	0xb000, 0x3000, 0x0800, 0x3000, 0xb000
};

549 550 551 552 553 554 555 556 557
static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
	0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
	0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
	0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
	0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
	0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
	0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
	0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
	0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
C
Chris Wilson 已提交
558 559
	0x3000, 0x0800, 0x3000
};
560

561
static void update_polyphase_filter(struct overlay_registers __iomem *regs)
562
{
563 564 565
	memcpy_toio(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
	memcpy_toio(regs->UV_HCOEFS, uv_static_hcoeffs,
		    sizeof(uv_static_hcoeffs));
566 567 568
}

static bool update_scaling_factors(struct intel_overlay *overlay,
569
				   struct overlay_registers __iomem *regs,
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
				   struct put_image_params *params)
{
	/* fixed point with a 12 bit shift */
	u32 xscale, yscale, xscale_UV, yscale_UV;
#define FP_SHIFT 12
#define FRACT_MASK 0xfff
	bool scale_changed = false;
	int uv_hscale = uv_hsubsampling(params->format);
	int uv_vscale = uv_vsubsampling(params->format);

	if (params->dst_w > 1)
		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
			/(params->dst_w);
	else
		xscale = 1 << FP_SHIFT;

	if (params->dst_h > 1)
		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
			/(params->dst_h);
	else
		yscale = 1 << FP_SHIFT;

	/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
C
Chris Wilson 已提交
593 594 595 596 597
	xscale_UV = xscale/uv_hscale;
	yscale_UV = yscale/uv_vscale;
	/* make the Y scale to UV scale ratio an exact multiply */
	xscale = xscale_UV * uv_hscale;
	yscale = yscale_UV * uv_vscale;
598
	/*} else {
C
Chris Wilson 已提交
599 600 601
	  xscale_UV = 0;
	  yscale_UV = 0;
	  }*/
602 603 604 605 606 607

	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
		scale_changed = true;
	overlay->old_xscale = xscale;
	overlay->old_yscale = yscale;

608 609 610 611
	iowrite32(((yscale & FRACT_MASK) << 20) |
		  ((xscale >> FP_SHIFT)  << 16) |
		  ((xscale & FRACT_MASK) << 3),
		 &regs->YRGBSCALE);
C
Chris Wilson 已提交
612

613 614 615 616
	iowrite32(((yscale_UV & FRACT_MASK) << 20) |
		  ((xscale_UV >> FP_SHIFT)  << 16) |
		  ((xscale_UV & FRACT_MASK) << 3),
		 &regs->UVSCALE);
C
Chris Wilson 已提交
617

618 619 620
	iowrite32((((yscale    >> FP_SHIFT) << 16) |
		   ((yscale_UV >> FP_SHIFT) << 0)),
		 &regs->UVSCALEV);
621 622 623 624 625 626 627 628

	if (scale_changed)
		update_polyphase_filter(regs);

	return scale_changed;
}

static void update_colorkey(struct intel_overlay *overlay,
629
			    struct overlay_registers __iomem *regs)
630 631
{
	u32 key = overlay->color_key;
632 633 634 635 636
	u32 flags;

	flags = 0;
	if (overlay->color_key_enabled)
		flags |= DST_KEY_ENABLE;
637

638
	switch (overlay->crtc->base.primary->fb->bits_per_pixel) {
C
Chris Wilson 已提交
639
	case 8:
640 641
		key = 0;
		flags |= CLK_RGB8I_MASK;
642 643
		break;

C
Chris Wilson 已提交
644
	case 16:
645
		if (overlay->crtc->base.primary->fb->depth == 15) {
646 647
			key = RGB15_TO_COLORKEY(key);
			flags |= CLK_RGB15_MASK;
C
Chris Wilson 已提交
648
		} else {
649 650
			key = RGB16_TO_COLORKEY(key);
			flags |= CLK_RGB16_MASK;
C
Chris Wilson 已提交
651
		}
652 653
		break;

C
Chris Wilson 已提交
654 655
	case 24:
	case 32:
656
		flags |= CLK_RGB24_MASK;
657
		break;
658
	}
659 660 661

	iowrite32(key, &regs->DCLRKV);
	iowrite32(flags, &regs->DCLRKM);
662 663 664 665 666 667 668 669
}

static u32 overlay_cmd_reg(struct put_image_params *params)
{
	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;

	if (params->format & I915_OVERLAY_YUV_PLANAR) {
		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
C
Chris Wilson 已提交
670 671 672 673 674 675 676 677 678 679
		case I915_OVERLAY_YUV422:
			cmd |= OCMD_YUV_422_PLANAR;
			break;
		case I915_OVERLAY_YUV420:
			cmd |= OCMD_YUV_420_PLANAR;
			break;
		case I915_OVERLAY_YUV411:
		case I915_OVERLAY_YUV410:
			cmd |= OCMD_YUV_410_PLANAR;
			break;
680 681 682
		}
	} else { /* YUV packed */
		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
C
Chris Wilson 已提交
683 684 685 686 687 688
		case I915_OVERLAY_YUV422:
			cmd |= OCMD_YUV_422_PACKED;
			break;
		case I915_OVERLAY_YUV411:
			cmd |= OCMD_YUV_411_PACKED;
			break;
689 690 691
		}

		switch (params->format & I915_OVERLAY_SWAP_MASK) {
C
Chris Wilson 已提交
692 693 694 695 696 697 698 699 700 701 702
		case I915_OVERLAY_NO_SWAP:
			break;
		case I915_OVERLAY_UV_SWAP:
			cmd |= OCMD_UV_SWAP;
			break;
		case I915_OVERLAY_Y_SWAP:
			cmd |= OCMD_Y_SWAP;
			break;
		case I915_OVERLAY_Y_AND_UV_SWAP:
			cmd |= OCMD_Y_AND_UV_SWAP;
			break;
703 704 705 706 707 708
		}
	}

	return cmd;
}

709
static int intel_overlay_do_put_image(struct intel_overlay *overlay,
710
				      struct drm_i915_gem_object *new_bo,
711
				      struct put_image_params *params)
712 713
{
	int ret, tmp_width;
714
	struct overlay_registers __iomem *regs;
715 716
	bool scale_changed = false;
	struct drm_device *dev = overlay->dev;
717
	u32 swidth, swidthsw, sheight, ostride;
718
	enum pipe pipe = overlay->crtc->pipe;
719

720 721
	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
722 723 724 725 726

	ret = intel_overlay_release_old_vid(overlay);
	if (ret != 0)
		return ret;

727 728
	ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL,
						   &i915_ggtt_view_normal);
729 730 731
	if (ret != 0)
		return ret;

732 733 734 735
	ret = i915_gem_object_put_fence(new_bo);
	if (ret)
		goto out_unpin;

736
	if (!overlay->active) {
737
		u32 oconfig;
738
		regs = intel_overlay_map_regs(overlay);
739 740 741 742
		if (!regs) {
			ret = -ENOMEM;
			goto out_unpin;
		}
743
		oconfig = OCONF_CC_OUT_8BIT;
744
		if (IS_GEN4(overlay->dev))
745
			oconfig |= OCONF_CSC_MODE_BT709;
746
		oconfig |= pipe == 0 ?
747
			OCONF_PIPE_A : OCONF_PIPE_B;
748
		iowrite32(oconfig, &regs->OCONFIG);
749
		intel_overlay_unmap_regs(overlay, regs);
750 751 752 753 754 755

		ret = intel_overlay_on(overlay);
		if (ret != 0)
			goto out_unpin;
	}

756
	regs = intel_overlay_map_regs(overlay);
757 758 759 760 761
	if (!regs) {
		ret = -ENOMEM;
		goto out_unpin;
	}

762 763
	iowrite32((params->dst_y << 16) | params->dst_x, &regs->DWINPOS);
	iowrite32((params->dst_h << 16) | params->dst_w, &regs->DWINSZ);
764 765 766 767 768 769

	if (params->format & I915_OVERLAY_YUV_PACKED)
		tmp_width = packed_width_bytes(params->format, params->src_w);
	else
		tmp_width = params->src_w;

770 771 772
	swidth = params->src_w;
	swidthsw = calc_swidthsw(overlay->dev, params->offset_Y, tmp_width);
	sheight = params->src_h;
773
	iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_Y, &regs->OBUF_0Y);
774
	ostride = params->stride_Y;
775 776 777 778 779

	if (params->format & I915_OVERLAY_YUV_PLANAR) {
		int uv_hscale = uv_hsubsampling(params->format);
		int uv_vscale = uv_vsubsampling(params->format);
		u32 tmp_U, tmp_V;
780
		swidth |= (params->src_w/uv_hscale) << 16;
781
		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
C
Chris Wilson 已提交
782
				      params->src_w/uv_hscale);
783
		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
C
Chris Wilson 已提交
784
				      params->src_w/uv_hscale);
785 786
		swidthsw |= max_t(u32, tmp_U, tmp_V) << 16;
		sheight |= (params->src_h/uv_vscale) << 16;
787 788
		iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_U, &regs->OBUF_0U);
		iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_V, &regs->OBUF_0V);
789
		ostride |= params->stride_UV << 16;
790 791
	}

792 793 794 795 796
	iowrite32(swidth, &regs->SWIDTH);
	iowrite32(swidthsw, &regs->SWIDTHSW);
	iowrite32(sheight, &regs->SHEIGHT);
	iowrite32(ostride, &regs->OSTRIDE);

797 798 799 800
	scale_changed = update_scaling_factors(overlay, regs, params);

	update_colorkey(overlay, regs);

801
	iowrite32(overlay_cmd_reg(params), &regs->OCMD);
802

803
	intel_overlay_unmap_regs(overlay, regs);
804

C
Chris Wilson 已提交
805 806 807
	ret = intel_overlay_continue(overlay, scale_changed);
	if (ret)
		goto out_unpin;
808

809 810 811
	i915_gem_track_fb(overlay->vid_bo, new_bo,
			  INTEL_FRONTBUFFER_OVERLAY(pipe));

812
	overlay->old_vid_bo = overlay->vid_bo;
813
	overlay->vid_bo = new_bo;
814

815 816 817
	intel_frontbuffer_flip(dev,
			       INTEL_FRONTBUFFER_OVERLAY(pipe));

818 819 820
	return 0;

out_unpin:
B
Ben Widawsky 已提交
821
	i915_gem_object_ggtt_unpin(new_bo);
822 823 824
	return ret;
}

825
int intel_overlay_switch_off(struct intel_overlay *overlay)
826
{
827
	struct overlay_registers __iomem *regs;
828
	struct drm_device *dev = overlay->dev;
829
	int ret;
830

831 832
	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
833

834
	ret = intel_overlay_recover_from_interrupt(overlay);
835 836
	if (ret != 0)
		return ret;
837

838 839 840 841 842 843 844
	if (!overlay->active)
		return 0;

	ret = intel_overlay_release_old_vid(overlay);
	if (ret != 0)
		return ret;

845
	regs = intel_overlay_map_regs(overlay);
846
	iowrite32(0, &regs->OCMD);
847
	intel_overlay_unmap_regs(overlay, regs);
848

849
	ret = intel_overlay_off(overlay);
850 851 852
	if (ret != 0)
		return ret;

853
	intel_overlay_off_tail(overlay);
854 855 856 857 858 859
	return 0;
}

static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
					  struct intel_crtc *crtc)
{
860
	if (!crtc->active)
861 862 863
		return -EINVAL;

	/* can't use the overlay with double wide pipe */
864
	if (crtc->config->double_wide)
865 866 867 868 869 870 871 872
		return -EINVAL;

	return 0;
}

static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
{
	struct drm_device *dev = overlay->dev;
873
	struct drm_i915_private *dev_priv = dev->dev_private;
874
	u32 pfit_control = I915_READ(PFIT_CONTROL);
875
	u32 ratio;
876 877

	/* XXX: This is not the same logic as in the xorg driver, but more in
878 879
	 * line with the intel documentation for the i965
	 */
880
	if (INTEL_INFO(dev)->gen >= 4) {
881
		/* on i965 use the PGM reg to read out the autoscaler values */
882 883
		ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965;
	} else {
884 885
		if (pfit_control & VERT_AUTO_SCALE)
			ratio = I915_READ(PFIT_AUTO_RATIOS);
886
		else
887 888
			ratio = I915_READ(PFIT_PGM_RATIOS);
		ratio >>= PFIT_VERT_SCALE_SHIFT;
889 890 891 892 893 894 895 896 897 898
	}

	overlay->pfit_vscale_ratio = ratio;
}

static int check_overlay_dst(struct intel_overlay *overlay,
			     struct drm_intel_overlay_put_image *rec)
{
	struct drm_display_mode *mode = &overlay->crtc->base.mode;

899 900 901 902
	if (rec->dst_x < mode->hdisplay &&
	    rec->dst_x + rec->dst_width <= mode->hdisplay &&
	    rec->dst_y < mode->vdisplay &&
	    rec->dst_y + rec->dst_height <= mode->vdisplay)
903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
		return 0;
	else
		return -EINVAL;
}

static int check_overlay_scaling(struct put_image_params *rec)
{
	u32 tmp;

	/* downscaling limit is 8.0 */
	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
	if (tmp > 7)
		return -EINVAL;
	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
	if (tmp > 7)
		return -EINVAL;

	return 0;
}

static int check_overlay_src(struct drm_device *dev,
			     struct drm_intel_overlay_put_image *rec,
925
			     struct drm_i915_gem_object *new_bo)
926 927 928
{
	int uv_hscale = uv_hsubsampling(rec->flags);
	int uv_vscale = uv_vsubsampling(rec->flags);
929 930 931
	u32 stride_mask;
	int depth;
	u32 tmp;
932 933 934

	/* check src dimensions */
	if (IS_845G(dev) || IS_I830(dev)) {
C
Chris Wilson 已提交
935
		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
936
		    rec->src_width  > IMAGE_MAX_WIDTH_LEGACY)
937 938
			return -EINVAL;
	} else {
C
Chris Wilson 已提交
939
		if (rec->src_height > IMAGE_MAX_HEIGHT ||
940
		    rec->src_width  > IMAGE_MAX_WIDTH)
941 942
			return -EINVAL;
	}
943

944
	/* better safe than sorry, use 4 as the maximal subsampling ratio */
C
Chris Wilson 已提交
945
	if (rec->src_height < N_VERT_Y_TAPS*4 ||
946
	    rec->src_width  < N_HORIZ_Y_TAPS*4)
947 948
		return -EINVAL;

949
	/* check alignment constraints */
950
	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
C
Chris Wilson 已提交
951 952 953
	case I915_OVERLAY_RGB:
		/* not implemented */
		return -EINVAL;
954

C
Chris Wilson 已提交
955 956
	case I915_OVERLAY_YUV_PACKED:
		if (uv_vscale != 1)
957
			return -EINVAL;
958 959

		depth = packed_depth_bytes(rec->flags);
C
Chris Wilson 已提交
960 961
		if (depth < 0)
			return depth;
962

C
Chris Wilson 已提交
963 964 965 966 967 968 969 970
		/* ignore UV planes */
		rec->stride_UV = 0;
		rec->offset_U = 0;
		rec->offset_V = 0;
		/* check pixel alignment */
		if (rec->offset_Y % depth)
			return -EINVAL;
		break;
971

C
Chris Wilson 已提交
972 973
	case I915_OVERLAY_YUV_PLANAR:
		if (uv_vscale < 0 || uv_hscale < 0)
974
			return -EINVAL;
C
Chris Wilson 已提交
975 976
		/* no offset restrictions for planar formats */
		break;
977

C
Chris Wilson 已提交
978 979
	default:
		return -EINVAL;
980 981 982 983 984 985
	}

	if (rec->src_width % uv_hscale)
		return -EINVAL;

	/* stride checking */
986 987 988 989
	if (IS_I830(dev) || IS_845G(dev))
		stride_mask = 255;
	else
		stride_mask = 63;
990 991 992

	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
		return -EINVAL;
993
	if (IS_GEN4(dev) && rec->stride_Y < 512)
994 995 996
		return -EINVAL;

	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
997 998
		4096 : 8192;
	if (rec->stride_Y > tmp || rec->stride_UV > 2*1024)
999 1000 1001 1002
		return -EINVAL;

	/* check buffer dimensions */
	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
C
Chris Wilson 已提交
1003 1004 1005 1006 1007 1008 1009
	case I915_OVERLAY_RGB:
	case I915_OVERLAY_YUV_PACKED:
		/* always 4 Y values per depth pixels */
		if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
			return -EINVAL;

		tmp = rec->stride_Y*rec->src_height;
1010
		if (rec->offset_Y + tmp > new_bo->base.size)
C
Chris Wilson 已提交
1011 1012 1013 1014 1015 1016 1017 1018 1019
			return -EINVAL;
		break;

	case I915_OVERLAY_YUV_PLANAR:
		if (rec->src_width > rec->stride_Y)
			return -EINVAL;
		if (rec->src_width/uv_hscale > rec->stride_UV)
			return -EINVAL;

1020
		tmp = rec->stride_Y * rec->src_height;
1021
		if (rec->offset_Y + tmp > new_bo->base.size)
C
Chris Wilson 已提交
1022
			return -EINVAL;
1023 1024

		tmp = rec->stride_UV * (rec->src_height / uv_vscale);
1025 1026
		if (rec->offset_U + tmp > new_bo->base.size ||
		    rec->offset_V + tmp > new_bo->base.size)
C
Chris Wilson 已提交
1027 1028
			return -EINVAL;
		break;
1029 1030 1031 1032 1033
	}

	return 0;
}

1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
/**
 * Return the pipe currently connected to the panel fitter,
 * or -1 if the panel fitter is not present or not in use
 */
static int intel_panel_fitter_pipe(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	u32  pfit_control;

	/* i830 doesn't have a panel fitter */
1044
	if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev)))
1045 1046 1047 1048 1049 1050 1051 1052 1053
		return -1;

	pfit_control = I915_READ(PFIT_CONTROL);

	/* See if the panel fitter is in use */
	if ((pfit_control & PFIT_ENABLE) == 0)
		return -1;

	/* 965 can place panel fitter on either pipe */
1054
	if (IS_GEN4(dev))
1055 1056 1057 1058 1059 1060
		return (pfit_control >> 29) & 0x3;

	/* older chips can only use pipe 1 */
	return 1;
}

1061
int intel_overlay_put_image(struct drm_device *dev, void *data,
1062
			    struct drm_file *file_priv)
1063 1064
{
	struct drm_intel_overlay_put_image *put_image_rec = data;
1065
	struct drm_i915_private *dev_priv = dev->dev_private;
1066
	struct intel_overlay *overlay;
R
Rob Clark 已提交
1067
	struct drm_crtc *drmmode_crtc;
1068
	struct intel_crtc *crtc;
1069
	struct drm_i915_gem_object *new_bo;
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
	struct put_image_params *params;
	int ret;

	overlay = dev_priv->overlay;
	if (!overlay) {
		DRM_DEBUG("userspace bug: no overlay\n");
		return -ENODEV;
	}

	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
1080
		drm_modeset_lock_all(dev);
1081 1082
		mutex_lock(&dev->struct_mutex);

1083
		ret = intel_overlay_switch_off(overlay);
1084 1085

		mutex_unlock(&dev->struct_mutex);
1086
		drm_modeset_unlock_all(dev);
1087 1088 1089 1090

		return ret;
	}

1091
	params = kmalloc(sizeof(*params), GFP_KERNEL);
1092 1093 1094
	if (!params)
		return -ENOMEM;

R
Rob Clark 已提交
1095 1096
	drmmode_crtc = drm_crtc_find(dev, put_image_rec->crtc_id);
	if (!drmmode_crtc) {
1097 1098 1099
		ret = -ENOENT;
		goto out_free;
	}
R
Rob Clark 已提交
1100
	crtc = to_intel_crtc(drmmode_crtc);
1101

1102 1103
	new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
						   put_image_rec->bo_handle));
1104
	if (&new_bo->base == NULL) {
1105 1106 1107
		ret = -ENOENT;
		goto out_free;
	}
1108

1109
	drm_modeset_lock_all(dev);
1110 1111
	mutex_lock(&dev->struct_mutex);

1112
	if (new_bo->tiling_mode) {
1113
		DRM_DEBUG_KMS("buffer used for overlay image can not be tiled\n");
1114 1115 1116 1117
		ret = -EINVAL;
		goto out_unlock;
	}

1118
	ret = intel_overlay_recover_from_interrupt(overlay);
1119 1120
	if (ret != 0)
		goto out_unlock;
1121

1122 1123
	if (overlay->crtc != crtc) {
		struct drm_display_mode *mode = &crtc->base.mode;
1124
		ret = intel_overlay_switch_off(overlay);
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
		if (ret != 0)
			goto out_unlock;

		ret = check_overlay_possible_on_crtc(overlay, crtc);
		if (ret != 0)
			goto out_unlock;

		overlay->crtc = crtc;
		crtc->overlay = overlay;

1135 1136 1137
		/* line too wide, i.e. one-line-mode */
		if (mode->hdisplay > 1024 &&
		    intel_panel_fitter_pipe(dev) == crtc->pipe) {
1138
			overlay->pfit_active = true;
1139 1140
			update_pfit_vscale_ratio(overlay);
		} else
1141
			overlay->pfit_active = false;
1142 1143 1144 1145 1146 1147 1148 1149
	}

	ret = check_overlay_dst(overlay, put_image_rec);
	if (ret != 0)
		goto out_unlock;

	if (overlay->pfit_active) {
		params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
C
Chris Wilson 已提交
1150
				 overlay->pfit_vscale_ratio);
1151 1152
		/* shifting right rounds downwards, so add 1 */
		params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
C
Chris Wilson 已提交
1153
				 overlay->pfit_vscale_ratio) + 1;
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
	} else {
		params->dst_y = put_image_rec->dst_y;
		params->dst_h = put_image_rec->dst_height;
	}
	params->dst_x = put_image_rec->dst_x;
	params->dst_w = put_image_rec->dst_width;

	params->src_w = put_image_rec->src_width;
	params->src_h = put_image_rec->src_height;
	params->src_scan_w = put_image_rec->src_scan_width;
	params->src_scan_h = put_image_rec->src_scan_height;
C
Chris Wilson 已提交
1165 1166
	if (params->src_scan_h > params->src_h ||
	    params->src_scan_w > params->src_w) {
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
		ret = -EINVAL;
		goto out_unlock;
	}

	ret = check_overlay_src(dev, put_image_rec, new_bo);
	if (ret != 0)
		goto out_unlock;
	params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
	params->stride_Y = put_image_rec->stride_Y;
	params->stride_UV = put_image_rec->stride_UV;
	params->offset_Y = put_image_rec->offset_Y;
	params->offset_U = put_image_rec->offset_U;
	params->offset_V = put_image_rec->offset_V;

	/* Check scaling after src size to prevent a divide-by-zero. */
	ret = check_overlay_scaling(params);
	if (ret != 0)
		goto out_unlock;

	ret = intel_overlay_do_put_image(overlay, new_bo, params);
	if (ret != 0)
		goto out_unlock;

	mutex_unlock(&dev->struct_mutex);
1191
	drm_modeset_unlock_all(dev);
1192 1193 1194 1195 1196 1197 1198

	kfree(params);

	return 0;

out_unlock:
	mutex_unlock(&dev->struct_mutex);
1199
	drm_modeset_unlock_all(dev);
1200
	drm_gem_object_unreference_unlocked(&new_bo->base);
1201
out_free:
1202 1203 1204 1205 1206 1207
	kfree(params);

	return ret;
}

static void update_reg_attrs(struct intel_overlay *overlay,
1208
			     struct overlay_registers __iomem *regs)
1209
{
1210 1211 1212
	iowrite32((overlay->contrast << 18) | (overlay->brightness & 0xff),
		  &regs->OCLRC0);
	iowrite32(overlay->saturation, &regs->OCLRC1);
1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
}

static bool check_gamma_bounds(u32 gamma1, u32 gamma2)
{
	int i;

	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
		return false;

	for (i = 0; i < 3; i++) {
C
Chris Wilson 已提交
1223
		if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
			return false;
	}

	return true;
}

static bool check_gamma5_errata(u32 gamma5)
{
	int i;

	for (i = 0; i < 3; i++) {
		if (((gamma5 >> i*8) & 0xff) == 0x80)
			return false;
	}

	return true;
}

static int check_gamma(struct drm_intel_overlay_attrs *attrs)
{
C
Chris Wilson 已提交
1244 1245 1246 1247 1248 1249 1250
	if (!check_gamma_bounds(0, attrs->gamma0) ||
	    !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
	    !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
	    !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
	    !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
	    !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
	    !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
1251
		return -EINVAL;
C
Chris Wilson 已提交
1252

1253 1254
	if (!check_gamma5_errata(attrs->gamma5))
		return -EINVAL;
C
Chris Wilson 已提交
1255

1256 1257 1258 1259
	return 0;
}

int intel_overlay_attrs(struct drm_device *dev, void *data,
1260
			struct drm_file *file_priv)
1261 1262
{
	struct drm_intel_overlay_attrs *attrs = data;
1263
	struct drm_i915_private *dev_priv = dev->dev_private;
1264
	struct intel_overlay *overlay;
1265
	struct overlay_registers __iomem *regs;
1266 1267 1268 1269 1270 1271 1272 1273
	int ret;

	overlay = dev_priv->overlay;
	if (!overlay) {
		DRM_DEBUG("userspace bug: no overlay\n");
		return -ENODEV;
	}

1274
	drm_modeset_lock_all(dev);
1275 1276
	mutex_lock(&dev->struct_mutex);

1277
	ret = -EINVAL;
1278
	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
1279
		attrs->color_key  = overlay->color_key;
1280
		attrs->brightness = overlay->brightness;
1281
		attrs->contrast   = overlay->contrast;
1282 1283
		attrs->saturation = overlay->saturation;

1284
		if (!IS_GEN2(dev)) {
1285 1286 1287 1288 1289 1290 1291 1292
			attrs->gamma0 = I915_READ(OGAMC0);
			attrs->gamma1 = I915_READ(OGAMC1);
			attrs->gamma2 = I915_READ(OGAMC2);
			attrs->gamma3 = I915_READ(OGAMC3);
			attrs->gamma4 = I915_READ(OGAMC4);
			attrs->gamma5 = I915_READ(OGAMC5);
		}
	} else {
1293
		if (attrs->brightness < -128 || attrs->brightness > 127)
1294
			goto out_unlock;
1295
		if (attrs->contrast > 255)
1296
			goto out_unlock;
1297
		if (attrs->saturation > 1023)
1298 1299
			goto out_unlock;

1300 1301 1302 1303
		overlay->color_key  = attrs->color_key;
		overlay->brightness = attrs->brightness;
		overlay->contrast   = attrs->contrast;
		overlay->saturation = attrs->saturation;
1304

1305
		regs = intel_overlay_map_regs(overlay);
1306 1307 1308 1309 1310 1311 1312
		if (!regs) {
			ret = -ENOMEM;
			goto out_unlock;
		}

		update_reg_attrs(overlay, regs);

1313
		intel_overlay_unmap_regs(overlay, regs);
1314 1315

		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
1316
			if (IS_GEN2(dev))
1317 1318 1319 1320 1321 1322 1323 1324
				goto out_unlock;

			if (overlay->active) {
				ret = -EBUSY;
				goto out_unlock;
			}

			ret = check_gamma(attrs);
1325
			if (ret)
1326 1327 1328 1329 1330 1331 1332 1333 1334 1335
				goto out_unlock;

			I915_WRITE(OGAMC0, attrs->gamma0);
			I915_WRITE(OGAMC1, attrs->gamma1);
			I915_WRITE(OGAMC2, attrs->gamma2);
			I915_WRITE(OGAMC3, attrs->gamma3);
			I915_WRITE(OGAMC4, attrs->gamma4);
			I915_WRITE(OGAMC5, attrs->gamma5);
		}
	}
1336
	overlay->color_key_enabled = (attrs->flags & I915_OVERLAY_DISABLE_DEST_COLORKEY) == 0;
1337

1338
	ret = 0;
1339 1340
out_unlock:
	mutex_unlock(&dev->struct_mutex);
1341
	drm_modeset_unlock_all(dev);
1342 1343 1344 1345 1346 1347

	return ret;
}

void intel_setup_overlay(struct drm_device *dev)
{
1348
	struct drm_i915_private *dev_priv = dev->dev_private;
1349
	struct intel_overlay *overlay;
1350
	struct drm_i915_gem_object *reg_bo;
1351
	struct overlay_registers __iomem *regs;
1352 1353
	int ret;

1354
	if (!HAS_OVERLAY(dev))
1355 1356
		return;

1357
	overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
1358 1359
	if (!overlay)
		return;
1360 1361 1362 1363 1364

	mutex_lock(&dev->struct_mutex);
	if (WARN_ON(dev_priv->overlay))
		goto out_free;

1365 1366
	overlay->dev = dev;

1367 1368 1369
	reg_bo = NULL;
	if (!OVERLAY_NEEDS_PHYSICAL(dev))
		reg_bo = i915_gem_object_create_stolen(dev, PAGE_SIZE);
1370 1371 1372
	if (reg_bo == NULL)
		reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
	if (reg_bo == NULL)
1373
		goto out_free;
1374
	overlay->reg_bo = reg_bo;
1375

1376
	if (OVERLAY_NEEDS_PHYSICAL(dev)) {
1377
		ret = i915_gem_object_attach_phys(reg_bo, PAGE_SIZE);
1378 1379 1380 1381
		if (ret) {
			DRM_ERROR("failed to attach phys overlay regs\n");
			goto out_free_bo;
		}
1382
		overlay->flip_addr = reg_bo->phys_handle->busaddr;
1383
	} else {
1384
		ret = i915_gem_obj_ggtt_pin(reg_bo, PAGE_SIZE, PIN_MAPPABLE);
1385
		if (ret) {
1386 1387 1388
			DRM_ERROR("failed to pin overlay register bo\n");
			goto out_free_bo;
		}
1389
		overlay->flip_addr = i915_gem_obj_ggtt_offset(reg_bo);
1390 1391 1392

		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
		if (ret) {
1393 1394 1395
			DRM_ERROR("failed to move overlay register bo into the GTT\n");
			goto out_unpin_bo;
		}
1396 1397 1398 1399
	}

	/* init all values */
	overlay->color_key = 0x0101fe;
1400
	overlay->color_key_enabled = true;
1401 1402 1403 1404
	overlay->brightness = -19;
	overlay->contrast = 75;
	overlay->saturation = 146;

1405
	regs = intel_overlay_map_regs(overlay);
1406
	if (!regs)
1407
		goto out_unpin_bo;
1408

1409
	memset_io(regs, 0, sizeof(struct overlay_registers));
1410 1411 1412
	update_polyphase_filter(regs);
	update_reg_attrs(overlay, regs);

1413
	intel_overlay_unmap_regs(overlay, regs);
1414 1415

	dev_priv->overlay = overlay;
1416
	mutex_unlock(&dev->struct_mutex);
1417 1418 1419
	DRM_INFO("initialized overlay support\n");
	return;

1420
out_unpin_bo:
1421
	if (!OVERLAY_NEEDS_PHYSICAL(dev))
B
Ben Widawsky 已提交
1422
		i915_gem_object_ggtt_unpin(reg_bo);
1423
out_free_bo:
1424
	drm_gem_object_unreference(&reg_bo->base);
1425
out_free:
1426
	mutex_unlock(&dev->struct_mutex);
1427 1428 1429 1430 1431 1432
	kfree(overlay);
	return;
}

void intel_cleanup_overlay(struct drm_device *dev)
{
1433
	struct drm_i915_private *dev_priv = dev->dev_private;
1434

1435 1436
	if (!dev_priv->overlay)
		return;
1437

1438 1439 1440
	/* The bo's should be free'd by the generic code already.
	 * Furthermore modesetting teardown happens beforehand so the
	 * hardware should be off already */
1441
	WARN_ON(dev_priv->overlay->active);
1442 1443 1444

	drm_gem_object_unreference_unlocked(&dev_priv->overlay->reg_bo->base);
	kfree(dev_priv->overlay);
1445
}
1446 1447 1448 1449 1450 1451 1452 1453

struct intel_overlay_error_state {
	struct overlay_registers regs;
	unsigned long base;
	u32 dovsta;
	u32 isr;
};

1454
static struct overlay_registers __iomem *
1455
intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
1456
{
1457
	struct drm_i915_private *dev_priv = overlay->dev->dev_private;
1458
	struct overlay_registers __iomem *regs;
1459 1460

	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1461 1462 1463
		/* Cast to make sparse happy, but it's wc memory anyway, so
		 * equivalent to the wc io mapping on X86. */
		regs = (struct overlay_registers __iomem *)
1464
			overlay->reg_bo->phys_handle->vaddr;
1465
	else
B
Ben Widawsky 已提交
1466
		regs = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
1467
						i915_gem_obj_ggtt_offset(overlay->reg_bo));
1468 1469 1470 1471 1472

	return regs;
}

static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
1473
					struct overlay_registers __iomem *regs)
1474 1475
{
	if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1476
		io_mapping_unmap_atomic(regs);
1477 1478 1479
}


1480 1481 1482
struct intel_overlay_error_state *
intel_overlay_capture_error_state(struct drm_device *dev)
{
1483
	struct drm_i915_private *dev_priv = dev->dev_private;
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496
	struct intel_overlay *overlay = dev_priv->overlay;
	struct intel_overlay_error_state *error;
	struct overlay_registers __iomem *regs;

	if (!overlay || !overlay->active)
		return NULL;

	error = kmalloc(sizeof(*error), GFP_ATOMIC);
	if (error == NULL)
		return NULL;

	error->dovsta = I915_READ(DOVSTA);
	error->isr = I915_READ(ISR);
1497
	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
1498
		error->base = (__force long)overlay->reg_bo->phys_handle->vaddr;
1499
	else
1500
		error->base = i915_gem_obj_ggtt_offset(overlay->reg_bo);
1501 1502 1503 1504 1505 1506

	regs = intel_overlay_map_regs_atomic(overlay);
	if (!regs)
		goto err;

	memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
1507
	intel_overlay_unmap_regs_atomic(overlay, regs);
1508 1509 1510 1511 1512 1513 1514 1515 1516

	return error;

err:
	kfree(error);
	return NULL;
}

void
1517 1518
intel_overlay_print_error_state(struct drm_i915_error_state_buf *m,
				struct intel_overlay_error_state *error)
1519
{
1520 1521 1522 1523
	i915_error_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
			  error->dovsta, error->isr);
	i915_error_printf(m, "  Register file at 0x%08lx:\n",
			  error->base);
1524

1525
#define P(x) i915_error_printf(m, "    " #x ":	0x%08x\n", error->regs.x)
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568
	P(OBUF_0Y);
	P(OBUF_1Y);
	P(OBUF_0U);
	P(OBUF_0V);
	P(OBUF_1U);
	P(OBUF_1V);
	P(OSTRIDE);
	P(YRGB_VPH);
	P(UV_VPH);
	P(HORZ_PH);
	P(INIT_PHS);
	P(DWINPOS);
	P(DWINSZ);
	P(SWIDTH);
	P(SWIDTHSW);
	P(SHEIGHT);
	P(YRGBSCALE);
	P(UVSCALE);
	P(OCLRC0);
	P(OCLRC1);
	P(DCLRKV);
	P(DCLRKM);
	P(SCLRKVH);
	P(SCLRKVL);
	P(SCLRKEN);
	P(OCONFIG);
	P(OCMD);
	P(OSTART_0Y);
	P(OSTART_1Y);
	P(OSTART_0U);
	P(OSTART_0V);
	P(OSTART_1U);
	P(OSTART_1V);
	P(OTILEOFF_0Y);
	P(OTILEOFF_1Y);
	P(OTILEOFF_0U);
	P(OTILEOFF_0V);
	P(OTILEOFF_1U);
	P(OTILEOFF_1V);
	P(FASTHSCALE);
	P(UVSCALEV);
#undef P
}