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