1
2
3
4
5
6
7
8
9
10
11
12
13#include <drm/drmP.h>
14#include <drm/drm_atomic_helper.h>
15#include <drm/drm_crtc.h>
16#include <drm/drm_crtc_helper.h>
17#include <drm/drm_encoder.h>
18#include <drm/drm_modes.h>
19#include <drm/drm_of.h>
20
21#include <uapi/drm/drm_mode.h>
22
23#include <linux/component.h>
24#include <linux/ioport.h>
25#include <linux/of_address.h>
26#include <linux/of_device.h>
27#include <linux/of_irq.h>
28#include <linux/regmap.h>
29#include <linux/reset.h>
30
31#include "sun4i_crtc.h"
32#include "sun4i_dotclock.h"
33#include "sun4i_drv.h"
34#include "sun4i_lvds.h"
35#include "sun4i_rgb.h"
36#include "sun4i_tcon.h"
37#include "sun6i_mipi_dsi.h"
38#include "sunxi_engine.h"
39
40static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
41{
42 struct drm_connector *connector;
43 struct drm_connector_list_iter iter;
44
45 drm_connector_list_iter_begin(encoder->dev, &iter);
46 drm_for_each_connector_iter(connector, &iter)
47 if (connector->encoder == encoder) {
48 drm_connector_list_iter_end(&iter);
49 return connector;
50 }
51 drm_connector_list_iter_end(&iter);
52
53 return NULL;
54}
55
56static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
57{
58 struct drm_connector *connector;
59 struct drm_display_info *info;
60
61 connector = sun4i_tcon_get_connector(encoder);
62 if (!connector)
63 return -EINVAL;
64
65 info = &connector->display_info;
66 if (info->num_bus_formats != 1)
67 return -EINVAL;
68
69 switch (info->bus_formats[0]) {
70 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
71 return 18;
72
73 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
74 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
75 return 24;
76 }
77
78 return -EINVAL;
79}
80
81static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
82 bool enabled)
83{
84 struct clk *clk;
85
86 switch (channel) {
87 case 0:
88 WARN_ON(!tcon->quirks->has_channel_0);
89 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
90 SUN4I_TCON0_CTL_TCON_ENABLE,
91 enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0);
92 clk = tcon->dclk;
93 break;
94 case 1:
95 WARN_ON(!tcon->quirks->has_channel_1);
96 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
97 SUN4I_TCON1_CTL_TCON_ENABLE,
98 enabled ? SUN4I_TCON1_CTL_TCON_ENABLE : 0);
99 clk = tcon->sclk1;
100 break;
101 default:
102 DRM_WARN("Unknown channel... doing nothing\n");
103 return;
104 }
105
106 if (enabled) {
107 clk_prepare_enable(clk);
108 clk_rate_exclusive_get(clk);
109 } else {
110 clk_rate_exclusive_put(clk);
111 clk_disable_unprepare(clk);
112 }
113}
114
115static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon,
116 const struct drm_encoder *encoder,
117 bool enabled)
118{
119 if (enabled) {
120 u8 val;
121
122 regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
123 SUN4I_TCON0_LVDS_IF_EN,
124 SUN4I_TCON0_LVDS_IF_EN);
125
126
127
128
129
130
131 regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
132 SUN6I_TCON0_LVDS_ANA0_C(2) |
133 SUN6I_TCON0_LVDS_ANA0_V(3) |
134 SUN6I_TCON0_LVDS_ANA0_PD(2) |
135 SUN6I_TCON0_LVDS_ANA0_EN_LDO);
136 udelay(2);
137
138 regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
139 SUN6I_TCON0_LVDS_ANA0_EN_MB,
140 SUN6I_TCON0_LVDS_ANA0_EN_MB);
141 udelay(2);
142
143 regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
144 SUN6I_TCON0_LVDS_ANA0_EN_DRVC,
145 SUN6I_TCON0_LVDS_ANA0_EN_DRVC);
146
147 if (sun4i_tcon_get_pixel_depth(encoder) == 18)
148 val = 7;
149 else
150 val = 0xf;
151
152 regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
153 SUN6I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
154 SUN6I_TCON0_LVDS_ANA0_EN_DRVD(val));
155 } else {
156 regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
157 SUN4I_TCON0_LVDS_IF_EN, 0);
158 }
159}
160
161void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
162 const struct drm_encoder *encoder,
163 bool enabled)
164{
165 bool is_lvds = false;
166 int channel;
167
168 switch (encoder->encoder_type) {
169 case DRM_MODE_ENCODER_LVDS:
170 is_lvds = true;
171
172 case DRM_MODE_ENCODER_DSI:
173 case DRM_MODE_ENCODER_NONE:
174 channel = 0;
175 break;
176 case DRM_MODE_ENCODER_TMDS:
177 case DRM_MODE_ENCODER_TVDAC:
178 channel = 1;
179 break;
180 default:
181 DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
182 return;
183 }
184
185 if (is_lvds && !enabled)
186 sun4i_tcon_lvds_set_status(tcon, encoder, false);
187
188 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
189 SUN4I_TCON_GCTL_TCON_ENABLE,
190 enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
191
192 if (is_lvds && enabled)
193 sun4i_tcon_lvds_set_status(tcon, encoder, true);
194
195 sun4i_tcon_channel_set_status(tcon, channel, enabled);
196}
197
198void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
199{
200 u32 mask, val = 0;
201
202 DRM_DEBUG_DRIVER("%sabling VBLANK interrupt\n", enable ? "En" : "Dis");
203
204 mask = SUN4I_TCON_GINT0_VBLANK_ENABLE(0) |
205 SUN4I_TCON_GINT0_VBLANK_ENABLE(1) |
206 SUN4I_TCON_GINT0_TCON0_TRI_FINISH_ENABLE;
207
208 if (enable)
209 val = mask;
210
211 regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, mask, val);
212}
213EXPORT_SYMBOL(sun4i_tcon_enable_vblank);
214
215
216
217
218
219
220
221static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
222{
223 struct sun4i_drv *drv = drm->dev_private;
224 struct sun4i_tcon *tcon;
225
226 list_for_each_entry(tcon, &drv->tcon_list, list)
227 if (tcon->id == 0)
228 return tcon;
229
230 dev_warn(drm->dev,
231 "TCON0 not found, display output muxing may not work\n");
232
233 return NULL;
234}
235
236void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
237 const struct drm_encoder *encoder)
238{
239 int ret = -ENOTSUPP;
240
241 if (tcon->quirks->set_mux)
242 ret = tcon->quirks->set_mux(tcon, encoder);
243
244 DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
245 encoder->name, encoder->crtc->name, ret);
246}
247
248static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
249 int channel)
250{
251 int delay = mode->vtotal - mode->vdisplay;
252
253 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
254 delay /= 2;
255
256 if (channel == 1)
257 delay -= 2;
258
259 delay = min(delay, 30);
260
261 DRM_DEBUG_DRIVER("TCON %d clock delay %u\n", channel, delay);
262
263 return delay;
264}
265
266static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
267 const struct drm_display_mode *mode)
268{
269
270 clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
271
272
273 regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
274 SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
275 SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
276}
277
278static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
279 struct mipi_dsi_device *device,
280 const struct drm_display_mode *mode)
281{
282 u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
283 u8 lanes = device->lanes;
284 u32 block_space, start_delay;
285 u32 tcon_div;
286
287 tcon->dclk_min_div = 4;
288 tcon->dclk_max_div = 127;
289
290 sun4i_tcon0_mode_set_common(tcon, mode);
291
292 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
293 SUN4I_TCON0_CTL_IF_MASK,
294 SUN4I_TCON0_CTL_IF_8080);
295
296 regmap_write(tcon->regs, SUN4I_TCON_ECC_FIFO_REG,
297 SUN4I_TCON_ECC_FIFO_EN);
298
299 regmap_write(tcon->regs, SUN4I_TCON0_CPU_IF_REG,
300 SUN4I_TCON0_CPU_IF_MODE_DSI |
301 SUN4I_TCON0_CPU_IF_TRI_FIFO_FLUSH |
302 SUN4I_TCON0_CPU_IF_TRI_FIFO_EN |
303 SUN4I_TCON0_CPU_IF_TRI_EN);
304
305
306
307
308
309
310
311 regmap_read(tcon->regs, SUN4I_TCON0_DCLK_REG, &tcon_div);
312 tcon_div &= GENMASK(6, 0);
313 block_space = mode->htotal * bpp / (tcon_div * lanes);
314 block_space -= mode->hdisplay + 40;
315
316 regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
317 SUN4I_TCON0_CPU_TRI0_BLOCK_SPACE(block_space) |
318 SUN4I_TCON0_CPU_TRI0_BLOCK_SIZE(mode->hdisplay));
319
320 regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI1_REG,
321 SUN4I_TCON0_CPU_TRI1_BLOCK_NUM(mode->vdisplay));
322
323 start_delay = (mode->crtc_vtotal - mode->crtc_vdisplay - 10 - 1);
324 start_delay = start_delay * mode->crtc_htotal * 149;
325 start_delay = start_delay / (mode->crtc_clock / 1000) / 8;
326 regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI2_REG,
327 SUN4I_TCON0_CPU_TRI2_TRANS_START_SET(10) |
328 SUN4I_TCON0_CPU_TRI2_START_DELAY(start_delay));
329
330
331
332
333
334 regmap_write(tcon->regs, SUN4I_TCON_SAFE_PERIOD_REG,
335 SUN4I_TCON_SAFE_PERIOD_NUM(3000) |
336 SUN4I_TCON_SAFE_PERIOD_MODE(3));
337
338
339 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG,
340 0xe0000000);
341}
342
343static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
344 const struct drm_encoder *encoder,
345 const struct drm_display_mode *mode)
346{
347 unsigned int bp;
348 u8 clk_delay;
349 u32 reg, val = 0;
350
351 WARN_ON(!tcon->quirks->has_channel_0);
352
353 tcon->dclk_min_div = 7;
354 tcon->dclk_max_div = 7;
355 sun4i_tcon0_mode_set_common(tcon, mode);
356
357
358 clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
359 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
360 SUN4I_TCON0_CTL_CLK_DELAY_MASK,
361 SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
362
363
364
365
366
367 bp = mode->crtc_htotal - mode->crtc_hsync_start;
368 DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
369 mode->crtc_htotal, bp);
370
371
372 regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
373 SUN4I_TCON0_BASIC1_H_TOTAL(mode->htotal) |
374 SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
375
376
377
378
379
380 bp = mode->crtc_vtotal - mode->crtc_vsync_start;
381 DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
382 mode->crtc_vtotal, bp);
383
384
385 regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
386 SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
387 SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
388
389 reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 |
390 SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL |
391 SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL;
392 if (sun4i_tcon_get_pixel_depth(encoder) == 24)
393 reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
394 else
395 reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
396
397 regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
398
399
400 if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
401 val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
402
403 if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
404 val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
405
406 regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
407
408
409 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
410 SUN4I_TCON_GCTL_IOMAP_MASK,
411 SUN4I_TCON_GCTL_IOMAP_TCON0);
412
413
414 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
415}
416
417static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
418 const struct drm_display_mode *mode)
419{
420 unsigned int bp, hsync, vsync;
421 u8 clk_delay;
422 u32 val = 0;
423
424 WARN_ON(!tcon->quirks->has_channel_0);
425
426 tcon->dclk_min_div = 6;
427 tcon->dclk_max_div = 127;
428 sun4i_tcon0_mode_set_common(tcon, mode);
429
430
431 clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
432 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
433 SUN4I_TCON0_CTL_CLK_DELAY_MASK,
434 SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
435
436
437
438
439
440 bp = mode->crtc_htotal - mode->crtc_hsync_start;
441 DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
442 mode->crtc_htotal, bp);
443
444
445 regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
446 SUN4I_TCON0_BASIC1_H_TOTAL(mode->crtc_htotal) |
447 SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
448
449
450
451
452
453 bp = mode->crtc_vtotal - mode->crtc_vsync_start;
454 DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
455 mode->crtc_vtotal, bp);
456
457
458 regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
459 SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
460 SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
461
462
463 hsync = mode->crtc_hsync_end - mode->crtc_hsync_start;
464 vsync = mode->crtc_vsync_end - mode->crtc_vsync_start;
465 DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync);
466 regmap_write(tcon->regs, SUN4I_TCON0_BASIC3_REG,
467 SUN4I_TCON0_BASIC3_V_SYNC(vsync) |
468 SUN4I_TCON0_BASIC3_H_SYNC(hsync));
469
470
471 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
472 val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
473
474 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
475 val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
476
477 regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG,
478 SUN4I_TCON0_IO_POL_HSYNC_POSITIVE | SUN4I_TCON0_IO_POL_VSYNC_POSITIVE,
479 val);
480
481
482 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
483 SUN4I_TCON_GCTL_IOMAP_MASK,
484 SUN4I_TCON_GCTL_IOMAP_TCON0);
485
486
487 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
488}
489
490static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
491 const struct drm_display_mode *mode)
492{
493 unsigned int bp, hsync, vsync, vtotal;
494 u8 clk_delay;
495 u32 val;
496
497 WARN_ON(!tcon->quirks->has_channel_1);
498
499
500 clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
501
502
503 clk_delay = sun4i_tcon_get_clk_delay(mode, 1);
504 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
505 SUN4I_TCON1_CTL_CLK_DELAY_MASK,
506 SUN4I_TCON1_CTL_CLK_DELAY(clk_delay));
507
508
509 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
510 val = SUN4I_TCON1_CTL_INTERLACE_ENABLE;
511 else
512 val = 0;
513 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
514 SUN4I_TCON1_CTL_INTERLACE_ENABLE,
515 val);
516
517
518 regmap_write(tcon->regs, SUN4I_TCON1_BASIC0_REG,
519 SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay) |
520 SUN4I_TCON1_BASIC0_Y(mode->crtc_vdisplay));
521
522
523 regmap_write(tcon->regs, SUN4I_TCON1_BASIC1_REG,
524 SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay) |
525 SUN4I_TCON1_BASIC1_Y(mode->crtc_vdisplay));
526
527
528 regmap_write(tcon->regs, SUN4I_TCON1_BASIC2_REG,
529 SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay) |
530 SUN4I_TCON1_BASIC2_Y(mode->crtc_vdisplay));
531
532
533 bp = mode->crtc_htotal - mode->crtc_hsync_start;
534 DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
535 mode->htotal, bp);
536 regmap_write(tcon->regs, SUN4I_TCON1_BASIC3_REG,
537 SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal) |
538 SUN4I_TCON1_BASIC3_H_BACKPORCH(bp));
539
540 bp = mode->crtc_vtotal - mode->crtc_vsync_start;
541 DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
542 mode->crtc_vtotal, bp);
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557 vtotal = mode->vtotal;
558 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
559 vtotal = vtotal * 2;
560
561
562 regmap_write(tcon->regs, SUN4I_TCON1_BASIC4_REG,
563 SUN4I_TCON1_BASIC4_V_TOTAL(vtotal) |
564 SUN4I_TCON1_BASIC4_V_BACKPORCH(bp));
565
566
567 hsync = mode->crtc_hsync_end - mode->crtc_hsync_start;
568 vsync = mode->crtc_vsync_end - mode->crtc_vsync_start;
569 DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync);
570 regmap_write(tcon->regs, SUN4I_TCON1_BASIC5_REG,
571 SUN4I_TCON1_BASIC5_V_SYNC(vsync) |
572 SUN4I_TCON1_BASIC5_H_SYNC(hsync));
573
574
575 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
576 SUN4I_TCON_GCTL_IOMAP_MASK,
577 SUN4I_TCON_GCTL_IOMAP_TCON1);
578}
579
580void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
581 const struct drm_encoder *encoder,
582 const struct drm_display_mode *mode)
583{
584 struct sun6i_dsi *dsi;
585
586 switch (encoder->encoder_type) {
587 case DRM_MODE_ENCODER_DSI:
588
589
590
591
592 dsi = encoder_to_sun6i_dsi(encoder);
593 sun4i_tcon0_mode_set_cpu(tcon, dsi->device, mode);
594 break;
595 case DRM_MODE_ENCODER_LVDS:
596 sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
597 break;
598 case DRM_MODE_ENCODER_NONE:
599 sun4i_tcon0_mode_set_rgb(tcon, mode);
600 sun4i_tcon_set_mux(tcon, 0, encoder);
601 break;
602 case DRM_MODE_ENCODER_TVDAC:
603 case DRM_MODE_ENCODER_TMDS:
604 sun4i_tcon1_mode_set(tcon, mode);
605 sun4i_tcon_set_mux(tcon, 1, encoder);
606 break;
607 default:
608 DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
609 }
610}
611EXPORT_SYMBOL(sun4i_tcon_mode_set);
612
613static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
614 struct sun4i_crtc *scrtc)
615{
616 unsigned long flags;
617
618 spin_lock_irqsave(&dev->event_lock, flags);
619 if (scrtc->event) {
620 drm_crtc_send_vblank_event(&scrtc->crtc, scrtc->event);
621 drm_crtc_vblank_put(&scrtc->crtc);
622 scrtc->event = NULL;
623 }
624 spin_unlock_irqrestore(&dev->event_lock, flags);
625}
626
627static irqreturn_t sun4i_tcon_handler(int irq, void *private)
628{
629 struct sun4i_tcon *tcon = private;
630 struct drm_device *drm = tcon->drm;
631 struct sun4i_crtc *scrtc = tcon->crtc;
632 struct sunxi_engine *engine = scrtc->engine;
633 unsigned int status;
634
635 regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status);
636
637 if (!(status & (SUN4I_TCON_GINT0_VBLANK_INT(0) |
638 SUN4I_TCON_GINT0_VBLANK_INT(1) |
639 SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT)))
640 return IRQ_NONE;
641
642 drm_crtc_handle_vblank(&scrtc->crtc);
643 sun4i_tcon_finish_page_flip(drm, scrtc);
644
645
646 regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG,
647 SUN4I_TCON_GINT0_VBLANK_INT(0) |
648 SUN4I_TCON_GINT0_VBLANK_INT(1) |
649 SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT,
650 0);
651
652 if (engine->ops->vblank_quirk)
653 engine->ops->vblank_quirk(engine);
654
655 return IRQ_HANDLED;
656}
657
658static int sun4i_tcon_init_clocks(struct device *dev,
659 struct sun4i_tcon *tcon)
660{
661 tcon->clk = devm_clk_get(dev, "ahb");
662 if (IS_ERR(tcon->clk)) {
663 dev_err(dev, "Couldn't get the TCON bus clock\n");
664 return PTR_ERR(tcon->clk);
665 }
666 clk_prepare_enable(tcon->clk);
667
668 if (tcon->quirks->has_channel_0) {
669 tcon->sclk0 = devm_clk_get(dev, "tcon-ch0");
670 if (IS_ERR(tcon->sclk0)) {
671 dev_err(dev, "Couldn't get the TCON channel 0 clock\n");
672 return PTR_ERR(tcon->sclk0);
673 }
674 }
675
676 if (tcon->quirks->has_channel_1) {
677 tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
678 if (IS_ERR(tcon->sclk1)) {
679 dev_err(dev, "Couldn't get the TCON channel 1 clock\n");
680 return PTR_ERR(tcon->sclk1);
681 }
682 }
683
684 return 0;
685}
686
687static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
688{
689 clk_disable_unprepare(tcon->clk);
690}
691
692static int sun4i_tcon_init_irq(struct device *dev,
693 struct sun4i_tcon *tcon)
694{
695 struct platform_device *pdev = to_platform_device(dev);
696 int irq, ret;
697
698 irq = platform_get_irq(pdev, 0);
699 if (irq < 0) {
700 dev_err(dev, "Couldn't retrieve the TCON interrupt\n");
701 return irq;
702 }
703
704 ret = devm_request_irq(dev, irq, sun4i_tcon_handler, 0,
705 dev_name(dev), tcon);
706 if (ret) {
707 dev_err(dev, "Couldn't request the IRQ\n");
708 return ret;
709 }
710
711 return 0;
712}
713
714static struct regmap_config sun4i_tcon_regmap_config = {
715 .reg_bits = 32,
716 .val_bits = 32,
717 .reg_stride = 4,
718 .max_register = 0x800,
719};
720
721static int sun4i_tcon_init_regmap(struct device *dev,
722 struct sun4i_tcon *tcon)
723{
724 struct platform_device *pdev = to_platform_device(dev);
725 struct resource *res;
726 void __iomem *regs;
727
728 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
729 regs = devm_ioremap_resource(dev, res);
730 if (IS_ERR(regs))
731 return PTR_ERR(regs);
732
733 tcon->regs = devm_regmap_init_mmio(dev, regs,
734 &sun4i_tcon_regmap_config);
735 if (IS_ERR(tcon->regs)) {
736 dev_err(dev, "Couldn't create the TCON regmap\n");
737 return PTR_ERR(tcon->regs);
738 }
739
740
741 regmap_write(tcon->regs, SUN4I_TCON_GCTL_REG, 0);
742 regmap_write(tcon->regs, SUN4I_TCON_GINT0_REG, 0);
743 regmap_write(tcon->regs, SUN4I_TCON_GINT1_REG, 0);
744
745
746 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, ~0);
747 regmap_write(tcon->regs, SUN4I_TCON1_IO_TRI_REG, ~0);
748
749 return 0;
750}
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767static struct sunxi_engine *
768sun4i_tcon_find_engine_traverse(struct sun4i_drv *drv,
769 struct device_node *node)
770{
771 struct device_node *port, *ep, *remote;
772 struct sunxi_engine *engine = ERR_PTR(-EINVAL);
773
774 port = of_graph_get_port_by_id(node, 0);
775 if (!port)
776 return ERR_PTR(-EINVAL);
777
778
779
780
781
782
783
784
785
786
787 if (of_get_available_child_count(port) != 1)
788 goto out_put_port;
789
790
791 ep = of_get_next_available_child(port, NULL);
792 if (!ep)
793 goto out_put_port;
794
795 remote = of_graph_get_remote_port_parent(ep);
796 if (!remote)
797 goto out_put_ep;
798
799
800 list_for_each_entry(engine, &drv->engine_list, list)
801 if (remote == engine->node)
802 goto out_put_remote;
803
804
805 engine = sun4i_tcon_find_engine_traverse(drv, remote);
806
807out_put_remote:
808 of_node_put(remote);
809out_put_ep:
810 of_node_put(ep);
811out_put_port:
812 of_node_put(port);
813
814 return engine;
815}
816
817
818
819
820
821
822
823
824
825
826
827static int sun4i_tcon_of_get_id_from_port(struct device_node *port)
828{
829 struct device_node *ep;
830 int ret = -EINVAL;
831
832
833 for_each_available_child_of_node(port, ep) {
834 struct device_node *remote;
835 u32 reg;
836
837 remote = of_graph_get_remote_endpoint(ep);
838 if (!remote)
839 continue;
840
841 ret = of_property_read_u32(remote, "reg", ®);
842 if (ret)
843 continue;
844
845 ret = reg;
846 }
847
848 return ret;
849}
850
851
852
853
854
855
856static struct sunxi_engine *sun4i_tcon_get_engine_by_id(struct sun4i_drv *drv,
857 int id)
858{
859 struct sunxi_engine *engine;
860
861 list_for_each_entry(engine, &drv->engine_list, list)
862 if (engine->id == id)
863 return engine;
864
865 return ERR_PTR(-EINVAL);
866}
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
902 struct device_node *node)
903{
904 struct device_node *port;
905 struct sunxi_engine *engine;
906
907 port = of_graph_get_port_by_id(node, 0);
908 if (!port)
909 return ERR_PTR(-EINVAL);
910
911
912
913
914
915 if (of_get_child_count(port) > 1) {
916
917 int id = sun4i_tcon_of_get_id_from_port(port);
918
919
920 engine = sun4i_tcon_get_engine_by_id(drv, id);
921
922 of_node_put(port);
923 return engine;
924 }
925
926
927 of_node_put(port);
928 return sun4i_tcon_find_engine_traverse(drv, node);
929}
930
931static int sun4i_tcon_bind(struct device *dev, struct device *master,
932 void *data)
933{
934 struct drm_device *drm = data;
935 struct sun4i_drv *drv = drm->dev_private;
936 struct sunxi_engine *engine;
937 struct device_node *remote;
938 struct sun4i_tcon *tcon;
939 struct reset_control *edp_rstc;
940 bool has_lvds_rst, has_lvds_alt, can_lvds;
941 int ret;
942
943 engine = sun4i_tcon_find_engine(drv, dev->of_node);
944 if (IS_ERR(engine)) {
945 dev_err(dev, "Couldn't find matching engine\n");
946 return -EPROBE_DEFER;
947 }
948
949 tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
950 if (!tcon)
951 return -ENOMEM;
952 dev_set_drvdata(dev, tcon);
953 tcon->drm = drm;
954 tcon->dev = dev;
955 tcon->id = engine->id;
956 tcon->quirks = of_device_get_match_data(dev);
957
958 tcon->lcd_rst = devm_reset_control_get(dev, "lcd");
959 if (IS_ERR(tcon->lcd_rst)) {
960 dev_err(dev, "Couldn't get our reset line\n");
961 return PTR_ERR(tcon->lcd_rst);
962 }
963
964 if (tcon->quirks->needs_edp_reset) {
965 edp_rstc = devm_reset_control_get_shared(dev, "edp");
966 if (IS_ERR(edp_rstc)) {
967 dev_err(dev, "Couldn't get edp reset line\n");
968 return PTR_ERR(edp_rstc);
969 }
970
971 ret = reset_control_deassert(edp_rstc);
972 if (ret) {
973 dev_err(dev, "Couldn't deassert edp reset line\n");
974 return ret;
975 }
976 }
977
978
979 ret = reset_control_reset(tcon->lcd_rst);
980 if (ret) {
981 dev_err(dev, "Couldn't deassert our reset line\n");
982 return ret;
983 }
984
985 if (tcon->quirks->supports_lvds) {
986
987
988
989
990
991
992
993 tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
994 if (IS_ERR(tcon->lvds_rst)) {
995 dev_err(dev, "Couldn't get our reset line\n");
996 return PTR_ERR(tcon->lvds_rst);
997 } else if (tcon->lvds_rst) {
998 has_lvds_rst = true;
999 reset_control_reset(tcon->lvds_rst);
1000 } else {
1001 has_lvds_rst = false;
1002 }
1003
1004
1005
1006
1007
1008
1009
1010
1011 if (tcon->quirks->has_lvds_alt) {
1012 tcon->lvds_pll = devm_clk_get(dev, "lvds-alt");
1013 if (IS_ERR(tcon->lvds_pll)) {
1014 if (PTR_ERR(tcon->lvds_pll) == -ENOENT) {
1015 has_lvds_alt = false;
1016 } else {
1017 dev_err(dev, "Couldn't get the LVDS PLL\n");
1018 return PTR_ERR(tcon->lvds_pll);
1019 }
1020 } else {
1021 has_lvds_alt = true;
1022 }
1023 }
1024
1025 if (!has_lvds_rst ||
1026 (tcon->quirks->has_lvds_alt && !has_lvds_alt)) {
1027 dev_warn(dev, "Missing LVDS properties, Please upgrade your DT\n");
1028 dev_warn(dev, "LVDS output disabled\n");
1029 can_lvds = false;
1030 } else {
1031 can_lvds = true;
1032 }
1033 } else {
1034 can_lvds = false;
1035 }
1036
1037 ret = sun4i_tcon_init_clocks(dev, tcon);
1038 if (ret) {
1039 dev_err(dev, "Couldn't init our TCON clocks\n");
1040 goto err_assert_reset;
1041 }
1042
1043 ret = sun4i_tcon_init_regmap(dev, tcon);
1044 if (ret) {
1045 dev_err(dev, "Couldn't init our TCON regmap\n");
1046 goto err_free_clocks;
1047 }
1048
1049 if (tcon->quirks->has_channel_0) {
1050 ret = sun4i_dclk_create(dev, tcon);
1051 if (ret) {
1052 dev_err(dev, "Couldn't create our TCON dot clock\n");
1053 goto err_free_clocks;
1054 }
1055 }
1056
1057 ret = sun4i_tcon_init_irq(dev, tcon);
1058 if (ret) {
1059 dev_err(dev, "Couldn't init our TCON interrupts\n");
1060 goto err_free_dotclock;
1061 }
1062
1063 tcon->crtc = sun4i_crtc_init(drm, engine, tcon);
1064 if (IS_ERR(tcon->crtc)) {
1065 dev_err(dev, "Couldn't create our CRTC\n");
1066 ret = PTR_ERR(tcon->crtc);
1067 goto err_free_dotclock;
1068 }
1069
1070
1071
1072
1073
1074
1075 remote = of_graph_get_remote_node(dev->of_node, 1, 0);
1076 if (of_device_is_compatible(remote, "panel-lvds"))
1077 if (can_lvds)
1078 ret = sun4i_lvds_init(drm, tcon);
1079 else
1080 ret = -EINVAL;
1081 else
1082 ret = sun4i_rgb_init(drm, tcon);
1083 of_node_put(remote);
1084
1085 if (ret < 0)
1086 goto err_free_dotclock;
1087
1088 if (tcon->quirks->needs_de_be_mux) {
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
1100 SUN4I_TCON0_CTL_SRC_SEL_MASK,
1101 tcon->id);
1102 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
1103 SUN4I_TCON1_CTL_SRC_SEL_MASK,
1104 tcon->id);
1105 }
1106
1107 list_add_tail(&tcon->list, &drv->tcon_list);
1108
1109 return 0;
1110
1111err_free_dotclock:
1112 if (tcon->quirks->has_channel_0)
1113 sun4i_dclk_free(tcon);
1114err_free_clocks:
1115 sun4i_tcon_free_clocks(tcon);
1116err_assert_reset:
1117 reset_control_assert(tcon->lcd_rst);
1118 return ret;
1119}
1120
1121static void sun4i_tcon_unbind(struct device *dev, struct device *master,
1122 void *data)
1123{
1124 struct sun4i_tcon *tcon = dev_get_drvdata(dev);
1125
1126 list_del(&tcon->list);
1127 if (tcon->quirks->has_channel_0)
1128 sun4i_dclk_free(tcon);
1129 sun4i_tcon_free_clocks(tcon);
1130}
1131
1132static const struct component_ops sun4i_tcon_ops = {
1133 .bind = sun4i_tcon_bind,
1134 .unbind = sun4i_tcon_unbind,
1135};
1136
1137static int sun4i_tcon_probe(struct platform_device *pdev)
1138{
1139 struct device_node *node = pdev->dev.of_node;
1140 struct drm_bridge *bridge;
1141 struct drm_panel *panel;
1142 int ret;
1143
1144 ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
1145 if (ret == -EPROBE_DEFER)
1146 return ret;
1147
1148 return component_add(&pdev->dev, &sun4i_tcon_ops);
1149}
1150
1151static int sun4i_tcon_remove(struct platform_device *pdev)
1152{
1153 component_del(&pdev->dev, &sun4i_tcon_ops);
1154
1155 return 0;
1156}
1157
1158
1159static int sun4i_a10_tcon_set_mux(struct sun4i_tcon *tcon,
1160 const struct drm_encoder *encoder)
1161{
1162 struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
1163 u32 shift;
1164
1165 if (!tcon0)
1166 return -EINVAL;
1167
1168 switch (encoder->encoder_type) {
1169 case DRM_MODE_ENCODER_TMDS:
1170
1171 shift = 8;
1172 break;
1173 default:
1174 return -EINVAL;
1175 }
1176
1177 regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG,
1178 0x3 << shift, tcon->id << shift);
1179
1180 return 0;
1181}
1182
1183static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
1184 const struct drm_encoder *encoder)
1185{
1186 u32 val;
1187
1188 if (encoder->encoder_type == DRM_MODE_ENCODER_TVDAC)
1189 val = 1;
1190 else
1191 val = 0;
1192
1193
1194
1195
1196 return regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, val);
1197}
1198
1199static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
1200 const struct drm_encoder *encoder)
1201{
1202 struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
1203 u32 shift;
1204
1205 if (!tcon0)
1206 return -EINVAL;
1207
1208 switch (encoder->encoder_type) {
1209 case DRM_MODE_ENCODER_TMDS:
1210
1211 shift = 8;
1212 break;
1213 default:
1214
1215 return -EINVAL;
1216 }
1217
1218 regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG,
1219 0x3 << shift, tcon->id << shift);
1220
1221 return 0;
1222}
1223
1224static const struct sun4i_tcon_quirks sun4i_a10_quirks = {
1225 .has_channel_0 = true,
1226 .has_channel_1 = true,
1227 .set_mux = sun4i_a10_tcon_set_mux,
1228};
1229
1230static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
1231 .has_channel_0 = true,
1232 .has_channel_1 = true,
1233 .set_mux = sun5i_a13_tcon_set_mux,
1234};
1235
1236static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
1237 .has_channel_0 = true,
1238 .has_channel_1 = true,
1239 .has_lvds_alt = true,
1240 .needs_de_be_mux = true,
1241 .set_mux = sun6i_tcon_set_mux,
1242};
1243
1244static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
1245 .has_channel_0 = true,
1246 .has_channel_1 = true,
1247 .needs_de_be_mux = true,
1248};
1249
1250static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
1251 .has_channel_0 = true,
1252 .has_channel_1 = true,
1253
1254 .set_mux = sun4i_a10_tcon_set_mux,
1255};
1256
1257static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
1258 .has_channel_0 = true,
1259 .has_lvds_alt = true,
1260};
1261
1262static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
1263 .supports_lvds = true,
1264 .has_channel_0 = true,
1265};
1266
1267static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
1268 .has_channel_1 = true,
1269};
1270
1271static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
1272 .has_channel_0 = true,
1273};
1274
1275static const struct sun4i_tcon_quirks sun9i_a80_tcon_lcd_quirks = {
1276 .has_channel_0 = true,
1277 .needs_edp_reset = true,
1278};
1279
1280static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks = {
1281 .has_channel_1 = true,
1282 .needs_edp_reset = true,
1283};
1284
1285
1286const struct of_device_id sun4i_tcon_of_table[] = {
1287 { .compatible = "allwinner,sun4i-a10-tcon", .data = &sun4i_a10_quirks },
1288 { .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
1289 { .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
1290 { .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
1291 { .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks },
1292 { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
1293 { .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks },
1294 { .compatible = "allwinner,sun8i-a83t-tcon-tv", .data = &sun8i_a83t_tv_quirks },
1295 { .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
1296 { .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = &sun9i_a80_tcon_lcd_quirks },
1297 { .compatible = "allwinner,sun9i-a80-tcon-tv", .data = &sun9i_a80_tcon_tv_quirks },
1298 { }
1299};
1300MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
1301EXPORT_SYMBOL(sun4i_tcon_of_table);
1302
1303static struct platform_driver sun4i_tcon_platform_driver = {
1304 .probe = sun4i_tcon_probe,
1305 .remove = sun4i_tcon_remove,
1306 .driver = {
1307 .name = "sun4i-tcon",
1308 .of_match_table = sun4i_tcon_of_table,
1309 },
1310};
1311module_platform_driver(sun4i_tcon_platform_driver);
1312
1313MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
1314MODULE_DESCRIPTION("Allwinner A10 Timing Controller Driver");
1315MODULE_LICENSE("GPL");
1316