rcar_du_crtc.c 22.5 KB
Newer Older
1 2 3
/*
 * rcar_du_crtc.c  --  R-Car Display Unit CRTCs
 *
4
 * Copyright (C) 2013-2015 Renesas Electronics Corporation
5 6 7 8 9 10 11 12 13 14 15
 *
 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/clk.h>
#include <linux/mutex.h>
16
#include <linux/sys_soc.h>
17 18

#include <drm/drmP.h>
19 20
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
21 22 23 24
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h>
25
#include <drm/drm_plane_helper.h>
26 27 28 29 30 31

#include "rcar_du_crtc.h"
#include "rcar_du_drv.h"
#include "rcar_du_kms.h"
#include "rcar_du_plane.h"
#include "rcar_du_regs.h"
32
#include "rcar_du_vsp.h"
33 34 35

static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
{
36
	struct rcar_du_device *rcdu = rcrtc->group->dev;
37 38 39 40 41 42

	return rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
}

static void rcar_du_crtc_write(struct rcar_du_crtc *rcrtc, u32 reg, u32 data)
{
43
	struct rcar_du_device *rcdu = rcrtc->group->dev;
44 45 46 47 48 49

	rcar_du_write(rcdu, rcrtc->mmio_offset + reg, data);
}

static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr)
{
50
	struct rcar_du_device *rcdu = rcrtc->group->dev;
51 52 53 54 55 56 57

	rcar_du_write(rcdu, rcrtc->mmio_offset + reg,
		      rcar_du_read(rcdu, rcrtc->mmio_offset + reg) & ~clr);
}

static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set)
{
58
	struct rcar_du_device *rcdu = rcrtc->group->dev;
59 60 61 62 63 64 65 66

	rcar_du_write(rcdu, rcrtc->mmio_offset + reg,
		      rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set);
}

static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg,
				 u32 clr, u32 set)
{
67
	struct rcar_du_device *rcdu = rcrtc->group->dev;
68 69 70 71 72
	u32 value = rcar_du_read(rcdu, rcrtc->mmio_offset + reg);

	rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
}

73 74 75 76 77 78 79 80
static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
{
	int ret;

	ret = clk_prepare_enable(rcrtc->clock);
	if (ret < 0)
		return ret;

81 82 83 84
	ret = clk_prepare_enable(rcrtc->extclock);
	if (ret < 0)
		goto error_clock;

85
	ret = rcar_du_group_get(rcrtc->group);
86
	if (ret < 0)
87 88 89
		goto error_group;

	return 0;
90

91 92 93 94
error_group:
	clk_disable_unprepare(rcrtc->extclock);
error_clock:
	clk_disable_unprepare(rcrtc->clock);
95 96 97 98 99
	return ret;
}

static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
{
100
	rcar_du_group_put(rcrtc->group);
101 102

	clk_disable_unprepare(rcrtc->extclock);
103 104 105
	clk_disable_unprepare(rcrtc->clock);
}

106 107 108 109
/* -----------------------------------------------------------------------------
 * Hardware Setup
 */

K
Koji Matsuoka 已提交
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
struct dpll_info {
	unsigned int output;
	unsigned int fdpll;
	unsigned int n;
	unsigned int m;
};

static void rcar_du_dpll_divider(struct rcar_du_crtc *rcrtc,
				 struct dpll_info *dpll,
				 unsigned long input,
				 unsigned long target)
{
	unsigned long best_diff = (unsigned long)-1;
	unsigned long diff;
	unsigned int fdpll;
	unsigned int m;
	unsigned int n;

	for (n = 39; n < 120; n++) {
		for (m = 0; m < 4; m++) {
			for (fdpll = 1; fdpll < 32; fdpll++) {
				unsigned long output;

				output = input * (n + 1) / (m + 1)
134
				       / (fdpll + 1);
K
Koji Matsuoka 已提交
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
				if (output >= 400000000)
					continue;

				diff = abs((long)output - (long)target);
				if (best_diff > diff) {
					best_diff = diff;
					dpll->n = n;
					dpll->m = m;
					dpll->fdpll = fdpll;
					dpll->output = output;
				}

				if (diff == 0)
					goto done;
			}
		}
	}

done:
	dev_dbg(rcrtc->group->dev->dev,
		"output:%u, fdpll:%u, n:%u, m:%u, diff:%lu\n",
		 dpll->output, dpll->fdpll, dpll->n, dpll->m,
		 best_diff);
}

