2 * rcar_du_crtc.c -- R-Car Display Unit CRTCs
4 * Copyright (C) 2013-2014 Renesas Electronics Corporation
6 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
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.
14 #include <linux/clk.h>
15 #include <linux/mutex.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>
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"
32 static u32
rcar_du_crtc_read(struct rcar_du_crtc
*rcrtc
, u32 reg
)
34 struct rcar_du_device
*rcdu
= rcrtc
->group
->dev
;
36 return rcar_du_read(rcdu
, rcrtc
->mmio_offset
+ reg
);
39 static void rcar_du_crtc_write(struct rcar_du_crtc
*rcrtc
, u32 reg
, u32 data
)
41 struct rcar_du_device
*rcdu
= rcrtc
->group
->dev
;
43 rcar_du_write(rcdu
, rcrtc
->mmio_offset
+ reg
, data
);
46 static void rcar_du_crtc_clr(struct rcar_du_crtc
*rcrtc
, u32 reg
, u32 clr
)
48 struct rcar_du_device
*rcdu
= rcrtc
->group
->dev
;
50 rcar_du_write(rcdu
, rcrtc
->mmio_offset
+ reg
,
51 rcar_du_read(rcdu
, rcrtc
->mmio_offset
+ reg
) & ~clr
);
54 static void rcar_du_crtc_set(struct rcar_du_crtc
*rcrtc
, u32 reg
, u32 set
)
56 struct rcar_du_device
*rcdu
= rcrtc
->group
->dev
;
58 rcar_du_write(rcdu
, rcrtc
->mmio_offset
+ reg
,
59 rcar_du_read(rcdu
, rcrtc
->mmio_offset
+ reg
) | set
);
62 static void rcar_du_crtc_clr_set(struct rcar_du_crtc
*rcrtc
, u32 reg
,
65 struct rcar_du_device
*rcdu
= rcrtc
->group
->dev
;
66 u32 value
= rcar_du_read(rcdu
, rcrtc
->mmio_offset
+ reg
);
68 rcar_du_write(rcdu
, rcrtc
->mmio_offset
+ reg
, (value
& ~clr
) | set
);
71 static int rcar_du_crtc_get(struct rcar_du_crtc
*rcrtc
)
75 ret
= clk_prepare_enable(rcrtc
->clock
);
79 ret
= clk_prepare_enable(rcrtc
->extclock
);
83 ret
= rcar_du_group_get(rcrtc
->group
);
90 clk_disable_unprepare(rcrtc
->extclock
);
92 clk_disable_unprepare(rcrtc
->clock
);
96 static void rcar_du_crtc_put(struct rcar_du_crtc
*rcrtc
)
98 rcar_du_group_put(rcrtc
->group
);
100 clk_disable_unprepare(rcrtc
->extclock
);
101 clk_disable_unprepare(rcrtc
->clock
);
104 /* -----------------------------------------------------------------------------
108 static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc
*rcrtc
)
110 const struct drm_display_mode
*mode
= &rcrtc
->crtc
.state
->adjusted_mode
;
111 unsigned long mode_clock
= mode
->clock
* 1000;
117 /* Compute the clock divisor and select the internal or external dot
118 * clock based on the requested frequency.
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
;
125 if (rcrtc
->extclock
) {
126 unsigned long extclk
;
127 unsigned long extrate
;
131 extclk
= clk_get_rate(rcrtc
->extclock
);
132 extdiv
= DIV_ROUND_CLOSEST(extclk
, mode_clock
);
133 extdiv
= clamp(extdiv
, 1U, 64U) - 1;
135 rate
= clk
/ (div
+ 1);
136 extrate
= extclk
/ (extdiv
+ 1);
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
;
146 rcar_du_group_write(rcrtc
->group
, rcrtc
->index
% 2 ? ESCR2
: ESCR
,
148 rcar_du_group_write(rcrtc
->group
, rcrtc
->index
% 2 ? OTAR2
: OTAR
, 0);
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
);
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);
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);
174 rcar_du_crtc_write(rcrtc
, DESR
, mode
->htotal
- mode
->hsync_start
);
175 rcar_du_crtc_write(rcrtc
, DEWR
, mode
->hdisplay
);
178 void rcar_du_crtc_route_output(struct drm_crtc
*crtc
,
179 enum rcar_du_output output
)
181 struct rcar_du_crtc
*rcrtc
= to_rcar_crtc(crtc
);
182 struct rcar_du_device
*rcdu
= rcrtc
->group
->dev
;
184 /* Store the route from the CRTC output to the DU output. The DU will be
185 * configured when starting the CRTC.
187 rcrtc
->outputs
|= BIT(output
);
189 /* Store RGB routing to DPAD0, the hardware will be configured when
192 if (output
== RCAR_DU_OUTPUT_DPAD0
)
193 rcdu
->dpad0_source
= rcrtc
->index
;
196 static unsigned int plane_zpos(struct rcar_du_plane
*plane
)
198 return to_rcar_du_plane_state(plane
->plane
.state
)->zpos
;
201 static const struct rcar_du_format_info
*
202 plane_format(struct rcar_du_plane
*plane
)
204 return to_rcar_du_plane_state(plane
->plane
.state
)->format
;
207 static void rcar_du_crtc_update_planes(struct rcar_du_crtc
*rcrtc
)
209 struct rcar_du_plane
*planes
[RCAR_DU_NUM_HW_PLANES
];
210 unsigned int num_planes
= 0;
211 unsigned int prio
= 0;
216 for (i
= 0; i
< ARRAY_SIZE(rcrtc
->group
->planes
.planes
); ++i
) {
217 struct rcar_du_plane
*plane
= &rcrtc
->group
->planes
.planes
[i
];
220 if (plane
->plane
.state
->crtc
!= &rcrtc
->crtc
)
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
))
227 planes
[j
] = planes
[j
-1];
231 prio
+= plane_format(plane
)->planes
* 4;
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
;
240 dspr
|= (index
+ 1) << prio
;
241 dptsr
|= DPTSR_PnDK(index
) | DPTSR_PnTS(index
);
243 if (plane_format(plane
)->planes
== 2) {
244 index
= (index
+ 1) % 8;
247 dspr
|= (index
+ 1) << prio
;
248 dptsr
|= DPTSR_PnDK(index
) | DPTSR_PnTS(index
);
252 /* Select display timing and dot clock generator 2 for planes associated
253 * with superposition controller 2.
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.
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
);
269 mutex_unlock(&rcrtc
->group
->lock
);
272 rcar_du_group_write(rcrtc
->group
, rcrtc
->index
% 2 ? DS2PR
: DS1PR
,
276 /* -----------------------------------------------------------------------------
280 void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc
*rcrtc
,
281 struct drm_file
*file
)
283 struct drm_pending_vblank_event
*event
;
284 struct drm_device
*dev
= rcrtc
->crtc
.dev
;
287 /* Destroy the pending vertical blanking event associated with the
288 * pending page flip, if any, and disable vertical blanking interrupts.
290 spin_lock_irqsave(&dev
->event_lock
, flags
);
291 event
= rcrtc
->event
;
292 if (event
&& event
->base
.file_priv
== file
) {
294 event
->base
.destroy(&event
->base
);
295 drm_crtc_vblank_put(&rcrtc
->crtc
);
297 spin_unlock_irqrestore(&dev
->event_lock
, flags
);
300 static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc
*rcrtc
)
302 struct drm_pending_vblank_event
*event
;
303 struct drm_device
*dev
= rcrtc
->crtc
.dev
;
306 spin_lock_irqsave(&dev
->event_lock
, flags
);
307 event
= rcrtc
->event
;
309 spin_unlock_irqrestore(&dev
->event_lock
, flags
);
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
);
319 drm_crtc_vblank_put(&rcrtc
->crtc
);
322 static bool rcar_du_crtc_page_flip_pending(struct rcar_du_crtc
*rcrtc
)
324 struct drm_device
*dev
= rcrtc
->crtc
.dev
;
328 spin_lock_irqsave(&dev
->event_lock
, flags
);
329 pending
= rcrtc
->event
!= NULL
;
330 spin_unlock_irqrestore(&dev
->event_lock
, flags
);
335 static void rcar_du_crtc_wait_page_flip(struct rcar_du_crtc
*rcrtc
)
337 struct rcar_du_device
*rcdu
= rcrtc
->group
->dev
;
339 if (wait_event_timeout(rcrtc
->flip_wait
,
340 !rcar_du_crtc_page_flip_pending(rcrtc
),
341 msecs_to_jiffies(50)))
344 dev_warn(rcdu
->dev
, "page flip timeout\n");
346 rcar_du_crtc_finish_page_flip(rcrtc
);
349 /* -----------------------------------------------------------------------------
350 * Start/Stop and Suspend/Resume
353 static void rcar_du_crtc_start(struct rcar_du_crtc
*rcrtc
)
355 struct drm_crtc
*crtc
= &rcrtc
->crtc
;
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));
365 /* Configure display timings and output routing */
366 rcar_du_crtc_set_display_timing(rcrtc
);
367 rcar_du_group_set_routing(rcrtc
->group
);
369 /* Start with all planes disabled. */
370 rcar_du_group_write(rcrtc
->group
, rcrtc
->index
% 2 ? DS2PR
: DS1PR
, 0);
372 /* Select master sync mode. This enables display operation in master
373 * sync mode (with the HSYNC and VSYNC signals configured as outputs and
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) |
381 rcar_du_group_start_stop(rcrtc
->group
, true);
383 /* Turn vertical blanking interrupt reporting back on. */
384 drm_crtc_vblank_on(crtc
);
386 rcrtc
->started
= true;
389 static void rcar_du_crtc_stop(struct rcar_du_crtc
*rcrtc
)
391 struct drm_crtc
*crtc
= &rcrtc
->crtc
;
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.
400 rcar_du_crtc_wait_page_flip(rcrtc
);
401 drm_crtc_vblank_off(crtc
);
403 /* Select switch sync mode. This stops display operation and configures
404 * the HSYNC and VSYNC signals as inputs.
406 rcar_du_crtc_clr_set(rcrtc
, DSYSR
, DSYSR_TVM_MASK
, DSYSR_TVM_SWITCH
);
408 rcar_du_group_start_stop(rcrtc
->group
, false);
410 rcrtc
->started
= false;
413 void rcar_du_crtc_suspend(struct rcar_du_crtc
*rcrtc
)
415 rcar_du_crtc_stop(rcrtc
);
416 rcar_du_crtc_put(rcrtc
);
419 void rcar_du_crtc_resume(struct rcar_du_crtc
*rcrtc
)
426 rcar_du_crtc_get(rcrtc
);
427 rcar_du_crtc_start(rcrtc
);
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
];
433 if (plane
->plane
.state
->crtc
!= &rcrtc
->crtc
)
436 rcar_du_plane_setup(plane
);
439 rcar_du_crtc_update_planes(rcrtc
);
442 /* -----------------------------------------------------------------------------
446 static void rcar_du_crtc_enable(struct drm_crtc
*crtc
)
448 struct rcar_du_crtc
*rcrtc
= to_rcar_crtc(crtc
);
453 rcar_du_crtc_get(rcrtc
);
454 rcar_du_crtc_start(rcrtc
);
456 rcrtc
->enabled
= true;
459 static void rcar_du_crtc_disable(struct drm_crtc
*crtc
)
461 struct rcar_du_crtc
*rcrtc
= to_rcar_crtc(crtc
);
466 rcar_du_crtc_stop(rcrtc
);
467 rcar_du_crtc_put(rcrtc
);
469 rcrtc
->enabled
= false;
473 static bool rcar_du_crtc_mode_fixup(struct drm_crtc
*crtc
,
474 const struct drm_display_mode
*mode
,
475 struct drm_display_mode
*adjusted_mode
)
477 /* TODO Fixup modes */
481 static void rcar_du_crtc_atomic_begin(struct drm_crtc
*crtc
)
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
;
489 WARN_ON(drm_crtc_vblank_get(crtc
) != 0);
491 spin_lock_irqsave(&dev
->event_lock
, flags
);
492 rcrtc
->event
= event
;
493 spin_unlock_irqrestore(&dev
->event_lock
, flags
);
497 static void rcar_du_crtc_atomic_flush(struct drm_crtc
*crtc
)
499 struct rcar_du_crtc
*rcrtc
= to_rcar_crtc(crtc
);
501 rcar_du_crtc_update_planes(rcrtc
);
504 static 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
,
512 static 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
,
521 /* -----------------------------------------------------------------------------
525 static irqreturn_t
rcar_du_crtc_irq(int irq
, void *arg
)
527 struct rcar_du_crtc
*rcrtc
= arg
;
528 irqreturn_t ret
= IRQ_NONE
;
531 status
= rcar_du_crtc_read(rcrtc
, DSSR
);
532 rcar_du_crtc_write(rcrtc
, DSRCR
, status
& DSRCR_MASK
);
534 if (status
& DSSR_FRM
) {
535 drm_handle_vblank(rcrtc
->crtc
.dev
, rcrtc
->index
);
536 rcar_du_crtc_finish_page_flip(rcrtc
);
543 /* -----------------------------------------------------------------------------
547 int rcar_du_crtc_create(struct rcar_du_group
*rgrp
, unsigned int index
)
549 static const unsigned int mmio_offsets
[] = {
550 DU0_REG_OFFSET
, DU1_REG_OFFSET
, DU2_REG_OFFSET
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
;
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
);
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
);
578 sprintf(clk_name
, "dclkin.%u", index
);
579 clk
= devm_clk_get(rcdu
->dev
, clk_name
);
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
;
587 init_waitqueue_head(&rcrtc
->flip_wait
);
590 rcrtc
->mmio_offset
= mmio_offsets
[index
];
591 rcrtc
->index
= index
;
592 rcrtc
->enabled
= false;
594 ret
= drm_crtc_init_with_planes(rcdu
->ddev
, crtc
,
595 &rgrp
->planes
.planes
[index
% 2].plane
,
600 drm_crtc_helper_add(crtc
, &crtc_helper_funcs
);
602 /* Start with vertical blanking interrupt reporting disabled. */
603 drm_crtc_vblank_off(crtc
);
605 /* Register the interrupt handler. */
606 if (rcar_du_has(rcdu
, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
)) {
607 irq
= platform_get_irq(pdev
, index
);
610 irq
= platform_get_irq(pdev
, 0);
611 irqflags
= IRQF_SHARED
;
615 dev_err(rcdu
->dev
, "no IRQ for CRTC %u\n", index
);
619 ret
= devm_request_irq(rcdu
->dev
, irq
, rcar_du_crtc_irq
, irqflags
,
620 dev_name(rcdu
->dev
), rcrtc
);
623 "failed to register IRQ for CRTC %u\n", index
);
630 void rcar_du_crtc_enable_vblank(struct rcar_du_crtc
*rcrtc
, bool enable
)
633 rcar_du_crtc_write(rcrtc
, DSRCR
, DSRCR_VBCL
);
634 rcar_du_crtc_set(rcrtc
, DIER
, DIER_VBE
);
636 rcar_du_crtc_clr(rcrtc
, DIER
, DIER_VBE
);