rcar_du_crtc.c 21.1 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
 */

Koji Matsuoka's avatar
Koji Matsuoka committed
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);
Koji Matsuoka's avatar
Koji Matsuoka committed
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;
Koji Matsuoka's avatar
Koji Matsuoka committed
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) {
Koji Matsuoka's avatar
Koji Matsuoka committed
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);
Koji Matsuoka's avatar
Koji Matsuoka committed
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);
Koji Matsuoka's avatar
Koji Matsuoka committed
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)) {
Koji Matsuoka's avatar
Koji Matsuoka committed
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
}

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

497 498
	/*
	 * Disable all planes and wait for the change to take effect. This is
499 500 501 502 503 504 505 506 507 508 509 510
	 * required as the DSnPR 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.
	 *
	 * 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.
	 */
	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0);
	drm_crtc_wait_one_vblank(crtc);

511 512
	/*
	 * Disable vertical blanking interrupt reporting. We first need to wait
513 514
	 * for page flip completion before stopping the CRTC as userspace
	 * expects page flips to eventually complete.
515 516
	 */
	rcar_du_crtc_wait_page_flip(rcrtc);
517
	drm_crtc_vblank_off(crtc);
518

519 520 521 522
	/* Disable the VSP compositor. */
	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
		rcar_du_vsp_disable(rcrtc);

523 524
	/*
	 * Select switch sync mode. This stops display operation and configures
525 526 527 528
	 * the HSYNC and VSYNC signals as inputs.
	 */
	rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);

529
	rcar_du_group_start_stop(rcrtc->group, false);
530 531 532 533
}

void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc)
{
534 535 536
	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
		rcar_du_vsp_disable(rcrtc);

537
	rcar_du_crtc_stop(rcrtc);
538
	rcar_du_crtc_put(rcrtc);
539 540 541 542
}

void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
{
543 544
	unsigned int i;

545
	if (!rcrtc->crtc.state->active)
546 547
		return;

548
	rcar_du_crtc_get(rcrtc);
549
	rcar_du_crtc_setup(rcrtc);
550 551

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

556 557
			if (plane->plane.state->crtc != &rcrtc->crtc)
				continue;
558

559 560
			rcar_du_plane_setup(plane);
		}
561 562 563
	}

	rcar_du_crtc_update_planes(rcrtc);
564
	rcar_du_crtc_start(rcrtc);
565 566
}

567 568 569 570
/* -----------------------------------------------------------------------------
 * CRTC Functions
 */

571 572
static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
				       struct drm_crtc_state *old_state)
573 574 575
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);

576 577 578 579 580 581 582 583 584 585
	/*
	 * 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;
	}

586 587 588
	rcar_du_crtc_start(rcrtc);
}

589 590
static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
					struct drm_crtc_state *old_state)
591 592
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
593

594 595
	rcar_du_crtc_stop(rcrtc);
	rcar_du_crtc_put(rcrtc);
596

597 598 599 600 601 602 603
	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);

604
	rcrtc->initialized = false;
605
	rcrtc->outputs = 0;
606 607
}

608 609
static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
				      struct drm_crtc_state *old_crtc_state)
610 611
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
612

613 614 615 616 617 618 619 620 621 622 623 624 625
	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;
	}

626 627
	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
		rcar_du_vsp_atomic_begin(rcrtc);
628 629
}

630 631
static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
				      struct drm_crtc_state *old_crtc_state)
632 633
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
634 635
	struct drm_device *dev = rcrtc->crtc.dev;
	unsigned long flags;
636

637
	rcar_du_crtc_update_planes(rcrtc);
638

639 640 641 642 643 644 645 646 647
	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);
	}

648 649
	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
		rcar_du_vsp_atomic_flush(rcrtc);
650 651
}

652
static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
653 654
	.atomic_begin = rcar_du_crtc_atomic_begin,
	.atomic_flush = rcar_du_crtc_atomic_flush,
655
	.atomic_enable = rcar_du_crtc_atomic_enable,
656
	.atomic_disable = rcar_du_crtc_atomic_disable,
657 658
};

659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
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);
}

676
static const struct drm_crtc_funcs crtc_funcs = {
677
	.reset = drm_atomic_helper_crtc_reset,
678
	.destroy = drm_crtc_cleanup,
679
	.set_config = drm_atomic_helper_set_config,
680
	.page_flip = drm_atomic_helper_page_flip,
681 682
	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
683 684
	.enable_vblank = rcar_du_crtc_enable_vblank,
	.disable_vblank = rcar_du_crtc_disable_vblank,
685 686
};

687 688 689 690 691 692 693
/* -----------------------------------------------------------------------------
 * Interrupt Handling
 */

static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
{
	struct rcar_du_crtc *rcrtc = arg;
694
	struct rcar_du_device *rcdu = rcrtc->group->dev;
695 696 697 698 699 700
	irqreturn_t ret = IRQ_NONE;
	u32 status;

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

701
	if (status & DSSR_VBK) {
702
		drm_crtc_handle_vblank(&rcrtc->crtc);
703 704 705 706

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

707 708 709 710 711 712 713 714 715 716
		ret = IRQ_HANDLED;
	}

	return ret;
}

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

717
int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
718
{
719
	static const unsigned int mmio_offsets[] = {
720
		DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET, DU3_REG_OFFSET
721 722
	};

723
	struct rcar_du_device *rcdu = rgrp->dev;
724
	struct platform_device *pdev = to_platform_device(rcdu->dev);
725 726
	struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index];
	struct drm_crtc *crtc = &rcrtc->crtc;
727
	struct drm_plane *primary;
728
	unsigned int irqflags;
729 730
	struct clk *clk;
	char clk_name[9];
731 732
	char *name;
	int irq;
733 734
	int ret;

735
	/* Get the CRTC clock and the optional external clock. */
736 737 738 739 740 741 742 743 744 745 746 747 748
	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);
	}

749 750 751 752 753 754 755 756 757
	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;
	}

758 759
	init_waitqueue_head(&rcrtc->flip_wait);

760
	rcrtc->group = rgrp;
761
	rcrtc->mmio_offset = mmio_offsets[index];
762 763
	rcrtc->index = index;

764
	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
765
		primary = &rcrtc->vsp->planes[rcrtc->vsp_pipe].plane;
766 767 768 769
	else
		primary = &rgrp->planes[index % 2].plane;

	ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary,
770
					NULL, &crtc_funcs, NULL);
771 772 773 774 775
	if (ret < 0)
		return ret;

	drm_crtc_helper_add(crtc, &crtc_helper_funcs);

776 777 778
	/* Start with vertical blanking interrupt reporting disabled. */
	drm_crtc_vblank_off(crtc);

779 780 781 782 783 784 785 786 787 788 789
	/* 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);
790
		return irq;
791 792 793 794 795 796 797 798 799 800
	}

	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;
	}

801 802
	return 0;
}