1/* 2 * rcar_du_crtc.c -- R-Car Display Unit CRTCs 3 * 4 * Copyright (C) 2013-2014 Renesas Electronics Corporation 5 * 6 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 */ 13 14#include <linux/clk.h> 15#include <linux/mutex.h> 16 17#include <drm/drmP.h> 18#include <drm/drm_atomic.h> 19#include <drm/drm_atomic_helper.h> 20#include <drm/drm_crtc.h> 21#include <drm/drm_crtc_helper.h> 22#include <drm/drm_fb_cma_helper.h> 23#include <drm/drm_gem_cma_helper.h> 24#include <drm/drm_plane_helper.h> 25 26#include "rcar_du_crtc.h" 27#include "rcar_du_drv.h" 28#include "rcar_du_kms.h" 29#include "rcar_du_plane.h" 30#include "rcar_du_regs.h" 31 32static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg) 33{ 34 struct rcar_du_device *rcdu = rcrtc->group->dev; 35 36 return rcar_du_read(rcdu, rcrtc->mmio_offset + reg); 37} 38 39static void rcar_du_crtc_write(struct rcar_du_crtc *rcrtc, u32 reg, u32 data) 40{ 41 struct rcar_du_device *rcdu = rcrtc->group->dev; 42 43 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, data); 44} 45 46static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr) 47{ 48 struct rcar_du_device *rcdu = rcrtc->group->dev; 49 50 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, 51 rcar_du_read(rcdu, rcrtc->mmio_offset + reg) & ~clr); 52} 53 54static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set) 55{ 56 struct rcar_du_device *rcdu = rcrtc->group->dev; 57 58 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, 59 rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set); 60} 61 62static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg, 63 u32 clr, u32 set) 64{ 65 struct rcar_du_device *rcdu = rcrtc->group->dev; 66 u32 value = rcar_du_read(rcdu, rcrtc->mmio_offset + reg); 67 68 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set); 69} 70 71static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc) 72{ 73 int ret; 74 75 ret = clk_prepare_enable(rcrtc->clock); 76 if (ret < 0) 77 return ret; 78 79 ret = clk_prepare_enable(rcrtc->extclock); 80 if (ret < 0) 81 goto error_clock; 82 83 ret = rcar_du_group_get(rcrtc->group); 84 if (ret < 0) 85 goto error_group; 86 87 return 0; 88 89error_group: 90 clk_disable_unprepare(rcrtc->extclock); 91error_clock: 92 clk_disable_unprepare(rcrtc->clock); 93 return ret; 94} 95 96static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc) 97{ 98 rcar_du_group_put(rcrtc->group); 99 100 clk_disable_unprepare(rcrtc->extclock); 101 clk_disable_unprepare(rcrtc->clock); 102} 103 104/* ----------------------------------------------------------------------------- 105 * Hardware Setup 106 */ 107 108static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) 109{ 110 const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode; 111 unsigned long mode_clock = mode->clock * 1000; 112 unsigned long clk; 113 u32 value; 114 u32 escr; 115 u32 div; 116 117 /* Compute the clock divisor and select the internal or external dot 118 * clock based on the requested frequency. 119 */ 120 clk = clk_get_rate(rcrtc->clock); 121 div = DIV_ROUND_CLOSEST(clk, mode_clock); 122 div = clamp(div, 1U, 64U) - 1; 123 escr = div | ESCR_DCLKSEL_CLKS; 124 125 if (rcrtc->extclock) { 126 unsigned long extclk; 127 unsigned long extrate; 128 unsigned long rate; 129 u32 extdiv; 130 131 extclk = clk_get_rate(rcrtc->extclock); 132 extdiv = DIV_ROUND_CLOSEST(extclk, mode_clock); 133 extdiv = clamp(extdiv, 1U, 64U) - 1; 134 135 rate = clk / (div + 1); 136 extrate = extclk / (extdiv + 1); 137 138 if (abs((long)extrate - (long)mode_clock) < 139 abs((long)rate - (long)mode_clock)) { 140 dev_dbg(rcrtc->group->dev->dev, 141 "crtc%u: using external clock\n", rcrtc->index); 142 escr = extdiv | ESCR_DCLKSEL_DCLKIN; 143 } 144 } 145 146 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? ESCR2 : ESCR, 147 escr); 148 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0); 149 150 /* Signal polarities */ 151 value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL) 152 | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : DSMR_HSL) 153 | DSMR_DIPM_DE | DSMR_CSPM; 154 rcar_du_crtc_write(rcrtc, DSMR, value); 155 156 /* Display timings */ 157 rcar_du_crtc_write(rcrtc, HDSR, mode->htotal - mode->hsync_start - 19); 158 rcar_du_crtc_write(rcrtc, HDER, mode->htotal - mode->hsync_start + 159 mode->hdisplay - 19); 160 rcar_du_crtc_write(rcrtc, HSWR, mode->hsync_end - 161 mode->hsync_start - 1); 162 rcar_du_crtc_write(rcrtc, HCR, mode->htotal - 1); 163 164 rcar_du_crtc_write(rcrtc, VDSR, mode->crtc_vtotal - 165 mode->crtc_vsync_end - 2); 166 rcar_du_crtc_write(rcrtc, VDER, mode->crtc_vtotal - 167 mode->crtc_vsync_end + 168 mode->crtc_vdisplay - 2); 169 rcar_du_crtc_write(rcrtc, VSPR, mode->crtc_vtotal - 170 mode->crtc_vsync_end + 171 mode->crtc_vsync_start - 1); 172 rcar_du_crtc_write(rcrtc, VCR, mode->crtc_vtotal - 1); 173 174 rcar_du_crtc_write(rcrtc, DESR, mode->htotal - mode->hsync_start); 175 rcar_du_crtc_write(rcrtc, DEWR, mode->hdisplay); 176} 177 178void rcar_du_crtc_route_output(struct drm_crtc *crtc, 179 enum rcar_du_output output) 180{ 181 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 182 struct rcar_du_device *rcdu = rcrtc->group->dev; 183 184 /* Store the route from the CRTC output to the DU output. The DU will be 185 * configured when starting the CRTC. 186 */ 187 rcrtc->outputs |= BIT(output); 188 189 /* Store RGB routing to DPAD0, the hardware will be configured when 190 * starting the CRTC. 191 */ 192 if (output == RCAR_DU_OUTPUT_DPAD0) 193 rcdu->dpad0_source = rcrtc->index; 194} 195 196static unsigned int plane_zpos(struct rcar_du_plane *plane) 197{ 198 return to_rcar_du_plane_state(plane->plane.state)->zpos; 199} 200 201static const struct rcar_du_format_info * 202plane_format(struct rcar_du_plane *plane) 203{ 204 return to_rcar_du_plane_state(plane->plane.state)->format; 205} 206 207static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) 208{ 209 struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES]; 210 unsigned int num_planes = 0; 211 unsigned int prio = 0; 212 unsigned int i; 213 u32 dptsr = 0; 214 u32 dspr = 0; 215 216 for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) { 217 struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i]; 218 unsigned int j; 219 220 if (plane->plane.state->crtc != &rcrtc->crtc) 221 continue; 222 223 /* Insert the plane in the sorted planes array. */ 224 for (j = num_planes++; j > 0; --j) { 225 if (plane_zpos(planes[j-1]) <= plane_zpos(plane)) 226 break; 227 planes[j] = planes[j-1]; 228 } 229 230 planes[j] = plane; 231 prio += plane_format(plane)->planes * 4; 232 } 233 234 for (i = 0; i < num_planes; ++i) { 235 struct rcar_du_plane *plane = planes[i]; 236 struct drm_plane_state *state = plane->plane.state; 237 unsigned int index = to_rcar_du_plane_state(state)->hwindex; 238 239 prio -= 4; 240 dspr |= (index + 1) << prio; 241 dptsr |= DPTSR_PnDK(index) | DPTSR_PnTS(index); 242 243 if (plane_format(plane)->planes == 2) { 244 index = (index + 1) % 8; 245 246 prio -= 4; 247 dspr |= (index + 1) << prio; 248 dptsr |= DPTSR_PnDK(index) | DPTSR_PnTS(index); 249 } 250 } 251 252 /* Select display timing and dot clock generator 2 for planes associated 253 * with superposition controller 2. 254 */ 255 if (rcrtc->index % 2) { 256 /* The DPTSR register is updated when the display controller is 257 * stopped. We thus need to restart the DU. Once again, sorry 258 * for the flicker. One way to mitigate the issue would be to 259 * pre-associate planes with CRTCs (either with a fixed 4/4 260 * split, or through a module parameter). Flicker would then 261 * occur only if we need to break the pre-association. 262 */ 263 mutex_lock(&rcrtc->group->lock); 264 if (rcar_du_group_read(rcrtc->group, DPTSR) != dptsr) { 265 rcar_du_group_write(rcrtc->group, DPTSR, dptsr); 266 if (rcrtc->group->used_crtcs) 267 rcar_du_group_restart(rcrtc->group); 268 } 269 mutex_unlock(&rcrtc->group->lock); 270 } 271 272 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 273 dspr); 274} 275 276/* ----------------------------------------------------------------------------- 277 * Page Flip 278 */ 279 280void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc, 281 struct drm_file *file) 282{ 283 struct drm_pending_vblank_event *event; 284 struct drm_device *dev = rcrtc->crtc.dev; 285 unsigned long flags; 286 287 /* Destroy the pending vertical blanking event associated with the 288 * pending page flip, if any, and disable vertical blanking interrupts. 289 */ 290 spin_lock_irqsave(&dev->event_lock, flags); 291 event = rcrtc->event; 292 if (event && event->base.file_priv == file) { 293 rcrtc->event = NULL; 294 event->base.destroy(&event->base); 295 drm_crtc_vblank_put(&rcrtc->crtc); 296 } 297 spin_unlock_irqrestore(&dev->event_lock, flags); 298} 299 300static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc) 301{ 302 struct drm_pending_vblank_event *event; 303 struct drm_device *dev = rcrtc->crtc.dev; 304 unsigned long flags; 305 306 spin_lock_irqsave(&dev->event_lock, flags); 307 event = rcrtc->event; 308 rcrtc->event = NULL; 309 spin_unlock_irqrestore(&dev->event_lock, flags); 310 311 if (event == NULL) 312 return; 313 314 spin_lock_irqsave(&dev->event_lock, flags); 315 drm_send_vblank_event(dev, rcrtc->index, event); 316 wake_up(&rcrtc->flip_wait); 317 spin_unlock_irqrestore(&dev->event_lock, flags); 318 319 drm_crtc_vblank_put(&rcrtc->crtc); 320} 321 322static bool rcar_du_crtc_page_flip_pending(struct rcar_du_crtc *rcrtc) 323{ 324 struct drm_device *dev = rcrtc->crtc.dev; 325 unsigned long flags; 326 bool pending; 327 328 spin_lock_irqsave(&dev->event_lock, flags); 329 pending = rcrtc->event != NULL; 330 spin_unlock_irqrestore(&dev->event_lock, flags); 331 332 return pending; 333} 334 335static void rcar_du_crtc_wait_page_flip(struct rcar_du_crtc *rcrtc) 336{ 337 struct rcar_du_device *rcdu = rcrtc->group->dev; 338 339 if (wait_event_timeout(rcrtc->flip_wait, 340 !rcar_du_crtc_page_flip_pending(rcrtc), 341 msecs_to_jiffies(50))) 342 return; 343 344 dev_warn(rcdu->dev, "page flip timeout\n"); 345 346 rcar_du_crtc_finish_page_flip(rcrtc); 347} 348 349/* ----------------------------------------------------------------------------- 350 * Start/Stop and Suspend/Resume 351 */ 352 353static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) 354{ 355 struct drm_crtc *crtc = &rcrtc->crtc; 356 bool interlaced; 357 358 if (rcrtc->started) 359 return; 360 361 /* Set display off and background to black */ 362 rcar_du_crtc_write(rcrtc, DOOR, DOOR_RGB(0, 0, 0)); 363 rcar_du_crtc_write(rcrtc, BPOR, BPOR_RGB(0, 0, 0)); 364 365 /* Configure display timings and output routing */ 366 rcar_du_crtc_set_display_timing(rcrtc); 367 rcar_du_group_set_routing(rcrtc->group); 368 369 /* Start with all planes disabled. */ 370 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0); 371 372 /* Select master sync mode. This enables display operation in master 373 * sync mode (with the HSYNC and VSYNC signals configured as outputs and 374 * actively driven). 375 */ 376 interlaced = rcrtc->crtc.mode.flags & DRM_MODE_FLAG_INTERLACE; 377 rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK | DSYSR_SCM_MASK, 378 (interlaced ? DSYSR_SCM_INT_VIDEO : 0) | 379 DSYSR_TVM_MASTER); 380 381 rcar_du_group_start_stop(rcrtc->group, true); 382 383 /* Turn vertical blanking interrupt reporting back on. */ 384 drm_crtc_vblank_on(crtc); 385 386 rcrtc->started = true; 387} 388 389static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc) 390{ 391 struct drm_crtc *crtc = &rcrtc->crtc; 392 393 if (!rcrtc->started) 394 return; 395 396 /* Disable vertical blanking interrupt reporting. We first need to wait 397 * for page flip completion before stopping the CRTC as userspace 398 * expects page flips to eventually complete. 399 */ 400 rcar_du_crtc_wait_page_flip(rcrtc); 401 drm_crtc_vblank_off(crtc); 402 403 /* Select switch sync mode. This stops display operation and configures 404 * the HSYNC and VSYNC signals as inputs. 405 */ 406 rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH); 407 408 rcar_du_group_start_stop(rcrtc->group, false); 409 410 rcrtc->started = false; 411} 412 413void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc) 414{ 415 rcar_du_crtc_stop(rcrtc); 416 rcar_du_crtc_put(rcrtc); 417} 418 419void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc) 420{ 421 unsigned int i; 422 423 if (!rcrtc->enabled) 424 return; 425 426 rcar_du_crtc_get(rcrtc); 427 rcar_du_crtc_start(rcrtc); 428 429 /* Commit the planes state. */ 430 for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) { 431 struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i]; 432 433 if (plane->plane.state->crtc != &rcrtc->crtc) 434 continue; 435 436 rcar_du_plane_setup(plane); 437 } 438 439 rcar_du_crtc_update_planes(rcrtc); 440} 441 442/* ----------------------------------------------------------------------------- 443 * CRTC Functions 444 */ 445 446static void rcar_du_crtc_enable(struct drm_crtc *crtc) 447{ 448 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 449 450 if (rcrtc->enabled) 451 return; 452 453 rcar_du_crtc_get(rcrtc); 454 rcar_du_crtc_start(rcrtc); 455 456 rcrtc->enabled = true; 457} 458 459static void rcar_du_crtc_disable(struct drm_crtc *crtc) 460{ 461 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 462 463 if (!rcrtc->enabled) 464 return; 465 466 rcar_du_crtc_stop(rcrtc); 467 rcar_du_crtc_put(rcrtc); 468 469 rcrtc->enabled = false; 470 rcrtc->outputs = 0; 471} 472 473static bool rcar_du_crtc_mode_fixup(struct drm_crtc *crtc, 474 const struct drm_display_mode *mode, 475 struct drm_display_mode *adjusted_mode) 476{ 477 /* TODO Fixup modes */ 478 return true; 479} 480 481static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc) 482{ 483 struct drm_pending_vblank_event *event = crtc->state->event; 484 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 485 struct drm_device *dev = rcrtc->crtc.dev; 486 unsigned long flags; 487 488 if (event) { 489 WARN_ON(drm_crtc_vblank_get(crtc) != 0); 490 491 spin_lock_irqsave(&dev->event_lock, flags); 492 rcrtc->event = event; 493 spin_unlock_irqrestore(&dev->event_lock, flags); 494 } 495} 496 497static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc) 498{ 499 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 500 501 rcar_du_crtc_update_planes(rcrtc); 502} 503 504static const struct drm_crtc_helper_funcs crtc_helper_funcs = { 505 .mode_fixup = rcar_du_crtc_mode_fixup, 506 .disable = rcar_du_crtc_disable, 507 .enable = rcar_du_crtc_enable, 508 .atomic_begin = rcar_du_crtc_atomic_begin, 509 .atomic_flush = rcar_du_crtc_atomic_flush, 510}; 511 512static const struct drm_crtc_funcs crtc_funcs = { 513 .reset = drm_atomic_helper_crtc_reset, 514 .destroy = drm_crtc_cleanup, 515 .set_config = drm_atomic_helper_set_config, 516 .page_flip = drm_atomic_helper_page_flip, 517 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, 518 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, 519}; 520 521/* ----------------------------------------------------------------------------- 522 * Interrupt Handling 523 */ 524 525static irqreturn_t rcar_du_crtc_irq(int irq, void *arg) 526{ 527 struct rcar_du_crtc *rcrtc = arg; 528 irqreturn_t ret = IRQ_NONE; 529 u32 status; 530 531 status = rcar_du_crtc_read(rcrtc, DSSR); 532 rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK); 533 534 if (status & DSSR_FRM) { 535 drm_handle_vblank(rcrtc->crtc.dev, rcrtc->index); 536 rcar_du_crtc_finish_page_flip(rcrtc); 537 ret = IRQ_HANDLED; 538 } 539 540 return ret; 541} 542 543/* ----------------------------------------------------------------------------- 544 * Initialization 545 */ 546 547int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) 548{ 549 static const unsigned int mmio_offsets[] = { 550 DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET 551 }; 552 553 struct rcar_du_device *rcdu = rgrp->dev; 554 struct platform_device *pdev = to_platform_device(rcdu->dev); 555 struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; 556 struct drm_crtc *crtc = &rcrtc->crtc; 557 unsigned int irqflags; 558 struct clk *clk; 559 char clk_name[9]; 560 char *name; 561 int irq; 562 int ret; 563 564 /* Get the CRTC clock and the optional external clock. */ 565 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { 566 sprintf(clk_name, "du.%u", index); 567 name = clk_name; 568 } else { 569 name = NULL; 570 } 571 572 rcrtc->clock = devm_clk_get(rcdu->dev, name); 573 if (IS_ERR(rcrtc->clock)) { 574 dev_err(rcdu->dev, "no clock for CRTC %u\n", index); 575 return PTR_ERR(rcrtc->clock); 576 } 577 578 sprintf(clk_name, "dclkin.%u", index); 579 clk = devm_clk_get(rcdu->dev, clk_name); 580 if (!IS_ERR(clk)) { 581 rcrtc->extclock = clk; 582 } else if (PTR_ERR(rcrtc->clock) == -EPROBE_DEFER) { 583 dev_info(rcdu->dev, "can't get external clock %u\n", index); 584 return -EPROBE_DEFER; 585 } 586 587 init_waitqueue_head(&rcrtc->flip_wait); 588 589 rcrtc->group = rgrp; 590 rcrtc->mmio_offset = mmio_offsets[index]; 591 rcrtc->index = index; 592 rcrtc->enabled = false; 593 594 ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, 595 &rgrp->planes.planes[index % 2].plane, 596 NULL, &crtc_funcs); 597 if (ret < 0) 598 return ret; 599 600 drm_crtc_helper_add(crtc, &crtc_helper_funcs); 601 602 /* Start with vertical blanking interrupt reporting disabled. */ 603 drm_crtc_vblank_off(crtc); 604 605 /* Register the interrupt handler. */ 606 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { 607 irq = platform_get_irq(pdev, index); 608 irqflags = 0; 609 } else { 610 irq = platform_get_irq(pdev, 0); 611 irqflags = IRQF_SHARED; 612 } 613 614 if (irq < 0) { 615 dev_err(rcdu->dev, "no IRQ for CRTC %u\n", index); 616 return irq; 617 } 618 619 ret = devm_request_irq(rcdu->dev, irq, rcar_du_crtc_irq, irqflags, 620 dev_name(rcdu->dev), rcrtc); 621 if (ret < 0) { 622 dev_err(rcdu->dev, 623 "failed to register IRQ for CRTC %u\n", index); 624 return ret; 625 } 626 627 return 0; 628} 629 630void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable) 631{ 632 if (enable) { 633 rcar_du_crtc_write(rcrtc, DSRCR, DSRCR_VBCL); 634 rcar_du_crtc_set(rcrtc, DIER, DIER_VBE); 635 } else { 636 rcar_du_crtc_clr(rcrtc, DIER, DIER_VBE); 637 } 638} 639