160 161 162 163 164
static const struct soc_device_attribute rcar_du_r8a7795_es1[] = {
	{ .soc_id = "r8a7795", .revision = "ES1.*" },
	{ /* sentinel */ }
};

165 166
static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
{
167
	const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode;
K
Koji Matsuoka 已提交
168
	struct rcar_du_device *rcdu = rcrtc->group->dev;
169
	unsigned long mode_clock = mode->clock * 1000;
170 171
	unsigned long clk;
	u32 value;
172
	u32 escr;
173 174
	u32 div;

175 176
	/*
	 * Compute the clock divisor and select the internal or external dot
177 178
	 * clock based on the requested frequency.
	 */
179
	clk = clk_get_rate(rcrtc->clock);
180
	div = DIV_ROUND_CLOSEST(clk, mode_clock);
181
	div = clamp(div, 1U, 64U) - 1;
182 183 184
	escr = div | ESCR_DCLKSEL_CLKS;

	if (rcrtc->extclock) {
K
Koji Matsuoka 已提交
185
		struct dpll_info dpll = { 0 };
186 187 188 189 190 191
		unsigned long extclk;
		unsigned long extrate;
		unsigned long rate;
		u32 extdiv;

		extclk = clk_get_rate(rcrtc->extclock);
K
Koji Matsuoka 已提交
192
		if (rcdu->info->dpll_ch & (1 << rcrtc->index)) {
193 194 195 196 197 198 199 200 201 202 203 204 205 206
			unsigned long target = mode_clock;

			/*
			 * The H3 ES1.x exhibits dot clock duty cycle stability
			 * issues. We can work around them by configuring the
			 * DPLL to twice the desired frequency, coupled with a
			 * /2 post-divider. This isn't needed on other SoCs and
			 * breaks HDMI output on M3-W for a currently unknown
			 * reason, so restrict the workaround to H3 ES1.x.
			 */
			if (soc_device_match(rcar_du_r8a7795_es1))
				target *= 2;

			rcar_du_dpll_divider(rcrtc, &dpll, extclk, target);
K
Koji Matsuoka 已提交
207 208 209
			extclk = dpll.output;
		}

210 211 212 213 214 215 216 217
		extdiv = DIV_ROUND_CLOSEST(extclk, mode_clock);
		extdiv = clamp(extdiv, 1U, 64U) - 1;

		rate = clk / (div + 1);
		extrate = extclk / (extdiv + 1);

		if (abs((long)extrate - (long)mode_clock) <
		    abs((long)rate - (long)mode_clock)) {
K
Koji Matsuoka 已提交
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234

			if (rcdu->info->dpll_ch & (1 << rcrtc->index)) {
				u32 dpllcr = DPLLCR_CODE | DPLLCR_CLKE
					   | DPLLCR_FDPLL(dpll.fdpll)
					   | DPLLCR_N(dpll.n) | DPLLCR_M(dpll.m)
					   | DPLLCR_STBY;

				if (rcrtc->index == 1)
					dpllcr |= DPLLCR_PLCS1
					       |  DPLLCR_INCS_DOTCLKIN1;
				else
					dpllcr |= DPLLCR_PLCS0
					       |  DPLLCR_INCS_DOTCLKIN0;

				rcar_du_group_write(rcrtc->group, DPLLCR,
						    dpllcr);
			}
235 236

			escr = ESCR_DCLKSEL_DCLKIN | extdiv;
237
		}
238 239 240 241

		dev_dbg(rcrtc->group->dev->dev,
			"mode clock %lu extrate %lu rate %lu ESCR 0x%08x\n",
			mode_clock, extrate, rate, escr);
242
	}
243

244
	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? ESCR2 : ESCR,
245
			    escr);
246
	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0);
247 248

	/* Signal polarities */
249 250
	value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0)
	      | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0)
251
	      | DSMR_DIPM_DISP | DSMR_CSPM;
