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