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