252 253 254 255 256 257 258 259 260 261
	rcar_du_crtc_write(rcrtc, DSMR, value);

	/* Display timings */
	rcar_du_crtc_write(rcrtc, HDSR, mode->htotal - mode->hsync_start - 19);
	rcar_du_crtc_write(rcrtc, HDER, mode->htotal - mode->hsync_start +
					mode->hdisplay - 19);
	rcar_du_crtc_write(rcrtc, HSWR, mode->hsync_end -
					mode->hsync_start - 1);
	rcar_du_crtc_write(rcrtc, HCR,  mode->htotal - 1);

262 263 264 265 266 267 268 269 270
	rcar_du_crtc_write(rcrtc, VDSR, mode->crtc_vtotal -
					mode->crtc_vsync_end - 2);
	rcar_du_crtc_write(rcrtc, VDER, mode->crtc_vtotal -
					mode->crtc_vsync_end +
					mode->crtc_vdisplay - 2);
	rcar_du_crtc_write(rcrtc, VSPR, mode->crtc_vtotal -
					mode->crtc_vsync_end +
					mode->crtc_vsync_start - 1);
	rcar_du_crtc_write(rcrtc, VCR,  mode->crtc_vtotal - 1);
271

272
	rcar_du_crtc_write(rcrtc, DESR,  mode->htotal - mode->hsync_start - 1);
273 274 275
	rcar_du_crtc_write(rcrtc, DEWR,  mode->hdisplay);
}

276 277
void rcar_du_crtc_route_output(struct drm_crtc *crtc,
			       enum rcar_du_output output)
278 279
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
280
	struct rcar_du_device *rcdu = rcrtc->group->dev;
281

282 283
	/*
	 * Store the route from the CRTC output to the DU output. The DU will be
284 285
	 * configured when starting the CRTC.
	 */
286
	rcrtc->outputs |= BIT(output);
287

288 289
	/*
	 * Store RGB routing to DPAD0, the hardware will be configured when
290 291 292
	 * starting the CRTC.
	 */
	if (output == RCAR_DU_OUTPUT_DPAD0)
293
		rcdu->dpad0_source = rcrtc->index;
294 295
}

296 297
static unsigned int plane_zpos(struct rcar_du_plane *plane)
{
298
	return plane->plane.state->normalized_zpos;
299 300
}

301 302 303
static const struct rcar_du_format_info *
plane_format(struct rcar_du_plane *plane)
{
304
	return to_rcar_plane_state(plane->plane.state)->format;
305 306
}

307
static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
308 309
{
	struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
310
	struct rcar_du_device *rcdu = rcrtc->group->dev;
311
	unsigned int num_planes = 0;
312 313
	unsigned int dptsr_planes;
	unsigned int hwplanes = 0;
314 315 316 317
	unsigned int prio = 0;
	unsigned int i;
	u32 dspr = 0;

318
	for (i = 0; i < rcrtc->group->num_planes; ++i) {
319
		struct rcar_du_plane *plane = &rcrtc->group->planes[i];
320 321
		unsigned int j;

322
		if (plane->plane.state->crtc != &rcrtc->crtc)
323 324 325 326
			continue;

		/* Insert the plane in the sorted planes array. */
		for (j = num_planes++; j > 0; --j) {
327
			if (plane_zpos(planes[j-1]) <= plane_zpos(plane))
328 329 330 331 332
				break;
			planes[j] = planes[j-1];
		}

		planes[j] = plane;
333
		prio += plane_format(plane)->planes * 4;
334 335 336 337
	}

	for (i = 0; i < num_planes; ++i) {
		struct rcar_du_plane *plane = planes[i];
338
		struct drm_plane_state *state = plane->plane.state;
339
		unsigned int index = to_rcar_plane_state(state)->hwindex;
340 341 342

		prio -= 4;
		dspr |= (index + 1) << prio;
343
		hwplanes |= 1 << index;
344

345
		if (plane_format(plane)->planes == 2) {
346 347 348 349
			index = (index + 1) % 8;

			prio -= 4;
			dspr |= (index + 1) << prio;
350
			hwplanes |= 1 << index;
351 352 353
		}
	}

354 355
	/* If VSP+DU integration is enabled the plane assignment is fixed. */
	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
356 357 358 359 360 361 362
		if (rcdu->info->gen < 3) {
			dspr = (rcrtc->index % 2) + 1;
			hwplanes = 1 << (rcrtc->index % 2);
		} else {
			dspr = (rcrtc->index % 2) ? 3 : 1;
			hwplanes = 1 << ((rcrtc->index % 2) ? 2 : 0);
		}
363 364
	}

