hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
....@@ -1,53 +1,54 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * rcar_du_crtc.c -- R-Car Display Unit CRTCs
34 *
45 * Copyright (C) 2013-2015 Renesas Electronics Corporation
56 *
67 * 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.
128 */
139
1410 #include <linux/clk.h>
1511 #include <linux/mutex.h>
12
+#include <linux/platform_device.h>
1613 #include <linux/sys_soc.h>
1714
18
-#include <drm/drmP.h>
1915 #include <drm/drm_atomic.h>
2016 #include <drm/drm_atomic_helper.h>
17
+#include <drm/drm_bridge.h>
2118 #include <drm/drm_crtc.h>
22
-#include <drm/drm_crtc_helper.h>
19
+#include <drm/drm_device.h>
2320 #include <drm/drm_fb_cma_helper.h>
2421 #include <drm/drm_gem_cma_helper.h>
2522 #include <drm/drm_plane_helper.h>
23
+#include <drm/drm_vblank.h>
2624
25
+#include "rcar_cmm.h"
2726 #include "rcar_du_crtc.h"
2827 #include "rcar_du_drv.h"
28
+#include "rcar_du_encoder.h"
2929 #include "rcar_du_kms.h"
3030 #include "rcar_du_plane.h"
3131 #include "rcar_du_regs.h"
3232 #include "rcar_du_vsp.h"
33
+#include "rcar_lvds.h"
3334
3435 static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
3536 {
36
- struct rcar_du_device *rcdu = rcrtc->group->dev;
37
+ struct rcar_du_device *rcdu = rcrtc->dev;
3738
3839 return rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
3940 }
4041
4142 static void rcar_du_crtc_write(struct rcar_du_crtc *rcrtc, u32 reg, u32 data)
4243 {
43
- struct rcar_du_device *rcdu = rcrtc->group->dev;
44
+ struct rcar_du_device *rcdu = rcrtc->dev;
4445
4546 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, data);
4647 }
4748
4849 static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr)
4950 {
50
- struct rcar_du_device *rcdu = rcrtc->group->dev;
51
+ struct rcar_du_device *rcdu = rcrtc->dev;
5152
5253 rcar_du_write(rcdu, rcrtc->mmio_offset + reg,
5354 rcar_du_read(rcdu, rcrtc->mmio_offset + reg) & ~clr);
....@@ -55,52 +56,18 @@
5556
5657 static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set)
5758 {
58
- struct rcar_du_device *rcdu = rcrtc->group->dev;
59
+ struct rcar_du_device *rcdu = rcrtc->dev;
5960
6061 rcar_du_write(rcdu, rcrtc->mmio_offset + reg,
6162 rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set);
6263 }
6364
64
-static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg,
65
- u32 clr, u32 set)
65
+void rcar_du_crtc_dsysr_clr_set(struct rcar_du_crtc *rcrtc, u32 clr, u32 set)
6666 {
67
- struct rcar_du_device *rcdu = rcrtc->group->dev;
68
- u32 value = rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
67
+ struct rcar_du_device *rcdu = rcrtc->dev;
6968
70
- rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
71
-}
72
-
73
-static 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
-
91
-error_group:
92
- clk_disable_unprepare(rcrtc->extclock);
93
-error_clock:
94
- clk_disable_unprepare(rcrtc->clock);
95
- return ret;
96
-}
97
-
98
-static 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);
69
+ rcrtc->dsysr = (rcrtc->dsysr & ~clr) | set;
70
+ rcar_du_write(rcdu, rcrtc->mmio_offset + DSYSR, rcrtc->dsysr);
10471 }
10572
10673 /* -----------------------------------------------------------------------------
....@@ -192,10 +159,50 @@
192159 }
193160
194161 done:
195
- dev_dbg(rcrtc->group->dev->dev,
162
+ dev_dbg(rcrtc->dev->dev,
196163 "output:%u, fdpll:%u, n:%u, m:%u, diff:%lu\n",
197
- dpll->output, dpll->fdpll, dpll->n, dpll->m,
198
- best_diff);
164
+ dpll->output, dpll->fdpll, dpll->n, dpll->m, best_diff);
165
+}
166
+
167
+struct du_clk_params {
168
+ struct clk *clk;
169
+ unsigned long rate;
170
+ unsigned long diff;
171
+ u32 escr;
172
+};
173
+
174
+static void rcar_du_escr_divider(struct clk *clk, unsigned long target,
175
+ u32 escr, struct du_clk_params *params)
176
+{
177
+ unsigned long rate;
178
+ unsigned long diff;
179
+ u32 div;
180
+
181
+ /*
182
+ * If the target rate has already been achieved perfectly we can't do
183
+ * better.
184
+ */
185
+ if (params->diff == 0)
186
+ return;
187
+
188
+ /*
189
+ * Compute the input clock rate and internal divisor values to obtain
190
+ * the clock rate closest to the target frequency.
191
+ */
192
+ rate = clk_round_rate(clk, target);
193
+ div = clamp(DIV_ROUND_CLOSEST(rate, target), 1UL, 64UL) - 1;
194
+ diff = abs(rate / (div + 1) - target);
195
+
196
+ /*
197
+ * Store the parameters if the resulting frequency is better than any
198
+ * previously calculated value.
199
+ */
200
+ if (diff < params->diff) {
201
+ params->clk = clk;
202
+ params->rate = rate;
203
+ params->diff = diff;
204
+ params->escr = escr | div;
205
+ }
199206 }
200207
201208 static const struct soc_device_attribute rcar_du_r8a7795_es1[] = {
....@@ -206,96 +213,101 @@
206213 static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
207214 {
208215 const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode;
209
- struct rcar_du_device *rcdu = rcrtc->group->dev;
216
+ struct rcar_du_device *rcdu = rcrtc->dev;
210217 unsigned long mode_clock = mode->clock * 1000;
211
- unsigned long clk;
212
- u32 value;
218
+ unsigned int hdse_offset;
219
+ u32 dsmr;
213220 u32 escr;
214
- u32 div;
215221
216
- /*
217
- * Compute the clock divisor and select the internal or external dot
218
- * clock based on the requested frequency.
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) {
222
+ if (rcdu->info->dpll_mask & (1 << rcrtc->index)) {
223
+ unsigned long target = mode_clock;
226224 struct dpll_info dpll = { 0 };
227225 unsigned long extclk;
228
- unsigned long extrate;
229
- unsigned long rate;
230
- u32 extdiv;
226
+ u32 dpllcr;
227
+ u32 div = 0;
228
+
229
+ /*
230
+ * DU channels that have a display PLL can't use the internal
231
+ * system clock, and have no internal clock divider.
232
+ */
233
+
234
+ /*
235
+ * The H3 ES1.x exhibits dot clock duty cycle stability issues.
236
+ * We can work around them by configuring the DPLL to twice the
237
+ * desired frequency, coupled with a /2 post-divider. Restrict
238
+ * the workaround to H3 ES1.x as ES2.0 and all other SoCs have
239
+ * no post-divider when a display PLL is present (as shown by
240
+ * the workaround breaking HDMI output on M3-W during testing).
241
+ */
242
+ if (soc_device_match(rcar_du_r8a7795_es1)) {
243
+ target *= 2;
244
+ div = 1;
245
+ }
231246
232247 extclk = clk_get_rate(rcrtc->extclock);
233
- if (rcdu->info->dpll_ch & (1 << rcrtc->index)) {
234
- unsigned long target = mode_clock;
248
+ rcar_du_dpll_divider(rcrtc, &dpll, extclk, target);
235249
236
- /*
237
- * The H3 ES1.x exhibits dot clock duty cycle stability
238
- * issues. We can work around them by configuring the
239
- * DPLL to twice the desired frequency, coupled with a
240
- * /2 post-divider. This isn't needed on other SoCs and
241
- * breaks HDMI output on M3-W for a currently unknown
242
- * reason, so restrict the workaround to H3 ES1.x.
243
- */
244
- if (soc_device_match(rcar_du_r8a7795_es1))
245
- target *= 2;
250
+ dpllcr = DPLLCR_CODE | DPLLCR_CLKE
251
+ | DPLLCR_FDPLL(dpll.fdpll)
252
+ | DPLLCR_N(dpll.n) | DPLLCR_M(dpll.m)
253
+ | DPLLCR_STBY;
246254
247
- rcar_du_dpll_divider(rcrtc, &dpll, extclk, target);
248
- extclk = dpll.output;
249
- }
255
+ if (rcrtc->index == 1)
256
+ dpllcr |= DPLLCR_PLCS1
257
+ | DPLLCR_INCS_DOTCLKIN1;
258
+ else
259
+ dpllcr |= DPLLCR_PLCS0
260
+ | DPLLCR_INCS_DOTCLKIN0;
250261
251
- extdiv = DIV_ROUND_CLOSEST(extclk, mode_clock);
252
- extdiv = clamp(extdiv, 1U, 64U) - 1;
262
+ rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr);
253263
254
- rate = clk / (div + 1);
255
- extrate = extclk / (extdiv + 1);
264
+ escr = ESCR_DCLKSEL_DCLKIN | div;
265
+ } else if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) {
266
+ /*
267
+ * Use the LVDS PLL output as the dot clock when outputting to
268
+ * the LVDS encoder on an SoC that supports this clock routing
269
+ * option. We use the clock directly in that case, without any
270
+ * additional divider.
271
+ */
272
+ escr = ESCR_DCLKSEL_DCLKIN;
273
+ } else {
274
+ struct du_clk_params params = { .diff = (unsigned long)-1 };
256275
257
- if (abs((long)extrate - (long)mode_clock) <
258
- abs((long)rate - (long)mode_clock)) {
276
+ rcar_du_escr_divider(rcrtc->clock, mode_clock,
277
+ ESCR_DCLKSEL_CLKS, &params);
278
+ if (rcrtc->extclock)
279
+ rcar_du_escr_divider(rcrtc->extclock, mode_clock,
280
+ ESCR_DCLKSEL_DCLKIN, &params);
259281
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;
282
+ dev_dbg(rcrtc->dev->dev, "mode clock %lu %s rate %lu\n",
283
+ mode_clock, params.clk == rcrtc->clock ? "cpg" : "ext",
284
+ params.rate);
265285
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);
286
+ clk_set_rate(params.clk, params.rate);
287
+ escr = params.escr;
283288 }
284289
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);
290
+ dev_dbg(rcrtc->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr);
291
+
292
+ rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr);
293
+ rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0);
288294
289295 /* Signal polarities */
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);
296
+ dsmr = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0)
297
+ | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0)
298
+ | ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? DSMR_ODEV : 0)
299
+ | DSMR_DIPM_DISP | DSMR_CSPM;
300
+ rcar_du_crtc_write(rcrtc, DSMR, dsmr);
301
+
302
+ hdse_offset = 19;
303
+ if (rcrtc->group->cmms_mask & BIT(rcrtc->index % 2))
304
+ hdse_offset += 25;
294305
295306 /* Display timings */
296
- rcar_du_crtc_write(rcrtc, HDSR, mode->htotal - mode->hsync_start - 19);
307
+ rcar_du_crtc_write(rcrtc, HDSR, mode->htotal - mode->hsync_start -
308
+ hdse_offset);
297309 rcar_du_crtc_write(rcrtc, HDER, mode->htotal - mode->hsync_start +
298
- mode->hdisplay - 19);
310
+ mode->hdisplay - hdse_offset);
299311 rcar_du_crtc_write(rcrtc, HSWR, mode->hsync_end -
300312 mode->hsync_start - 1);
301313 rcar_du_crtc_write(rcrtc, HCR, mode->htotal - 1);
....@@ -314,26 +326,6 @@
314326 rcar_du_crtc_write(rcrtc, DEWR, mode->hdisplay);
315327 }
316328
317
-void 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
- * Store the route from the CRTC output to the DU output. The DU will be
325
- * configured when starting the CRTC.
326
- */
327
- rcrtc->outputs |= BIT(output);
328
-
329
- /*
330
- * Store RGB routing to DPAD0, the hardware will be configured when
331
- * starting the CRTC.
332
- */
333
- if (output == RCAR_DU_OUTPUT_DPAD0)
334
- rcdu->dpad0_source = rcrtc->index;
335
-}
336
-
337329 static unsigned int plane_zpos(struct rcar_du_plane *plane)
338330 {
339331 return plane->plane.state->normalized_zpos;
....@@ -348,7 +340,7 @@
348340 static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
349341 {
350342 struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
351
- struct rcar_du_device *rcdu = rcrtc->group->dev;
343
+ struct rcar_du_device *rcdu = rcrtc->dev;
352344 unsigned int num_planes = 0;
353345 unsigned int dptsr_planes;
354346 unsigned int hwplanes = 0;
....@@ -478,7 +470,7 @@
478470
479471 static void rcar_du_crtc_wait_page_flip(struct rcar_du_crtc *rcrtc)
480472 {
481
- struct rcar_du_device *rcdu = rcrtc->group->dev;
473
+ struct rcar_du_device *rcdu = rcrtc->dev;
482474
483475 if (wait_event_timeout(rcrtc->flip_wait,
484476 !rcar_du_crtc_page_flip_pending(rcrtc),
....@@ -488,6 +480,45 @@
488480 dev_warn(rcdu->dev, "page flip timeout\n");
489481
490482 rcar_du_crtc_finish_page_flip(rcrtc);
483
+}
484
+
485
+/* -----------------------------------------------------------------------------
486
+ * Color Management Module (CMM)
487
+ */
488
+
489
+static int rcar_du_cmm_check(struct drm_crtc *crtc,
490
+ struct drm_crtc_state *state)
491
+{
492
+ struct drm_property_blob *drm_lut = state->gamma_lut;
493
+ struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
494
+ struct device *dev = rcrtc->dev->dev;
495
+
496
+ if (!drm_lut)
497
+ return 0;
498
+
499
+ /* We only accept fully populated LUT tables. */
500
+ if (drm_color_lut_size(drm_lut) != CM2_LUT_SIZE) {
501
+ dev_err(dev, "invalid gamma lut size: %zu bytes\n",
502
+ drm_lut->length);
503
+ return -EINVAL;
504
+ }
505
+
506
+ return 0;
507
+}
508
+
509
+static void rcar_du_cmm_setup(struct drm_crtc *crtc)
510
+{
511
+ struct drm_property_blob *drm_lut = crtc->state->gamma_lut;
512
+ struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
513
+ struct rcar_cmm_config cmm_config = {};
514
+
515
+ if (!rcrtc->cmm)
516
+ return;
517
+
518
+ if (drm_lut)
519
+ cmm_config.lut.table = (struct drm_color_lut *)drm_lut->data;
520
+
521
+ rcar_cmm_setup(rcrtc->cmm, &cmm_config);
491522 }
492523
493524 /* -----------------------------------------------------------------------------
....@@ -508,11 +539,56 @@
508539 rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0);
509540
510541 /* Enable the VSP compositor. */
511
- if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
542
+ if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
512543 rcar_du_vsp_enable(rcrtc);
513544
514545 /* Turn vertical blanking interrupt reporting on. */
515546 drm_crtc_vblank_on(&rcrtc->crtc);
547
+}
548
+
549
+static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
550
+{
551
+ int ret;
552
+
553
+ /*
554
+ * Guard against double-get, as the function is called from both the
555
+ * .atomic_enable() and .atomic_begin() handlers.
556
+ */
557
+ if (rcrtc->initialized)
558
+ return 0;
559
+
560
+ ret = clk_prepare_enable(rcrtc->clock);
561
+ if (ret < 0)
562
+ return ret;
563
+
564
+ ret = clk_prepare_enable(rcrtc->extclock);
565
+ if (ret < 0)
566
+ goto error_clock;
567
+
568
+ ret = rcar_du_group_get(rcrtc->group);
569
+ if (ret < 0)
570
+ goto error_group;
571
+
572
+ rcar_du_crtc_setup(rcrtc);
573
+ rcrtc->initialized = true;
574
+
575
+ return 0;
576
+
577
+error_group:
578
+ clk_disable_unprepare(rcrtc->extclock);
579
+error_clock:
580
+ clk_disable_unprepare(rcrtc->clock);
581
+ return ret;
582
+}
583
+
584
+static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
585
+{
586
+ rcar_du_group_put(rcrtc->group);
587
+
588
+ clk_disable_unprepare(rcrtc->extclock);
589
+ clk_disable_unprepare(rcrtc->clock);
590
+
591
+ rcrtc->initialized = false;
516592 }
517593
518594 static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
....@@ -525,16 +601,16 @@
525601 * actively driven).
526602 */
527603 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);
604
+ rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK | DSYSR_SCM_MASK,
605
+ (interlaced ? DSYSR_SCM_INT_VIDEO : 0) |
606
+ DSYSR_TVM_MASTER);
531607
532608 rcar_du_group_start_stop(rcrtc->group, true);
533609 }
534610
535611 static void rcar_du_crtc_disable_planes(struct rcar_du_crtc *rcrtc)
536612 {
537
- struct rcar_du_device *rcdu = rcrtc->group->dev;
613
+ struct rcar_du_device *rcdu = rcrtc->dev;
538614 struct drm_crtc *crtc = &rcrtc->crtc;
539615 u32 status;
540616
....@@ -587,14 +663,22 @@
587663 drm_crtc_vblank_off(crtc);
588664
589665 /* Disable the VSP compositor. */
590
- if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
666
+ if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
591667 rcar_du_vsp_disable(rcrtc);
668
+
669
+ if (rcrtc->cmm)
670
+ rcar_cmm_disable(rcrtc->cmm);
592671
593672 /*
594673 * Select switch sync mode. This stops display operation and configures
595674 * the HSYNC and VSYNC signals as inputs.
675
+ *
676
+ * TODO: Find another way to stop the display for DUs that don't support
677
+ * TVM sync.
596678 */
597
- rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);
679
+ if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_TVM_SYNC))
680
+ rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK,
681
+ DSYSR_TVM_SWITCH);
598682
599683 rcar_du_group_start_stop(rcrtc->group, false);
600684 }
....@@ -603,31 +687,89 @@
603687 * CRTC Functions
604688 */
605689
690
+static int rcar_du_crtc_atomic_check(struct drm_crtc *crtc,
691
+ struct drm_crtc_state *state)
692
+{
693
+ struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(state);
694
+ struct drm_encoder *encoder;
695
+ int ret;
696
+
697
+ ret = rcar_du_cmm_check(crtc, state);
698
+ if (ret)
699
+ return ret;
700
+
701
+ /* Store the routes from the CRTC output to the DU outputs. */
702
+ rstate->outputs = 0;
703
+
704
+ drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) {
705
+ struct rcar_du_encoder *renc;
706
+
707
+ /* Skip the writeback encoder. */
708
+ if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
709
+ continue;
710
+
711
+ renc = to_rcar_encoder(encoder);
712
+ rstate->outputs |= BIT(renc->output);
713
+ }
714
+
715
+ return 0;
716
+}
717
+
606718 static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
607719 struct drm_crtc_state *old_state)
608720 {
609721 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
722
+ struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(crtc->state);
723
+ struct rcar_du_device *rcdu = rcrtc->dev;
724
+
725
+ if (rcrtc->cmm)
726
+ rcar_cmm_enable(rcrtc->cmm);
727
+ rcar_du_crtc_get(rcrtc);
610728
611729 /*
612
- * If the CRTC has already been setup by the .atomic_begin() handler we
613
- * can skip the setup stage.
730
+ * On D3/E3 the dot clock is provided by the LVDS encoder attached to
731
+ * the DU channel. We need to enable its clock output explicitly if
732
+ * the LVDS output is disabled.
614733 */
615
- if (!rcrtc->initialized) {
616
- rcar_du_crtc_get(rcrtc);
617
- rcar_du_crtc_setup(rcrtc);
618
- rcrtc->initialized = true;
734
+ if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) &&
735
+ rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) {
736
+ struct drm_bridge *bridge = rcdu->lvds[rcrtc->index];
737
+ const struct drm_display_mode *mode =
738
+ &crtc->state->adjusted_mode;
739
+
740
+ rcar_lvds_clk_enable(bridge, mode->clock * 1000);
619741 }
620742
621743 rcar_du_crtc_start(rcrtc);
744
+
745
+ /*
746
+ * TODO: The chip manual indicates that CMM tables should be written
747
+ * after the DU channel has been activated. Investigate the impact
748
+ * of this restriction on the first displayed frame.
749
+ */
750
+ rcar_du_cmm_setup(crtc);
622751 }
623752
624753 static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
625754 struct drm_crtc_state *old_state)
626755 {
627756 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
757
+ struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(old_state);
758
+ struct rcar_du_device *rcdu = rcrtc->dev;
628759
629760 rcar_du_crtc_stop(rcrtc);
630761 rcar_du_crtc_put(rcrtc);
762
+
763
+ if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) &&
764
+ rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) {
765
+ struct drm_bridge *bridge = rcdu->lvds[rcrtc->index];
766
+
767
+ /*
768
+ * Disable the LVDS clock output, see
769
+ * rcar_du_crtc_atomic_enable().
770
+ */
771
+ rcar_lvds_clk_disable(bridge);
772
+ }
631773
632774 spin_lock_irq(&crtc->dev->event_lock);
633775 if (crtc->state->event) {
....@@ -635,9 +777,6 @@
635777 crtc->state->event = NULL;
636778 }
637779 spin_unlock_irq(&crtc->dev->event_lock);
638
-
639
- rcrtc->initialized = false;
640
- rcrtc->outputs = 0;
641780 }
642781
643782 static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
....@@ -649,16 +788,23 @@
649788
650789 /*
651790 * If a mode set is in progress we can be called with the CRTC disabled.
652
- * We then need to first setup the CRTC in order to configure planes.
653
- * The .atomic_enable() handler will notice and skip the CRTC setup.
791
+ * We thus need to first get and setup the CRTC in order to configure
792
+ * planes. We must *not* put the CRTC in .atomic_flush(), as it must be
793
+ * kept awake until the .atomic_enable() call that will follow. The get
794
+ * operation in .atomic_enable() will in that case be a no-op, and the
795
+ * CRTC will be put later in .atomic_disable().
796
+ *
797
+ * If a mode set is not in progress the CRTC is enabled, and the
798
+ * following get call will be a no-op. There is thus no need to balance
799
+ * it in .atomic_flush() either.
654800 */
655
- if (!rcrtc->initialized) {
656
- rcar_du_crtc_get(rcrtc);
657
- rcar_du_crtc_setup(rcrtc);
658
- rcrtc->initialized = true;
659
- }
801
+ rcar_du_crtc_get(rcrtc);
660802
661
- if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
803
+ /* If the active state changed, we let .atomic_enable handle CMM. */
804
+ if (crtc->state->color_mgmt_changed && !crtc->state->active_changed)
805
+ rcar_du_cmm_setup(crtc);
806
+
807
+ if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
662808 rcar_du_vsp_atomic_begin(rcrtc);
663809 }
664810
....@@ -680,16 +826,109 @@
680826 spin_unlock_irqrestore(&dev->event_lock, flags);
681827 }
682828
683
- if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
829
+ if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
684830 rcar_du_vsp_atomic_flush(rcrtc);
685831 }
686832
833
+static enum drm_mode_status
834
+rcar_du_crtc_mode_valid(struct drm_crtc *crtc,
835
+ const struct drm_display_mode *mode)
836
+{
837
+ struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
838
+ struct rcar_du_device *rcdu = rcrtc->dev;
839
+ bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
840
+ unsigned int min_sync_porch;
841
+ unsigned int vbp;
842
+
843
+ if (interlaced && !rcar_du_has(rcdu, RCAR_DU_FEATURE_INTERLACED))
844
+ return MODE_NO_INTERLACE;
845
+
846
+ /*
847
+ * The hardware requires a minimum combined horizontal sync and back
848
+ * porch of 20 pixels (when CMM isn't used) or 45 pixels (when CMM is
849
+ * used), and a minimum vertical back porch of 3 lines.
850
+ */
851
+ min_sync_porch = 20;
852
+ if (rcrtc->group->cmms_mask & BIT(rcrtc->index % 2))
853
+ min_sync_porch += 25;
854
+
855
+ if (mode->htotal - mode->hsync_start < min_sync_porch)
856
+ return MODE_HBLANK_NARROW;
857
+
858
+ vbp = (mode->vtotal - mode->vsync_end) / (interlaced ? 2 : 1);
859
+ if (vbp < 3)
860
+ return MODE_VBLANK_NARROW;
861
+
862
+ return MODE_OK;
863
+}
864
+
687865 static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
866
+ .atomic_check = rcar_du_crtc_atomic_check,
688867 .atomic_begin = rcar_du_crtc_atomic_begin,
689868 .atomic_flush = rcar_du_crtc_atomic_flush,
690869 .atomic_enable = rcar_du_crtc_atomic_enable,
691870 .atomic_disable = rcar_du_crtc_atomic_disable,
871
+ .mode_valid = rcar_du_crtc_mode_valid,
692872 };
873
+
874
+static void rcar_du_crtc_crc_init(struct rcar_du_crtc *rcrtc)
875
+{
876
+ struct rcar_du_device *rcdu = rcrtc->dev;
877
+ const char **sources;
878
+ unsigned int count;
879
+ int i = -1;
880
+
881
+ /* CRC available only on Gen3 HW. */
882
+ if (rcdu->info->gen < 3)
883
+ return;
884
+
885
+ /* Reserve 1 for "auto" source. */
886
+ count = rcrtc->vsp->num_planes + 1;
887
+
888
+ sources = kmalloc_array(count, sizeof(*sources), GFP_KERNEL);
889
+ if (!sources)
890
+ return;
891
+
892
+ sources[0] = kstrdup("auto", GFP_KERNEL);
893
+ if (!sources[0])
894
+ goto error;
895
+
896
+ for (i = 0; i < rcrtc->vsp->num_planes; ++i) {
897
+ struct drm_plane *plane = &rcrtc->vsp->planes[i].plane;
898
+ char name[16];
899
+
900
+ sprintf(name, "plane%u", plane->base.id);
901
+ sources[i + 1] = kstrdup(name, GFP_KERNEL);
902
+ if (!sources[i + 1])
903
+ goto error;
904
+ }
905
+
906
+ rcrtc->sources = sources;
907
+ rcrtc->sources_count = count;
908
+ return;
909
+
910
+error:
911
+ while (i >= 0) {
912
+ kfree(sources[i]);
913
+ i--;
914
+ }
915
+ kfree(sources);
916
+}
917
+
918
+static void rcar_du_crtc_crc_cleanup(struct rcar_du_crtc *rcrtc)
919
+{
920
+ unsigned int i;
921
+
922
+ if (!rcrtc->sources)
923
+ return;
924
+
925
+ for (i = 0; i < rcrtc->sources_count; i++)
926
+ kfree(rcrtc->sources[i]);
927
+ kfree(rcrtc->sources);
928
+
929
+ rcrtc->sources = NULL;
930
+ rcrtc->sources_count = 0;
931
+}
693932
694933 static struct drm_crtc_state *
695934 rcar_du_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
....@@ -717,6 +956,15 @@
717956 kfree(to_rcar_crtc_state(state));
718957 }
719958
959
+static void rcar_du_crtc_cleanup(struct drm_crtc *crtc)
960
+{
961
+ struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
962
+
963
+ rcar_du_crtc_crc_cleanup(rcrtc);
964
+
965
+ return drm_crtc_cleanup(crtc);
966
+}
967
+
720968 static void rcar_du_crtc_reset(struct drm_crtc *crtc)
721969 {
722970 struct rcar_du_crtc_state *state;
....@@ -733,8 +981,7 @@
733981 state->crc.source = VSP1_DU_CRC_NONE;
734982 state->crc.index = 0;
735983
736
- crtc->state = &state->state;
737
- crtc->state->crtc = crtc;
984
+ __drm_atomic_helper_crtc_reset(crtc, &state->state);
738985 }
739986
740987 static int rcar_du_crtc_enable_vblank(struct drm_crtc *crtc)
....@@ -756,6 +1003,68 @@
7561003 rcrtc->vblank_enable = false;
7571004 }
7581005
1006
+static int rcar_du_crtc_parse_crc_source(struct rcar_du_crtc *rcrtc,
1007
+ const char *source_name,
1008
+ enum vsp1_du_crc_source *source)
1009
+{
1010
+ unsigned int index;
1011
+ int ret;
1012
+
1013
+ /*
1014
+ * Parse the source name. Supported values are "plane%u" to compute the
1015
+ * CRC on an input plane (%u is the plane ID), and "auto" to compute the
1016
+ * CRC on the composer (VSP) output.
1017
+ */
1018
+
1019
+ if (!source_name) {
1020
+ *source = VSP1_DU_CRC_NONE;
1021
+ return 0;
1022
+ } else if (!strcmp(source_name, "auto")) {
1023
+ *source = VSP1_DU_CRC_OUTPUT;
1024
+ return 0;
1025
+ } else if (strstarts(source_name, "plane")) {
1026
+ unsigned int i;
1027
+
1028
+ *source = VSP1_DU_CRC_PLANE;
1029
+
1030
+ ret = kstrtouint(source_name + strlen("plane"), 10, &index);
1031
+ if (ret < 0)
1032
+ return ret;
1033
+
1034
+ for (i = 0; i < rcrtc->vsp->num_planes; ++i) {
1035
+ if (index == rcrtc->vsp->planes[i].plane.base.id)
1036
+ return i;
1037
+ }
1038
+ }
1039
+
1040
+ return -EINVAL;
1041
+}
1042
+
1043
+static int rcar_du_crtc_verify_crc_source(struct drm_crtc *crtc,
1044
+ const char *source_name,
1045
+ size_t *values_cnt)
1046
+{
1047
+ struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
1048
+ enum vsp1_du_crc_source source;
1049
+
1050
+ if (rcar_du_crtc_parse_crc_source(rcrtc, source_name, &source) < 0) {
1051
+ DRM_DEBUG_DRIVER("unknown source %s\n", source_name);
1052
+ return -EINVAL;
1053
+ }
1054
+
1055
+ *values_cnt = 1;
1056
+ return 0;
1057
+}
1058
+
1059
+static const char *const *
1060
+rcar_du_crtc_get_crc_sources(struct drm_crtc *crtc, size_t *count)
1061
+{
1062
+ struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
1063
+
1064
+ *count = rcrtc->sources_count;
1065
+ return rcrtc->sources;
1066
+}
1067
+
7591068 static int rcar_du_crtc_set_crc_source(struct drm_crtc *crtc,
7601069 const char *source_name)
7611070 {
....@@ -764,38 +1073,14 @@
7641073 struct drm_crtc_state *crtc_state;
7651074 struct drm_atomic_state *state;
7661075 enum vsp1_du_crc_source source;
767
- unsigned int index = 0;
768
- unsigned int i;
1076
+ unsigned int index;
7691077 int ret;
7701078
771
- /*
772
- * Parse the source name. Supported values are "plane%u" to compute the
773
- * CRC on an input plane (%u is the plane ID), and "auto" to compute the
774
- * CRC on the composer (VSP) output.
775
- */
776
- if (!source_name) {
777
- source = VSP1_DU_CRC_NONE;
778
- } else if (!strcmp(source_name, "auto")) {
779
- source = VSP1_DU_CRC_OUTPUT;
780
- } else if (strstarts(source_name, "plane")) {
781
- source = VSP1_DU_CRC_PLANE;
1079
+ ret = rcar_du_crtc_parse_crc_source(rcrtc, source_name, &source);
1080
+ if (ret < 0)
1081
+ return ret;
7821082
783
- ret = kstrtouint(source_name + strlen("plane"), 10, &index);
784
- if (ret < 0)
785
- return ret;
786
-
787
- for (i = 0; i < rcrtc->vsp->num_planes; ++i) {
788
- if (index == rcrtc->vsp->planes[i].plane.base.id) {
789
- index = i;
790
- break;
791
- }
792
- }
793
-
794
- if (i >= rcrtc->vsp->num_planes)
795
- return -EINVAL;
796
- } else {
797
- return -EINVAL;
798
- }
1083
+ index = ret;
7991084
8001085 /* Perform an atomic commit to set the CRC source. */
8011086 drm_modeset_acquire_init(&ctx, 0);
....@@ -850,7 +1135,7 @@
8501135
8511136 static const struct drm_crtc_funcs crtc_funcs_gen3 = {
8521137 .reset = rcar_du_crtc_reset,
853
- .destroy = drm_crtc_cleanup,
1138
+ .destroy = rcar_du_crtc_cleanup,
8541139 .set_config = drm_atomic_helper_set_config,
8551140 .page_flip = drm_atomic_helper_page_flip,
8561141 .atomic_duplicate_state = rcar_du_crtc_atomic_duplicate_state,
....@@ -858,6 +1143,9 @@
8581143 .enable_vblank = rcar_du_crtc_enable_vblank,
8591144 .disable_vblank = rcar_du_crtc_disable_vblank,
8601145 .set_crc_source = rcar_du_crtc_set_crc_source,
1146
+ .verify_crc_source = rcar_du_crtc_verify_crc_source,
1147
+ .get_crc_sources = rcar_du_crtc_get_crc_sources,
1148
+ .gamma_set = drm_atomic_helper_legacy_gamma_set,
8611149 };
8621150
8631151 /* -----------------------------------------------------------------------------
....@@ -867,7 +1155,7 @@
8671155 static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
8681156 {
8691157 struct rcar_du_crtc *rcrtc = arg;
870
- struct rcar_du_device *rcdu = rcrtc->group->dev;
1158
+ struct rcar_du_device *rcdu = rcrtc->dev;
8711159 irqreturn_t ret = IRQ_NONE;
8721160 u32 status;
8731161
....@@ -943,18 +1231,27 @@
9431231 clk = devm_clk_get(rcdu->dev, clk_name);
9441232 if (!IS_ERR(clk)) {
9451233 rcrtc->extclock = clk;
946
- } else if (PTR_ERR(rcrtc->clock) == -EPROBE_DEFER) {
947
- dev_info(rcdu->dev, "can't get external clock %u\n", hwindex);
1234
+ } else if (PTR_ERR(clk) == -EPROBE_DEFER) {
9481235 return -EPROBE_DEFER;
1236
+ } else if (rcdu->info->dpll_mask & BIT(hwindex)) {
1237
+ /*
1238
+ * DU channels that have a display PLL can't use the internal
1239
+ * system clock and thus require an external clock.
1240
+ */
1241
+ ret = PTR_ERR(clk);
1242
+ dev_err(rcdu->dev, "can't get dclkin.%u: %d\n", hwindex, ret);
1243
+ return ret;
9491244 }
9501245
9511246 init_waitqueue_head(&rcrtc->flip_wait);
9521247 init_waitqueue_head(&rcrtc->vblank_wait);
9531248 spin_lock_init(&rcrtc->vblank_lock);
9541249
1250
+ rcrtc->dev = rcdu;
9551251 rcrtc->group = rgrp;
9561252 rcrtc->mmio_offset = mmio_offsets[hwindex];
9571253 rcrtc->index = hwindex;
1254
+ rcrtc->dsysr = (rcrtc->index % 2 ? 0 : DSYSR_DRES) | DSYSR_TVM_TVSYNC;
9581255
9591256 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
9601257 primary = &rcrtc->vsp->planes[rcrtc->vsp_pipe].plane;
....@@ -968,10 +1265,16 @@
9681265 if (ret < 0)
9691266 return ret;
9701267
971
- drm_crtc_helper_add(crtc, &crtc_helper_funcs);
1268
+ /* CMM might be disabled for this CRTC. */
1269
+ if (rcdu->cmms[swindex]) {
1270
+ rcrtc->cmm = rcdu->cmms[swindex];
1271
+ rgrp->cmms_mask |= BIT(hwindex % 2);
9721272
973
- /* Start with vertical blanking interrupt reporting disabled. */
974
- drm_crtc_vblank_off(crtc);
1273
+ drm_mode_crtc_set_gamma_size(crtc, CM2_LUT_SIZE);
1274
+ drm_crtc_enable_color_mgmt(crtc, 0, false, CM2_LUT_SIZE);
1275
+ }
1276
+
1277
+ drm_crtc_helper_add(crtc, &crtc_helper_funcs);
9751278
9761279 /* Register the interrupt handler. */
9771280 if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
....@@ -996,5 +1299,7 @@
9961299 return ret;
9971300 }
9981301
1302
+ rcar_du_crtc_crc_init(rcrtc);
1303
+
9991304 return 0;
10001305 }