1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/clk.h>
15#include <linux/mutex.h>
16#include <linux/sys_soc.h>
17
18#include <drm/drmP.h>
19#include <drm/drm_atomic.h>
20#include <drm/drm_atomic_helper.h>
21#include <drm/drm_crtc.h>
22#include <drm/drm_crtc_helper.h>
23#include <drm/drm_fb_cma_helper.h>
24#include <drm/drm_gem_cma_helper.h>
25#include <drm/drm_plane_helper.h>
26
27#include "rcar_du_crtc.h"
28#include "rcar_du_drv.h"
29#include "rcar_du_kms.h"
30#include "rcar_du_plane.h"
31#include "rcar_du_regs.h"
32#include "rcar_du_vsp.h"
33
34static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
35{
36 struct rcar_du_device *rcdu = rcrtc->group->dev;
37
38 return rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
39}
40
41static void rcar_du_crtc_write(struct rcar_du_crtc *rcrtc, u32 reg, u32 data)
42{
43 struct rcar_du_device *rcdu = rcrtc->group->dev;
44
45 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, data);
46}
47
48static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr)
49{
50 struct rcar_du_device *rcdu = rcrtc->group->dev;
51
52 rcar_du_write(rcdu, rcrtc->mmio_offset + reg,
53 rcar_du_read(rcdu, rcrtc->mmio_offset + reg) & ~clr);
54}
55
56static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set)
57{
58 struct rcar_du_device *rcdu = rcrtc->group->dev;
59
60 rcar_du_write(rcdu, rcrtc->mmio_offset + reg,
61 rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set);
62}
63
64static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg,
65 u32 clr, u32 set)
66{
67 struct rcar_du_device *rcdu = rcrtc->group->dev;
68 u32 value = rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
69
70 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
71}
72
73static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
74{
75 int ret;
76
77 ret = clk_prepare_enable(rcrtc->clock);
78 if (ret < 0)
79 return ret;
80
81 ret = clk_prepare_enable(rcrtc->extclock);
82 if (ret < 0)
83 goto error_clock;
84
85 ret = rcar_du_group_get(rcrtc->group);
86 if (ret < 0)
87 goto error_group;
88
89 return 0;
90
91error_group:
92 clk_disable_unprepare(rcrtc->extclock);
93error_clock:
94 clk_disable_unprepare(rcrtc->clock);
95 return ret;
96}
97
98static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
99{
100 rcar_du_group_put(rcrtc->group);
101
102 clk_disable_unprepare(rcrtc->extclock);
103 clk_disable_unprepare(rcrtc->clock);
104}
105
106
107
108
109
110struct dpll_info {
111 unsigned int output;
112 unsigned int fdpll;
113 unsigned int n;
114 unsigned int m;
115};
116
117static void rcar_du_dpll_divider(struct rcar_du_crtc *rcrtc,
118 struct dpll_info *dpll,
119 unsigned long input,
120 unsigned long target)
121{
122 unsigned long best_diff = (unsigned long)-1;
123 unsigned long diff;
124 unsigned int fdpll;
125 unsigned int m;
126 unsigned int n;
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156 for (m = 0; m < 4; m++) {
157 for (n = 119; n > 38; n--) {
158
159
160
161
162
163
164
165
166
167 unsigned long fout = input * (n + 1) / (m + 1);
168
169 if (fout < 1000 || fout > 2048 * 1000 * 1000U)
170 continue;
171
172 for (fdpll = 1; fdpll < 32; fdpll++) {
173 unsigned long output;
174
175 output = fout / (fdpll + 1);
176 if (output >= 400 * 1000 * 1000)
177 continue;
178
179 diff = abs((long)output - (long)target);
180 if (best_diff > diff) {
181 best_diff = diff;
182 dpll->n = n;
183 dpll->m = m;
184 dpll->fdpll = fdpll;
185 dpll->output = output;
186 }
187
188 if (diff == 0)
189 goto done;
190 }
191 }
192 }
193
194done:
195 dev_dbg(rcrtc->group->dev->dev,
196 "output:%u, fdpll:%u, n:%u, m:%u, diff:%lu\n",
197 dpll->output, dpll->fdpll, dpll->n, dpll->m,
198 best_diff);
199}
200
201static const struct soc_device_attribute rcar_du_r8a7795_es1[] = {
202 { .soc_id = "r8a7795", .revision = "ES1.*" },
203 { }
204};
205
206static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
207{
208 const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode;
209 struct rcar_du_device *rcdu = rcrtc->group->dev;
210 unsigned long mode_clock = mode->clock * 1000;
211 unsigned long clk;
212 u32 value;
213 u32 escr;
214 u32 div;
215
216
217
218
219
220 clk = clk_get_rate(rcrtc->clock);
221 div = DIV_ROUND_CLOSEST(clk, mode_clock);
222 div = clamp(div, 1U, 64U) - 1;
223 escr = div | ESCR_DCLKSEL_CLKS;
224
225 if (rcrtc->extclock) {
226 struct dpll_info dpll = { 0 };
227 unsigned long extclk;
228 unsigned long extrate;
229 unsigned long rate;
230 u32 extdiv;
231
232 extclk = clk_get_rate(rcrtc->extclock);
233 if (rcdu->info->dpll_ch & (1 << rcrtc->index)) {
234 unsigned long target = mode_clock;
235
236
237
238
239
240
241
242
243
244 if (soc_device_match(rcar_du_r8a7795_es1))
245 target *= 2;
246
247 rcar_du_dpll_divider(rcrtc, &dpll, extclk, target);
248 extclk = dpll.output;
249 }
250
251 extdiv = DIV_ROUND_CLOSEST(extclk, mode_clock);
252 extdiv = clamp(extdiv, 1U, 64U) - 1;
253
254 rate = clk / (div + 1);
255 extrate = extclk / (extdiv + 1);
256
257 if (abs((long)extrate - (long)mode_clock) <
258 abs((long)rate - (long)mode_clock)) {
259
260 if (rcdu->info->dpll_ch & (1 << rcrtc->index)) {
261 u32 dpllcr = DPLLCR_CODE | DPLLCR_CLKE
262 | DPLLCR_FDPLL(dpll.fdpll)
263 | DPLLCR_N(dpll.n) | DPLLCR_M(dpll.m)
264 | DPLLCR_STBY;
265
266 if (rcrtc->index == 1)
267 dpllcr |= DPLLCR_PLCS1
268 | DPLLCR_INCS_DOTCLKIN1;
269 else
270 dpllcr |= DPLLCR_PLCS0
271 | DPLLCR_INCS_DOTCLKIN0;
272
273 rcar_du_group_write(rcrtc->group, DPLLCR,
274 dpllcr);
275 }
276
277 escr = ESCR_DCLKSEL_DCLKIN | extdiv;
278 }
279
280 dev_dbg(rcrtc->group->dev->dev,
281 "mode clock %lu extrate %lu rate %lu ESCR 0x%08x\n",
282 mode_clock, extrate, rate, escr);
283 }
284
285 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? ESCR2 : ESCR,
286 escr);
287 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0);
288
289
290 value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0)
291 | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0)
292 | DSMR_DIPM_DISP | DSMR_CSPM;
293 rcar_du_crtc_write(rcrtc, DSMR, value);
294
295
296 rcar_du_crtc_write(rcrtc, HDSR, mode->htotal - mode->hsync_start - 19);
297 rcar_du_crtc_write(rcrtc, HDER, mode->htotal - mode->hsync_start +
298 mode->hdisplay - 19);
299 rcar_du_crtc_write(rcrtc, HSWR, mode->hsync_end -
300 mode->hsync_start - 1);
301 rcar_du_crtc_write(rcrtc, HCR, mode->htotal - 1);
302
303 rcar_du_crtc_write(rcrtc, VDSR, mode->crtc_vtotal -
304 mode->crtc_vsync_end - 2);
305 rcar_du_crtc_write(rcrtc, VDER, mode->crtc_vtotal -
306 mode->crtc_vsync_end +
307 mode->crtc_vdisplay - 2);
308 rcar_du_crtc_write(rcrtc, VSPR, mode->crtc_vtotal -
309 mode->crtc_vsync_end +
310 mode->crtc_vsync_start - 1);
311 rcar_du_crtc_write(rcrtc, VCR, mode->crtc_vtotal - 1);
312
313 rcar_du_crtc_write(rcrtc, DESR, mode->htotal - mode->hsync_start - 1);
314 rcar_du_crtc_write(rcrtc, DEWR, mode->hdisplay);
315}
316
317void rcar_du_crtc_route_output(struct drm_crtc *crtc,
318 enum rcar_du_output output)
319{
320 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
321 struct rcar_du_device *rcdu = rcrtc->group->dev;
322
323
324
325
326
327 rcrtc->outputs |= BIT(output);
328
329
330
331
332
333 if (output == RCAR_DU_OUTPUT_DPAD0)
334 rcdu->dpad0_source = rcrtc->index;
335}
336
337static unsigned int plane_zpos(struct rcar_du_plane *plane)
338{
339 return plane->plane.state->normalized_zpos;
340}
341
342static const struct rcar_du_format_info *
343plane_format(struct rcar_du_plane *plane)
344{
345 return to_rcar_plane_state(plane->plane.state)->format;
346}
347
348static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
349{
350 struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
351 struct rcar_du_device *rcdu = rcrtc->group->dev;
352 unsigned int num_planes = 0;
353 unsigned int dptsr_planes;
354 unsigned int hwplanes = 0;
355 unsigned int prio = 0;
356 unsigned int i;
357 u32 dspr = 0;
358
359 for (i = 0; i < rcrtc->group->num_planes; ++i) {
360 struct rcar_du_plane *plane = &rcrtc->group->planes[i];
361 unsigned int j;
362
363 if (plane->plane.state->crtc != &rcrtc->crtc ||
364 !plane->plane.state->visible)
365 continue;
366
367
368 for (j = num_planes++; j > 0; --j) {
369 if (plane_zpos(planes[j-1]) <= plane_zpos(plane))
370 break;
371 planes[j] = planes[j-1];
372 }
373
374 planes[j] = plane;
375 prio += plane_format(plane)->planes * 4;
376 }
377
378 for (i = 0; i < num_planes; ++i) {
379 struct rcar_du_plane *plane = planes[i];
380 struct drm_plane_state *state = plane->plane.state;
381 unsigned int index = to_rcar_plane_state(state)->hwindex;
382
383 prio -= 4;
384 dspr |= (index + 1) << prio;
385 hwplanes |= 1 << index;
386
387 if (plane_format(plane)->planes == 2) {
388 index = (index + 1) % 8;
389
390 prio -= 4;
391 dspr |= (index + 1) << prio;
392 hwplanes |= 1 << index;
393 }
394 }
395
396
397 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
398 if (rcdu->info->gen < 3) {
399 dspr = (rcrtc->index % 2) + 1;
400 hwplanes = 1 << (rcrtc->index % 2);
401 } else {
402 dspr = (rcrtc->index % 2) ? 3 : 1;
403 hwplanes = 1 << ((rcrtc->index % 2) ? 2 : 0);
404 }
405 }
406
407
408
409
410
411
412
413
414
415
416 mutex_lock(&rcrtc->group->lock);
417
418 dptsr_planes = rcrtc->index % 2 ? rcrtc->group->dptsr_planes | hwplanes
419 : rcrtc->group->dptsr_planes & ~hwplanes;
420
421 if (dptsr_planes != rcrtc->group->dptsr_planes) {
422 rcar_du_group_write(rcrtc->group, DPTSR,
423 (dptsr_planes << 16) | dptsr_planes);
424 rcrtc->group->dptsr_planes = dptsr_planes;
425
426 if (rcrtc->group->used_crtcs)
427 rcar_du_group_restart(rcrtc->group);
428 }
429
430
431 if (rcrtc->group->need_restart)
432 rcar_du_group_restart(rcrtc->group);
433
434 mutex_unlock(&rcrtc->group->lock);
435
436 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
437 dspr);
438}
439
440
441
442
443
444void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
445{
446 struct drm_pending_vblank_event *event;
447 struct drm_device *dev = rcrtc->crtc.dev;
448 unsigned long flags;
449
450 spin_lock_irqsave(&dev->event_lock, flags);
451 event = rcrtc->event;
452 rcrtc->event = NULL;
453 spin_unlock_irqrestore(&dev->event_lock, flags);
454
455 if (event == NULL)
456 return;
457
458 spin_lock_irqsave(&dev->event_lock, flags);
459 drm_crtc_send_vblank_event(&rcrtc->crtc, event);
460 wake_up(&rcrtc->flip_wait);
461 spin_unlock_irqrestore(&dev->event_lock, flags);
462
463 drm_crtc_vblank_put(&rcrtc->crtc);
464}
465
466static bool rcar_du_crtc_page_flip_pending(struct rcar_du_crtc *rcrtc)
467{
468 struct drm_device *dev = rcrtc->crtc.dev;
469 unsigned long flags;
470 bool pending;
471
472 spin_lock_irqsave(&dev->event_lock, flags);
473 pending = rcrtc->event != NULL;
474 spin_unlock_irqrestore(&dev->event_lock, flags);
475
476 return pending;
477}
478
479static void rcar_du_crtc_wait_page_flip(struct rcar_du_crtc *rcrtc)
480{
481 struct rcar_du_device *rcdu = rcrtc->group->dev;
482
483 if (wait_event_timeout(rcrtc->flip_wait,
484 !rcar_du_crtc_page_flip_pending(rcrtc),
485 msecs_to_jiffies(50)))
486 return;
487
488 dev_warn(rcdu->dev, "page flip timeout\n");
489
490 rcar_du_crtc_finish_page_flip(rcrtc);
491}
492
493
494
495
496
497static void rcar_du_crtc_setup(struct rcar_du_crtc *rcrtc)
498{
499
500 rcar_du_crtc_write(rcrtc, DOOR, DOOR_RGB(0, 0, 0));
501 rcar_du_crtc_write(rcrtc, BPOR, BPOR_RGB(0, 0, 0));
502
503
504 rcar_du_crtc_set_display_timing(rcrtc);
505 rcar_du_group_set_routing(rcrtc->group);
506
507
508 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0);
509
510
511 if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
512 rcar_du_vsp_enable(rcrtc);
513
514
515 drm_crtc_vblank_on(&rcrtc->crtc);
516}
517
518static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
519{
520 bool interlaced;
521
522
523
524
525
526
527 interlaced = rcrtc->crtc.mode.flags & DRM_MODE_FLAG_INTERLACE;
528 rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK | DSYSR_SCM_MASK,
529 (interlaced ? DSYSR_SCM_INT_VIDEO : 0) |
530 DSYSR_TVM_MASTER);
531
532 rcar_du_group_start_stop(rcrtc->group, true);
533}
534
535static void rcar_du_crtc_disable_planes(struct rcar_du_crtc *rcrtc)
536{
537 struct rcar_du_device *rcdu = rcrtc->group->dev;
538 struct drm_crtc *crtc = &rcrtc->crtc;
539 u32 status;
540
541
542 drm_crtc_vblank_get(crtc);
543
544
545
546
547
548
549
550
551 spin_lock_irq(&rcrtc->vblank_lock);
552 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0);
553 status = rcar_du_crtc_read(rcrtc, DSSR);
554 rcrtc->vblank_count = status & DSSR_VBK ? 2 : 1;
555 spin_unlock_irq(&rcrtc->vblank_lock);
556
557 if (!wait_event_timeout(rcrtc->vblank_wait, rcrtc->vblank_count == 0,
558 msecs_to_jiffies(100)))
559 dev_warn(rcdu->dev, "vertical blanking timeout\n");
560
561 drm_crtc_vblank_put(crtc);
562}
563
564static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
565{
566 struct drm_crtc *crtc = &rcrtc->crtc;
567
568
569
570
571
572
573
574
575
576
577
578
579 rcar_du_crtc_disable_planes(rcrtc);
580
581
582
583
584
585
586 rcar_du_crtc_wait_page_flip(rcrtc);
587 drm_crtc_vblank_off(crtc);
588
589
590 if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
591 rcar_du_vsp_disable(rcrtc);
592
593
594
595
596
597 rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);
598
599 rcar_du_group_start_stop(rcrtc->group, false);
600}
601
602
603
604
605
606static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
607 struct drm_crtc_state *old_state)
608{
609 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
610
611
612
613
614
615 if (!rcrtc->initialized) {
616 rcar_du_crtc_get(rcrtc);
617 rcar_du_crtc_setup(rcrtc);
618 rcrtc->initialized = true;
619 }
620
621 rcar_du_crtc_start(rcrtc);
622}
623
624static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
625 struct drm_crtc_state *old_state)
626{
627 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
628
629 rcar_du_crtc_stop(rcrtc);
630 rcar_du_crtc_put(rcrtc);
631
632 spin_lock_irq(&crtc->dev->event_lock);
633 if (crtc->state->event) {
634 drm_crtc_send_vblank_event(crtc, crtc->state->event);
635 crtc->state->event = NULL;
636 }
637 spin_unlock_irq(&crtc->dev->event_lock);
638
639 rcrtc->initialized = false;
640 rcrtc->outputs = 0;
641}
642
643static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
644 struct drm_crtc_state *old_crtc_state)
645{
646 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
647
648 WARN_ON(!crtc->state->enable);
649
650
651
652
653
654
655 if (!rcrtc->initialized) {
656 rcar_du_crtc_get(rcrtc);
657 rcar_du_crtc_setup(rcrtc);
658 rcrtc->initialized = true;
659 }
660
661 if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
662 rcar_du_vsp_atomic_begin(rcrtc);
663}
664
665static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
666 struct drm_crtc_state *old_crtc_state)
667{
668 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
669 struct drm_device *dev = rcrtc->crtc.dev;
670 unsigned long flags;
671
672 rcar_du_crtc_update_planes(rcrtc);
673
674 if (crtc->state->event) {
675 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
676
677 spin_lock_irqsave(&dev->event_lock, flags);
678 rcrtc->event = crtc->state->event;
679 crtc->state->event = NULL;
680 spin_unlock_irqrestore(&dev->event_lock, flags);
681 }
682
683 if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
684 rcar_du_vsp_atomic_flush(rcrtc);
685}
686
687static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
688 .atomic_begin = rcar_du_crtc_atomic_begin,
689 .atomic_flush = rcar_du_crtc_atomic_flush,
690 .atomic_enable = rcar_du_crtc_atomic_enable,
691 .atomic_disable = rcar_du_crtc_atomic_disable,
692};
693
694static struct drm_crtc_state *
695rcar_du_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
696{
697 struct rcar_du_crtc_state *state;
698 struct rcar_du_crtc_state *copy;
699
700 if (WARN_ON(!crtc->state))
701 return NULL;
702
703 state = to_rcar_crtc_state(crtc->state);
704 copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
705 if (copy == NULL)
706 return NULL;
707
708 __drm_atomic_helper_crtc_duplicate_state(crtc, ©->state);
709
710 return ©->state;
711}
712
713static void rcar_du_crtc_atomic_destroy_state(struct drm_crtc *crtc,
714 struct drm_crtc_state *state)
715{
716 __drm_atomic_helper_crtc_destroy_state(state);
717 kfree(to_rcar_crtc_state(state));
718}
719
720static void rcar_du_crtc_reset(struct drm_crtc *crtc)
721{
722 struct rcar_du_crtc_state *state;
723
724 if (crtc->state) {
725 rcar_du_crtc_atomic_destroy_state(crtc, crtc->state);
726 crtc->state = NULL;
727 }
728
729 state = kzalloc(sizeof(*state), GFP_KERNEL);
730 if (state == NULL)
731 return;
732
733 state->crc.source = VSP1_DU_CRC_NONE;
734 state->crc.index = 0;
735
736 crtc->state = &state->state;
737 crtc->state->crtc = crtc;
738}
739
740static int rcar_du_crtc_enable_vblank(struct drm_crtc *crtc)
741{
742 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
743
744 rcar_du_crtc_write(rcrtc, DSRCR, DSRCR_VBCL);
745 rcar_du_crtc_set(rcrtc, DIER, DIER_VBE);
746 rcrtc->vblank_enable = true;
747
748 return 0;
749}
750
751static void rcar_du_crtc_disable_vblank(struct drm_crtc *crtc)
752{
753 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
754
755 rcar_du_crtc_clr(rcrtc, DIER, DIER_VBE);
756 rcrtc->vblank_enable = false;
757}
758
759static int rcar_du_crtc_set_crc_source(struct drm_crtc *crtc,
760 const char *source_name,
761 size_t *values_cnt)
762{
763 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
764 struct drm_modeset_acquire_ctx ctx;
765 struct drm_crtc_state *crtc_state;
766 struct drm_atomic_state *state;
767 enum vsp1_du_crc_source source;
768 unsigned int index = 0;
769 unsigned int i;
770 int ret;
771
772
773
774
775
776
777 if (!source_name) {
778 source = VSP1_DU_CRC_NONE;
779 } else if (!strcmp(source_name, "auto")) {
780 source = VSP1_DU_CRC_OUTPUT;
781 } else if (strstarts(source_name, "plane")) {
782 source = VSP1_DU_CRC_PLANE;
783
784 ret = kstrtouint(source_name + strlen("plane"), 10, &index);
785 if (ret < 0)
786 return ret;
787
788 for (i = 0; i < rcrtc->vsp->num_planes; ++i) {
789 if (index == rcrtc->vsp->planes[i].plane.base.id) {
790 index = i;
791 break;
792 }
793 }
794
795 if (i >= rcrtc->vsp->num_planes)
796 return -EINVAL;
797 } else {
798 return -EINVAL;
799 }
800
801 *values_cnt = 1;
802
803
804 drm_modeset_acquire_init(&ctx, 0);
805
806 state = drm_atomic_state_alloc(crtc->dev);
807 if (!state) {
808 ret = -ENOMEM;
809 goto unlock;
810 }
811
812 state->acquire_ctx = &ctx;
813
814retry:
815 crtc_state = drm_atomic_get_crtc_state(state, crtc);
816 if (!IS_ERR(crtc_state)) {
817 struct rcar_du_crtc_state *rcrtc_state;
818
819 rcrtc_state = to_rcar_crtc_state(crtc_state);
820 rcrtc_state->crc.source = source;
821 rcrtc_state->crc.index = index;
822
823 ret = drm_atomic_commit(state);
824 } else {
825 ret = PTR_ERR(crtc_state);
826 }
827
828 if (ret == -EDEADLK) {
829 drm_atomic_state_clear(state);
830 drm_modeset_backoff(&ctx);
831 goto retry;
832 }
833
834 drm_atomic_state_put(state);
835
836unlock:
837 drm_modeset_drop_locks(&ctx);
838 drm_modeset_acquire_fini(&ctx);
839
840 return 0;
841}
842
843static const struct drm_crtc_funcs crtc_funcs_gen2 = {
844 .reset = rcar_du_crtc_reset,
845 .destroy = drm_crtc_cleanup,
846 .set_config = drm_atomic_helper_set_config,
847 .page_flip = drm_atomic_helper_page_flip,
848 .atomic_duplicate_state = rcar_du_crtc_atomic_duplicate_state,
849 .atomic_destroy_state = rcar_du_crtc_atomic_destroy_state,
850 .enable_vblank = rcar_du_crtc_enable_vblank,
851 .disable_vblank = rcar_du_crtc_disable_vblank,
852};
853
854static const struct drm_crtc_funcs crtc_funcs_gen3 = {
855 .reset = rcar_du_crtc_reset,
856 .destroy = drm_crtc_cleanup,
857 .set_config = drm_atomic_helper_set_config,
858 .page_flip = drm_atomic_helper_page_flip,
859 .atomic_duplicate_state = rcar_du_crtc_atomic_duplicate_state,
860 .atomic_destroy_state = rcar_du_crtc_atomic_destroy_state,
861 .enable_vblank = rcar_du_crtc_enable_vblank,
862 .disable_vblank = rcar_du_crtc_disable_vblank,
863 .set_crc_source = rcar_du_crtc_set_crc_source,
864};
865
866
867
868
869
870static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
871{
872 struct rcar_du_crtc *rcrtc = arg;
873 struct rcar_du_device *rcdu = rcrtc->group->dev;
874 irqreturn_t ret = IRQ_NONE;
875 u32 status;
876
877 spin_lock(&rcrtc->vblank_lock);
878
879 status = rcar_du_crtc_read(rcrtc, DSSR);
880 rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK);
881
882 if (status & DSSR_VBK) {
883
884
885
886
887
888 if (rcrtc->vblank_count) {
889 if (--rcrtc->vblank_count == 0)
890 wake_up(&rcrtc->vblank_wait);
891 }
892 }
893
894 spin_unlock(&rcrtc->vblank_lock);
895
896 if (status & DSSR_VBK) {
897 if (rcdu->info->gen < 3) {
898 drm_crtc_handle_vblank(&rcrtc->crtc);
899 rcar_du_crtc_finish_page_flip(rcrtc);
900 }
901
902 ret = IRQ_HANDLED;
903 }
904
905 return ret;
906}
907
908
909
910
911
912int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
913 unsigned int hwindex)
914{
915 static const unsigned int mmio_offsets[] = {
916 DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET, DU3_REG_OFFSET
917 };
918
919 struct rcar_du_device *rcdu = rgrp->dev;
920 struct platform_device *pdev = to_platform_device(rcdu->dev);
921 struct rcar_du_crtc *rcrtc = &rcdu->crtcs[swindex];
922 struct drm_crtc *crtc = &rcrtc->crtc;
923 struct drm_plane *primary;
924 unsigned int irqflags;
925 struct clk *clk;
926 char clk_name[9];
927 char *name;
928 int irq;
929 int ret;
930
931
932 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
933 sprintf(clk_name, "du.%u", hwindex);
934 name = clk_name;
935 } else {
936 name = NULL;
937 }
938
939 rcrtc->clock = devm_clk_get(rcdu->dev, name);
940 if (IS_ERR(rcrtc->clock)) {
941 dev_err(rcdu->dev, "no clock for DU channel %u\n", hwindex);
942 return PTR_ERR(rcrtc->clock);
943 }
944
945 sprintf(clk_name, "dclkin.%u", hwindex);
946 clk = devm_clk_get(rcdu->dev, clk_name);
947 if (!IS_ERR(clk)) {
948 rcrtc->extclock = clk;
949 } else if (PTR_ERR(rcrtc->clock) == -EPROBE_DEFER) {
950 dev_info(rcdu->dev, "can't get external clock %u\n", hwindex);
951 return -EPROBE_DEFER;
952 }
953
954 init_waitqueue_head(&rcrtc->flip_wait);
955 init_waitqueue_head(&rcrtc->vblank_wait);
956 spin_lock_init(&rcrtc->vblank_lock);
957
958 rcrtc->group = rgrp;
959 rcrtc->mmio_offset = mmio_offsets[hwindex];
960 rcrtc->index = hwindex;
961
962 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
963 primary = &rcrtc->vsp->planes[rcrtc->vsp_pipe].plane;
964 else
965 primary = &rgrp->planes[swindex % 2].plane;
966
967 ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary, NULL,
968 rcdu->info->gen <= 2 ?
969 &crtc_funcs_gen2 : &crtc_funcs_gen3,
970 NULL);
971 if (ret < 0)
972 return ret;
973
974 drm_crtc_helper_add(crtc, &crtc_helper_funcs);
975
976
977 drm_crtc_vblank_off(crtc);
978
979
980 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
981
982 irq = platform_get_irq(pdev, swindex);
983 irqflags = 0;
984 } else {
985 irq = platform_get_irq(pdev, 0);
986 irqflags = IRQF_SHARED;
987 }
988
989 if (irq < 0) {
990 dev_err(rcdu->dev, "no IRQ for CRTC %u\n", swindex);
991 return irq;
992 }
993
994 ret = devm_request_irq(rcdu->dev, irq, rcar_du_crtc_irq, irqflags,
995 dev_name(rcdu->dev), rcrtc);
996 if (ret < 0) {
997 dev_err(rcdu->dev,
998 "failed to register IRQ for CRTC %u\n", swindex);
999 return ret;
1000 }
1001
1002 return 0;
1003}
1004