365 366
	/*
	 * Update the planes to display timing and dot clock generator
367 368 369 370 371 372
	 * associations.
	 *
	 * Updating the DPTSR register requires restarting the CRTC group,
	 * resulting in visible flicker. To mitigate the issue only update the
	 * association if needed by enabled planes. Planes being disabled will
	 * keep their current association.
373
	 */
374 375 376 377 378 379 380 381 382 383 384 385
	mutex_lock(&rcrtc->group->lock);

	dptsr_planes = rcrtc->index % 2 ? rcrtc->group->dptsr_planes | hwplanes
		     : rcrtc->group->dptsr_planes & ~hwplanes;

	if (dptsr_planes != rcrtc->group->dptsr_planes) {
		rcar_du_group_write(rcrtc->group, DPTSR,
				    (dptsr_planes << 16) | dptsr_planes);
		rcrtc->group->dptsr_planes = dptsr_planes;

		if (rcrtc->group->used_crtcs)
			rcar_du_group_restart(rcrtc->group);
386 387
	}

388 389 390 391
	/* Restart the group if plane sources have changed. */
	if (rcrtc->group->need_restart)
		rcar_du_group_restart(rcrtc->group);

392 393
	mutex_unlock(&rcrtc->group->lock);

394 395
	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
			    dspr);
396 397
}

398 399 400 401
/* -----------------------------------------------------------------------------
 * Page Flip
 */

402
void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
403 404 405 406 407 408 409 410 411 412 413 414 415 416
{
	struct drm_pending_vblank_event *event;
	struct drm_device *dev = rcrtc->crtc.dev;
	unsigned long flags;

	spin_lock_irqsave(&dev->event_lock, flags);
	event = rcrtc->event;
	rcrtc->event = NULL;
	spin_unlock_irqrestore(&dev->event_lock, flags);

	if (event == NULL)
		return;

	spin_lock_irqsave(&dev->event_lock, flags);
417
	drm_crtc_send_vblank_event(&rcrtc->crtc, event);
418
	wake_up(&rcrtc->flip_wait);
419 420
	spin_unlock_irqrestore(&dev->event_lock, flags);

421
	drm_crtc_vblank_put(&rcrtc->crtc);
422 423
}

424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
static bool rcar_du_crtc_page_flip_pending(struct rcar_du_crtc *rcrtc)
{
	struct drm_device *dev = rcrtc->crtc.dev;
	unsigned long flags;
	bool pending;

	spin_lock_irqsave(&dev->event_lock, flags);
	pending = rcrtc->event != NULL;
	spin_unlock_irqrestore(&dev->event_lock, flags);

	return pending;
}

static void rcar_du_crtc_wait_page_flip(struct rcar_du_crtc *rcrtc)
{
	struct rcar_du_device *rcdu = rcrtc->group->dev;

	if (wait_event_timeout(rcrtc->flip_wait,
			       !rcar_du_crtc_page_flip_pending(rcrtc),
			       msecs_to_jiffies(50)))
		return;

	dev_warn(rcdu->dev, "page flip timeout\n");

	rcar_du_crtc_finish_page_flip(rcrtc);
}

451 452 453 454
/* -----------------------------------------------------------------------------
 * Start/Stop and Suspend/Resume
 */

455
static void rcar_du_crtc_setup(struct rcar_du_crtc *rcrtc)
456 457 458 459 460 461 462
{
	/* Set display off and background to black */
	rcar_du_crtc_write(rcrtc, DOOR, DOOR_RGB(0, 0, 0));
	rcar_du_crtc_write(rcrtc, BPOR, BPOR_RGB(0, 0, 0));

	/* Configure display timings and output routing */
	rcar_du_crtc_set_display_timing(rcrtc);
463
	rcar_du_group_set_routing(rcrtc->group);
464

465 466
	/* Start with all planes disabled. */
	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0);
467

468 469 470 471 472 473 474 475 476 477 478 479
	/* Enable the VSP compositor. */
	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
		rcar_du_vsp_enable(rcrtc);

	/* Turn vertical blanking interrupt reporting on. */
	drm_crtc_vblank_on(&rcrtc->crtc);
}

static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
{
	bool interlaced;

480 481
	/*
	 * Select master sync mode. This enables display operation in master
482 483 484
	 * sync mode (with the HSYNC and VSYNC signals configured as outputs and
	 * actively driven).
	 */
485 486 487 488
	interlaced = rcrtc->crtc.mode.flags & DRM_MODE_FLAG_INTERLACE;
	rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK | DSYSR_SCM_MASK,
			     (interlaced ? DSYSR_SCM_INT_VIDEO : 0) |
			     DSYSR_TVM_MASTER);
489

490
	rcar_du_group_start_stop(rcrtc->group, true);
491 492
}

493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
static void rcar_du_crtc_disable_planes(struct rcar_du_crtc *rcrtc)
{
	struct rcar_du_device *rcdu = rcrtc->group->dev;
	struct drm_crtc *crtc = &rcrtc->crtc;
	u32 status;

	/* Make sure vblank interrupts are enabled. */
	drm_crtc_vblank_get(crtc);

	/*
	 * Disable planes and calculate how many vertical blanking interrupts we
	 * have to wait for. If a vertical blanking interrupt has been triggered
	 * but not processed yet, we don't know whether it occurred before or
	 * after the planes got disabled. We thus have to wait for two vblank
	 * interrupts in that case.
	 */
	spin_lock_irq(&rcrtc->vblank_lock);
	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0);
	status = rcar_du_crtc_read(rcrtc, DSSR);
	rcrtc->vblank_count = status & DSSR_VBK ? 2 : 1;
	spin_unlock_irq(&rcrtc->vblank_lock);

	if (!wait_event_timeout(rcrtc->vblank_wait, rcrtc->vblank_count == 0,
				msecs_to_jiffies(100)))
		dev_warn(rcdu->dev, "vertical blanking timeout\n");

	drm_crtc_vblank_put(crtc);
}

522 523 524 525
static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
{
	struct drm_crtc *crtc = &rcrtc->crtc;

526 527
	/*
	 * Disable all planes and wait for the change to take effect. This is
528 529 530 531
	 * required as the plane enable registers are updated on vblank, and no
	 * vblank will occur once the CRTC is stopped. Disabling planes when
	 * starting the CRTC thus wouldn't be enough as it would start scanning
	 * out immediately from old frame buffers until the next vblank.
532 533 534 535 536
	 *
	 * This increases the CRTC stop delay, especially when multiple CRTCs
	 * are stopped in one operation as we now wait for one vblank per CRTC.
	 * Whether this can be improved needs to be researched.
	 */
537
	rcar_du_crtc_disable_planes(rcrtc);
538

539 540
	/*
	 * Disable vertical blanking interrupt reporting. We first need to wait
541 542
	 * for page flip completion before stopping the CRTC as userspace
	 * expects page flips to eventually complete.
543 544
	 */
	rcar_du_crtc_wait_page_flip(rcrtc);
545
	drm_crtc_vblank_off(crtc);
546

547 548 549 550
	/* Disable the VSP compositor. */
	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
		rcar_du_vsp_disable(rcrtc);

551 552
	/*
	 * Select switch sync mode. This stops display operation and configures
553 554 555 556
	 * the HSYNC and VSYNC signals as inputs.
	 */
	rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);

557
	rcar_du_group_start_stop(rcrtc->group, false);
558 559 560 561
}

void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc)
{
562 563 564
	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
		rcar_du_vsp_disable(rcrtc);

565
	rcar_du_crtc_stop(rcrtc);
566
	rcar_du_crtc_put(rcrtc);
567 568 569 570
}

void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
{
571 572
	unsigned int i;

573
	if (!rcrtc->crtc.state->active)
574 575
		return;

576
	rcar_du_crtc_get(rcrtc);
577
	rcar_du_crtc_setup(rcrtc);
578 579

	/* Commit the planes state. */
580
	if (!rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) {
581 582
		for (i = 0; i < rcrtc->group->num_planes; ++i) {
			struct rcar_du_plane *plane = &rcrtc->group->planes[i];
583

584 585
			if (plane->plane.state->crtc != &rcrtc->crtc)
				continue;
586

587 588
			rcar_du_plane_setup(plane);
		}
589 590 591
	}

	rcar_du_crtc_update_planes(rcrtc);
592
	rcar_du_crtc_start(rcrtc);
593 594
}

595 596 597 598
/* -----------------------------------------------------------------------------
 * CRTC Functions
 */

599 600
static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
				       struct drm_crtc_state *old_state)
601 602 603
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);

604 605 606 607 608 609 610 611 612 613
	/*
	 * If the CRTC has already been setup by the .atomic_begin() handler we
	 * can skip the setup stage.
	 */
	if (!rcrtc->initialized) {
		rcar_du_crtc_get(rcrtc);
		rcar_du_crtc_setup(rcrtc);
		rcrtc->initialized = true;
	}

614 615 616
	rcar_du_crtc_start(rcrtc);
}

617 618
static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
					struct drm_crtc_state *old_state)
619 620
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
621

622 623
	rcar_du_crtc_stop(rcrtc);
	rcar_du_crtc_put(rcrtc);
624

625 626 627 628 629 630 631
	spin_lock_irq(&crtc->dev->event_lock);
	if (crtc->state->event) {
		drm_crtc_send_vblank_event(crtc, crtc->state->event);
		crtc->state->event = NULL;
	}
	spin_unlock_irq(&crtc->dev->event_lock);

632
	rcrtc->initialized = false;
633
	rcrtc->outputs = 0;
634 635
}

636 637
static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
				      struct drm_crtc_state *old_crtc_state)
638 639
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
640

641 642 643 644 645 646 647 648 649 650 651 652 653
	WARN_ON(!crtc->state->enable);

	/*
	 * If a mode set is in progress we can be called with the CRTC disabled.
	 * We then need to first setup the CRTC in order to configure planes.
	 * The .atomic_enable() handler will notice and skip the CRTC setup.
	 */
	if (!rcrtc->initialized) {
		rcar_du_crtc_get(rcrtc);
		rcar_du_crtc_setup(rcrtc);
		rcrtc->initialized = true;
	}

654 655
	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
		rcar_du_vsp_atomic_begin(rcrtc);
656 657
}

658 659
static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
				      struct drm_crtc_state *old_crtc_state)
660 661
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
662 663
	struct drm_device *dev = rcrtc->crtc.dev;
	unsigned long flags;
664

665
	rcar_du_crtc_update_planes(rcrtc);
666

667 668 669 670 671 672 673 674 675
	if (crtc->state->event) {
		WARN_ON(drm_crtc_vblank_get(crtc) != 0);

		spin_lock_irqsave(&dev->event_lock, flags);
		rcrtc->event = crtc->state->event;
		crtc->state->event = NULL;
		spin_unlock_irqrestore(&dev->event_lock, flags);
	}

676 677
	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
		rcar_du_vsp_atomic_flush(rcrtc);
678 679
}

680
static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
681 682
	.atomic_begin = rcar_du_crtc_atomic_begin,
	.atomic_flush = rcar_du_crtc_atomic_flush,
683
	.atomic_enable = rcar_du_crtc_atomic_enable,
684
	.atomic_disable = rcar_du_crtc_atomic_disable,
685 686
};

687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
static int rcar_du_crtc_enable_vblank(struct drm_crtc *crtc)
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);

	rcar_du_crtc_write(rcrtc, DSRCR, DSRCR_VBCL);
	rcar_du_crtc_set(rcrtc, DIER, DIER_VBE);

	return 0;
}

static void rcar_du_crtc_disable_vblank(struct drm_crtc *crtc)
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);

	rcar_du_crtc_clr(rcrtc, DIER, DIER_VBE);
}

704
static const struct drm_crtc_funcs crtc_funcs = {
705
	.reset = drm_atomic_helper_crtc_reset,
706
	.destroy = drm_crtc_cleanup,
707
	.set_config = drm_atomic_helper_set_config,
708
	.page_flip = drm_atomic_helper_page_flip,
709 710
	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
711 712
	.enable_vblank = rcar_du_crtc_enable_vblank,
	.disable_vblank = rcar_du_crtc_disable_vblank,
713 714
};

715 716 717 718 719 720 721
/* -----------------------------------------------------------------------------
 * Interrupt Handling
 */

static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
{
	struct rcar_du_crtc *rcrtc = arg;
722
	struct rcar_du_device *rcdu = rcrtc->group->dev;
723 724 725
	irqreturn_t ret = IRQ_NONE;
	u32 status;

726 727
	spin_lock(&rcrtc->vblank_lock);

728 729 730
	status = rcar_du_crtc_read(rcrtc, DSSR);
	rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK);

731 732 733 734 735 736 737 738 739 740 741 742 743 744
	if (status & DSSR_VBK) {
		/*
		 * Wake up the vblank wait if the counter reaches 0. This must
		 * be protected by the vblank_lock to avoid races in
		 * rcar_du_crtc_disable_planes().
		 */
		if (rcrtc->vblank_count) {
			if (--rcrtc->vblank_count == 0)
				wake_up(&rcrtc->vblank_wait);
		}
	}

	spin_unlock(&rcrtc->vblank_lock);

745
	if (status & DSSR_VBK) {
746
		drm_crtc_handle_vblank(&rcrtc->crtc);
747 748 749 750

		if (rcdu->info->gen < 3)
			rcar_du_crtc_finish_page_flip(rcrtc);

751 752 753 754 755 756 757 758 759 760
		ret = IRQ_HANDLED;
	}

	return ret;
}

/* -----------------------------------------------------------------------------
 * Initialization
 */

761
int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
762
{
763
	static const unsigned int mmio_offsets[] = {
764
		DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET, DU3_REG_OFFSET
765 766
	};

767
	struct rcar_du_device *rcdu = rgrp->dev;
768
	struct platform_device *pdev = to_platform_device(rcdu->dev);
769 770
	struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index];
	struct drm_crtc *crtc = &rcrtc->crtc;
771
	struct drm_plane *primary;
772
	unsigned int irqflags;
773 774
	struct clk *clk;
	char clk_name[9];
775 776
	char *name;
	int irq;
777 778
	int ret;

779
	/* Get the CRTC clock and the optional external clock. */
780 781 782 783 784 785 786 787 788 789 790 791 792
	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
		sprintf(clk_name, "du.%u", index);
		name = clk_name;
	} else {
		name = NULL;
	}

	rcrtc->clock = devm_clk_get(rcdu->dev, name);
	if (IS_ERR(rcrtc->clock)) {
		dev_err(rcdu->dev, "no clock for CRTC %u\n", index);
		return PTR_ERR(rcrtc->clock);
	}

793 794 795 796 797 798 799 800 801
	sprintf(clk_name, "dclkin.%u", index);
	clk = devm_clk_get(rcdu->dev, clk_name);
	if (!IS_ERR(clk)) {
		rcrtc->extclock = clk;
	} else if (PTR_ERR(rcrtc->clock) == -EPROBE_DEFER) {
		dev_info(rcdu->dev, "can't get external clock %u\n", index);
		return -EPROBE_DEFER;
	}

802
	init_waitqueue_head(&rcrtc->flip_wait);
803 804
	init_waitqueue_head(&rcrtc->vblank_wait);
	spin_lock_init(&rcrtc->vblank_lock);
805

806
	rcrtc->group = rgrp;
807
	rcrtc->mmio_offset = mmio_offsets[index];
808 809
	rcrtc->index = index;

810
	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
811
		primary = &rcrtc->vsp->planes[rcrtc->vsp_pipe].plane;
812 813 814 815
	else
		primary = &rgrp->planes[index % 2].plane;

	ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary,
816
					NULL, &crtc_funcs, NULL);
817 818 819 820 821
	if (ret < 0)
		return ret;

	drm_crtc_helper_add(crtc, &crtc_helper_funcs);

822 823 824
	/* Start with vertical blanking interrupt reporting disabled. */
	drm_crtc_vblank_off(crtc);

825 826 827 828 829 830 831 832 833 834 835
	/* Register the interrupt handler. */
	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
		irq = platform_get_irq(pdev, index);
		irqflags = 0;
	} else {
		irq = platform_get_irq(pdev, 0);
		irqflags = IRQF_SHARED;
	}

	if (irq < 0) {
		dev_err(rcdu->dev, "no IRQ for CRTC %u\n", index);
J
Julia Lawall 已提交
836
		return irq;
837 838 839 840 841 842 843 844 845 846
	}

	ret = devm_request_irq(rcdu->dev, irq, rcar_du_crtc_irq, irqflags,
			       dev_name(rcdu->dev), rcrtc);
	if (ret < 0) {
		dev_err(rcdu->dev,
			"failed to register IRQ for CRTC %u\n", index);
		return ret;
	}

847 848
	return 0;
}