2 * Copyright (C) 2015 Free Electrons
3 * Copyright (C) 2015 NextThing Co
5 * Maxime Ripard <maxime.ripard@free-electrons.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
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>
22 #include <uapi/drm/drm_mode.h>
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>
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"
40 static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
42 struct drm_connector *connector;
43 struct drm_connector_list_iter iter;
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);
51 drm_connector_list_iter_end(&iter);
56 static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
58 struct drm_connector *connector;
59 struct drm_display_info *info;
61 connector = sun4i_tcon_get_connector(encoder);
65 info = &connector->display_info;
66 if (info->num_bus_formats != 1)
69 switch (info->bus_formats[0]) {
70 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
73 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
74 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
81 static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
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);
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);
102 DRM_WARN("Unknown channel... doing nothing\n");
107 clk_prepare_enable(clk);
108 clk_rate_exclusive_get(clk);
110 clk_rate_exclusive_put(clk);
111 clk_disable_unprepare(clk);
115 static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon,
116 const struct drm_encoder *encoder,
122 regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
123 SUN4I_TCON0_LVDS_IF_EN,
124 SUN4I_TCON0_LVDS_IF_EN);
127 * As their name suggest, these values only apply to the A31
128 * and later SoCs. We'll have to rework this when merging
129 * support for the older SoCs.
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);
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);
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);
147 if (sun4i_tcon_get_pixel_depth(encoder) == 18)
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));
156 regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
157 SUN4I_TCON0_LVDS_IF_EN, 0);
161 void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
162 const struct drm_encoder *encoder,
165 bool is_lvds = false;
168 switch (encoder->encoder_type) {
169 case DRM_MODE_ENCODER_LVDS:
172 case DRM_MODE_ENCODER_NONE:
175 case DRM_MODE_ENCODER_TMDS:
176 case DRM_MODE_ENCODER_TVDAC:
180 DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
184 if (is_lvds && !enabled)
185 sun4i_tcon_lvds_set_status(tcon, encoder, false);
187 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
188 SUN4I_TCON_GCTL_TCON_ENABLE,
189 enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
191 if (is_lvds && enabled)
192 sun4i_tcon_lvds_set_status(tcon, encoder, true);
194 sun4i_tcon_channel_set_status(tcon, channel, enabled);
197 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
201 DRM_DEBUG_DRIVER("%sabling VBLANK interrupt\n", enable ? "En" : "Dis");
203 mask = SUN4I_TCON_GINT0_VBLANK_ENABLE(0) |
204 SUN4I_TCON_GINT0_VBLANK_ENABLE(1);
209 regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, mask, val);
211 EXPORT_SYMBOL(sun4i_tcon_enable_vblank);
214 * This function is a helper for TCON output muxing. The TCON output
215 * muxing control register in earlier SoCs (without the TCON TOP block)
216 * are located in TCON0. This helper returns a pointer to TCON0's
217 * sun4i_tcon structure, or NULL if not found.
219 static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
221 struct sun4i_drv *drv = drm->dev_private;
222 struct sun4i_tcon *tcon;
224 list_for_each_entry(tcon, &drv->tcon_list, list)
229 "TCON0 not found, display output muxing may not work\n");
234 void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
235 const struct drm_encoder *encoder)
239 if (tcon->quirks->set_mux)
240 ret = tcon->quirks->set_mux(tcon, encoder);
242 DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
243 encoder->name, encoder->crtc->name, ret);
246 static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
249 int delay = mode->vtotal - mode->vdisplay;
251 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
257 delay = min(delay, 30);
259 DRM_DEBUG_DRIVER("TCON %d clock delay %u\n", channel, delay);
264 static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
265 const struct drm_display_mode *mode)
267 /* Configure the dot clock */
268 clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
270 /* Set the resolution */
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));
276 static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
277 const struct drm_encoder *encoder,
278 const struct drm_display_mode *mode)
284 WARN_ON(!tcon->quirks->has_channel_0);
286 tcon->dclk_min_div = 7;
287 tcon->dclk_max_div = 7;
288 sun4i_tcon0_mode_set_common(tcon, mode);
290 /* Adjust clock delay */
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));
297 * This is called a backporch in the register documentation,
298 * but it really is the back porch + hsync
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);
304 /* Set horizontal display timings */
305 regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
306 SUN4I_TCON0_BASIC1_H_TOTAL(mode->htotal) |
307 SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
310 * This is called a backporch in the register documentation,
311 * but it really is the back porch + hsync
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);
317 /* Set vertical display timings */
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));
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;
328 reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
330 regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
332 /* Setup the polarity of the various signals */
333 if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
334 val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
336 if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
337 val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
339 regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
341 /* Map output pins to channel 0 */
342 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
343 SUN4I_TCON_GCTL_IOMAP_MASK,
344 SUN4I_TCON_GCTL_IOMAP_TCON0);
346 /* Enable the output on the pins */
347 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
350 static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
351 const struct drm_display_mode *mode)
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;
360 WARN_ON(!tcon->quirks->has_channel_0);
362 tcon->dclk_min_div = 6;
363 tcon->dclk_max_div = 127;
364 sun4i_tcon0_mode_set_common(tcon, mode);
366 /* Adjust clock delay */
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));
373 * This is called a backporch in the register documentation,
374 * but it really is the back porch + hsync
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);
380 /* Set horizontal display timings */
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));
386 * This is called a backporch in the register documentation,
387 * but it really is the back porch + hsync
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);
393 /* Set vertical display timings */
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));
398 /* Set Hsync and Vsync length */
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));
406 /* Setup the polarity of the various signals */
407 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
408 val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
410 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
411 val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
414 * On A20 and similar SoCs, the only way to achieve Positive Edge
415 * (Rising Edge), is setting dclk clock phase to 2/3(240°).
416 * By default TCON works in Negative Edge(Falling Edge),
417 * this is why phase is set to 0 in that case.
418 * Unfortunately there's no way to logically invert dclk through
420 * The only acceptable way to work, triple checked with scope,
421 * is using clock phase set to 0° for Negative Edge and set to 240°
423 * On A33 and similar SoCs there would be a 90° phase option,
424 * but it divides also dclk by 2.
425 * Following code is a way to avoid quirks all around TCON
426 * and DOTCLOCK drivers.
428 if (display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_POSEDGE)
429 clk_set_phase(tcon->dclk, 240);
431 if (display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE)
432 clk_set_phase(tcon->dclk, 0);
434 regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG,
435 SUN4I_TCON0_IO_POL_HSYNC_POSITIVE | SUN4I_TCON0_IO_POL_VSYNC_POSITIVE,
438 /* Map output pins to channel 0 */
439 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
440 SUN4I_TCON_GCTL_IOMAP_MASK,
441 SUN4I_TCON_GCTL_IOMAP_TCON0);
443 /* Enable the output on the pins */
444 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
447 static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
448 const struct drm_display_mode *mode)
450 unsigned int bp, hsync, vsync, vtotal;
454 WARN_ON(!tcon->quirks->has_channel_1);
456 /* Configure the dot clock */
457 clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
459 /* Adjust clock delay */
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));
465 /* Set interlaced mode */
466 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
467 val = SUN4I_TCON1_CTL_INTERLACE_ENABLE;
470 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
471 SUN4I_TCON1_CTL_INTERLACE_ENABLE,
474 /* Set the input resolution */
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));
479 /* Set the upscaling resolution */
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));
484 /* Set the output resolution */
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));
489 /* Set horizontal display timings */
490 bp = mode->crtc_htotal - mode->crtc_hsync_start;
491 DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
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));
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);
502 * The vertical resolution needs to be doubled in all
503 * cases. We could use crtc_vtotal and always multiply by two,
504 * but that leads to a rounding error in interlace when vtotal
507 * This happens with TV's PAL for example, where vtotal will
508 * be 625, crtc_vtotal 312, and thus crtc_vtotal * 2 will be
509 * 624, which apparently confuses the hardware.
511 * To work around this, we will always use vtotal, and
512 * multiply by two only if we're not in interlace.
514 vtotal = mode->vtotal;
515 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
518 /* Set vertical display timings */
519 regmap_write(tcon->regs, SUN4I_TCON1_BASIC4_REG,
520 SUN4I_TCON1_BASIC4_V_TOTAL(vtotal) |
521 SUN4I_TCON1_BASIC4_V_BACKPORCH(bp));
523 /* Set Hsync and Vsync length */
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));
531 /* Map output pins to channel 1 */
532 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
533 SUN4I_TCON_GCTL_IOMAP_MASK,
534 SUN4I_TCON_GCTL_IOMAP_TCON1);
537 void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
538 const struct drm_encoder *encoder,
539 const struct drm_display_mode *mode)
541 switch (encoder->encoder_type) {
542 case DRM_MODE_ENCODER_LVDS:
543 sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
545 case DRM_MODE_ENCODER_NONE:
546 sun4i_tcon0_mode_set_rgb(tcon, mode);
547 sun4i_tcon_set_mux(tcon, 0, encoder);
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);
555 DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
558 EXPORT_SYMBOL(sun4i_tcon_mode_set);
560 static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
561 struct sun4i_crtc *scrtc)
565 spin_lock_irqsave(&dev->event_lock, flags);
567 drm_crtc_send_vblank_event(&scrtc->crtc, scrtc->event);
568 drm_crtc_vblank_put(&scrtc->crtc);
571 spin_unlock_irqrestore(&dev->event_lock, flags);
574 static irqreturn_t sun4i_tcon_handler(int irq, void *private)
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;
582 regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status);
584 if (!(status & (SUN4I_TCON_GINT0_VBLANK_INT(0) |
585 SUN4I_TCON_GINT0_VBLANK_INT(1))))
588 drm_crtc_handle_vblank(&scrtc->crtc);
589 sun4i_tcon_finish_page_flip(drm, scrtc);
591 /* Acknowledge the interrupt */
592 regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG,
593 SUN4I_TCON_GINT0_VBLANK_INT(0) |
594 SUN4I_TCON_GINT0_VBLANK_INT(1),
597 if (engine->ops->vblank_quirk)
598 engine->ops->vblank_quirk(engine);
603 static int sun4i_tcon_init_clocks(struct device *dev,
604 struct sun4i_tcon *tcon)
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);
611 clk_prepare_enable(tcon->clk);
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);
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);
632 static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
634 clk_disable_unprepare(tcon->clk);
637 static int sun4i_tcon_init_irq(struct device *dev,
638 struct sun4i_tcon *tcon)
640 struct platform_device *pdev = to_platform_device(dev);
643 irq = platform_get_irq(pdev, 0);
645 dev_err(dev, "Couldn't retrieve the TCON interrupt\n");
649 ret = devm_request_irq(dev, irq, sun4i_tcon_handler, 0,
650 dev_name(dev), tcon);
652 dev_err(dev, "Couldn't request the IRQ\n");
659 static struct regmap_config sun4i_tcon_regmap_config = {
663 .max_register = 0x800,
666 static int sun4i_tcon_init_regmap(struct device *dev,
667 struct sun4i_tcon *tcon)
669 struct platform_device *pdev = to_platform_device(dev);
670 struct resource *res;
673 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
674 regs = devm_ioremap_resource(dev, res);
676 return PTR_ERR(regs);
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);
685 /* Make sure the TCON is disabled and all IRQs are off */
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);
690 /* Disable IO lines and set them to tristate */
691 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, ~0);
692 regmap_write(tcon->regs, SUN4I_TCON1_IO_TRI_REG, ~0);
698 * On SoCs with the old display pipeline design (Display Engine 1.0),
699 * the TCON is always tied to just one backend. Hence we can traverse
700 * the of_graph upwards to find the backend our tcon is connected to,
701 * and take its ID as our own.
703 * We can either identify backends from their compatible strings, which
704 * means maintaining a large list of them. Or, since the backend is
705 * registered and binded before the TCON, we can just go through the
706 * list of registered backends and compare the device node.
708 * As the structures now store engines instead of backends, here this
709 * function in fact searches the corresponding engine, and the ID is
710 * requested via the get_id function of the engine.
712 static struct sunxi_engine *
713 sun4i_tcon_find_engine_traverse(struct sun4i_drv *drv,
714 struct device_node *node)
716 struct device_node *port, *ep, *remote;
717 struct sunxi_engine *engine = ERR_PTR(-EINVAL);
719 port = of_graph_get_port_by_id(node, 0);
721 return ERR_PTR(-EINVAL);
724 * This only works if there is only one path from the TCON
725 * to any display engine. Otherwise the probe order of the
726 * TCONs and display engines is not guaranteed. They may
727 * either bind to the wrong one, or worse, bind to the same
728 * one if additional checks are not done.
730 * Bail out if there are multiple input connections.
732 if (of_get_available_child_count(port) != 1)
735 /* Get the first connection without specifying an ID */
736 ep = of_get_next_available_child(port, NULL);
740 remote = of_graph_get_remote_port_parent(ep);
744 /* does this node match any registered engines? */
745 list_for_each_entry(engine, &drv->engine_list, list)
746 if (remote == engine->node)
749 /* keep looking through upstream ports */
750 engine = sun4i_tcon_find_engine_traverse(drv, remote);
763 * The device tree binding says that the remote endpoint ID of any
764 * connection between components, up to and including the TCON, of
765 * the display pipeline should be equal to the actual ID of the local
766 * component. Thus we can look at any one of the input connections of
767 * the TCONs, and use that connection's remote endpoint ID as our own.
769 * Since the user of this function already finds the input port,
770 * the port is passed in directly without further checks.
772 static int sun4i_tcon_of_get_id_from_port(struct device_node *port)
774 struct device_node *ep;
777 /* try finding an upstream endpoint */
778 for_each_available_child_of_node(port, ep) {
779 struct device_node *remote;
782 remote = of_graph_get_remote_endpoint(ep);
786 ret = of_property_read_u32(remote, "reg", ®);
797 * Once we know the TCON's id, we can look through the list of
798 * engines to find a matching one. We assume all engines have
799 * been probed and added to the list.
801 static struct sunxi_engine *sun4i_tcon_get_engine_by_id(struct sun4i_drv *drv,
804 struct sunxi_engine *engine;
806 list_for_each_entry(engine, &drv->engine_list, list)
807 if (engine->id == id)
810 return ERR_PTR(-EINVAL);
814 * On SoCs with the old display pipeline design (Display Engine 1.0),
815 * we assumed the TCON was always tied to just one backend. However
816 * this proved not to be the case. On the A31, the TCON can select
817 * either backend as its source. On the A20 (and likely on the A10),
818 * the backend can choose which TCON to output to.
820 * The device tree binding says that the remote endpoint ID of any
821 * connection between components, up to and including the TCON, of
822 * the display pipeline should be equal to the actual ID of the local
823 * component. Thus we should be able to look at any one of the input
824 * connections of the TCONs, and use that connection's remote endpoint
827 * However the connections between the backend and TCON were assumed
828 * to be always singular, and their endpoit IDs were all incorrectly
829 * set to 0. This means for these old device trees, we cannot just look
830 * up the remote endpoint ID of a TCON input endpoint. TCON1 would be
831 * incorrectly identified as TCON0.
833 * This function first checks if the TCON node has 2 input endpoints.
834 * If so, then the device tree is a corrected version, and it will use
835 * sun4i_tcon_of_get_id() and sun4i_tcon_get_engine_by_id() from above
836 * to fetch the ID and engine directly. If not, then it is likely an
837 * old device trees, where the endpoint IDs were incorrect, but did not
838 * have endpoint connections between the backend and TCON across
839 * different display pipelines. It will fall back to the old method of
840 * traversing the of_graph to try and find a matching engine by device
843 * In the case of single display pipeline device trees, either method
846 static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
847 struct device_node *node)
849 struct device_node *port;
850 struct sunxi_engine *engine;
852 port = of_graph_get_port_by_id(node, 0);
854 return ERR_PTR(-EINVAL);
857 * Is this a corrected device tree with cross pipeline
858 * connections between the backend and TCON?
860 if (of_get_child_count(port) > 1) {
861 /* Get our ID directly from an upstream endpoint */
862 int id = sun4i_tcon_of_get_id_from_port(port);
864 /* Get our engine by matching our ID */
865 engine = sun4i_tcon_get_engine_by_id(drv, id);
871 /* Fallback to old method by traversing input endpoints */
873 return sun4i_tcon_find_engine_traverse(drv, node);
876 static int sun4i_tcon_bind(struct device *dev, struct device *master,
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;
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;
894 tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
897 dev_set_drvdata(dev, tcon);
900 tcon->id = engine->id;
901 tcon->quirks = of_device_get_match_data(dev);
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);
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);
916 ret = reset_control_deassert(edp_rstc);
918 dev_err(dev, "Couldn't deassert edp reset line\n");
923 /* Make sure our TCON is reset */
924 ret = reset_control_reset(tcon->lcd_rst);
926 dev_err(dev, "Couldn't deassert our reset line\n");
930 if (tcon->quirks->supports_lvds) {
932 * This can only be made optional since we've had DT
933 * nodes without the LVDS reset properties.
935 * If the property is missing, just disable LVDS, and
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) {
944 reset_control_reset(tcon->lvds_rst);
946 has_lvds_rst = false;
950 * This can only be made optional since we've had DT
951 * nodes without the LVDS reset properties.
953 * If the property is missing, just disable LVDS, and
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;
962 dev_err(dev, "Couldn't get the LVDS PLL\n");
963 return PTR_ERR(tcon->lvds_pll);
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");
982 ret = sun4i_tcon_init_clocks(dev, tcon);
984 dev_err(dev, "Couldn't init our TCON clocks\n");
985 goto err_assert_reset;
988 ret = sun4i_tcon_init_regmap(dev, tcon);
990 dev_err(dev, "Couldn't init our TCON regmap\n");
991 goto err_free_clocks;
994 if (tcon->quirks->has_channel_0) {
995 ret = sun4i_dclk_create(dev, tcon);
997 dev_err(dev, "Couldn't create our TCON dot clock\n");
998 goto err_free_clocks;
1002 ret = sun4i_tcon_init_irq(dev, tcon);
1004 dev_err(dev, "Couldn't init our TCON interrupts\n");
1005 goto err_free_dotclock;
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;
1016 * If we have an LVDS panel connected to the TCON, we should
1017 * just probe the LVDS connector. Otherwise, just probe RGB as
1020 remote = of_graph_get_remote_node(dev->of_node, 1, 0);
1021 if (of_device_is_compatible(remote, "panel-lvds"))
1023 ret = sun4i_lvds_init(drm, tcon);
1027 ret = sun4i_rgb_init(drm, tcon);
1028 of_node_put(remote);
1031 goto err_free_dotclock;
1033 if (tcon->quirks->needs_de_be_mux) {
1035 * We assume there is no dynamic muxing of backends
1036 * and TCONs, so we select the backend with same ID.
1038 * While dynamic selection might be interesting, since
1039 * the CRTC is tied to the TCON, while the layers are
1040 * tied to the backends, this means, we will need to
1041 * switch between groups of layers. There might not be
1042 * a way to represent this constraint in DRM.
1044 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
1045 SUN4I_TCON0_CTL_SRC_SEL_MASK,
1047 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
1048 SUN4I_TCON1_CTL_SRC_SEL_MASK,
1052 list_add_tail(&tcon->list, &drv->tcon_list);
1057 if (tcon->quirks->has_channel_0)
1058 sun4i_dclk_free(tcon);
1060 sun4i_tcon_free_clocks(tcon);
1062 reset_control_assert(tcon->lcd_rst);
1066 static void sun4i_tcon_unbind(struct device *dev, struct device *master,
1069 struct sun4i_tcon *tcon = dev_get_drvdata(dev);
1071 list_del(&tcon->list);
1072 if (tcon->quirks->has_channel_0)
1073 sun4i_dclk_free(tcon);
1074 sun4i_tcon_free_clocks(tcon);
1077 static const struct component_ops sun4i_tcon_ops = {
1078 .bind = sun4i_tcon_bind,
1079 .unbind = sun4i_tcon_unbind,
1082 static int sun4i_tcon_probe(struct platform_device *pdev)
1084 struct device_node *node = pdev->dev.of_node;
1085 struct drm_bridge *bridge;
1086 struct drm_panel *panel;
1089 ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
1090 if (ret == -EPROBE_DEFER)
1093 return component_add(&pdev->dev, &sun4i_tcon_ops);
1096 static int sun4i_tcon_remove(struct platform_device *pdev)
1098 component_del(&pdev->dev, &sun4i_tcon_ops);
1103 /* platform specific TCON muxing callbacks */
1104 static int sun4i_a10_tcon_set_mux(struct sun4i_tcon *tcon,
1105 const struct drm_encoder *encoder)
1107 struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
1113 switch (encoder->encoder_type) {
1114 case DRM_MODE_ENCODER_TMDS:
1122 regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG,
1123 0x3 << shift, tcon->id << shift);
1128 static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
1129 const struct drm_encoder *encoder)
1133 if (encoder->encoder_type == DRM_MODE_ENCODER_TVDAC)
1139 * FIXME: Undocumented bits
1141 return regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, val);
1144 static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
1145 const struct drm_encoder *encoder)
1147 struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
1153 switch (encoder->encoder_type) {
1154 case DRM_MODE_ENCODER_TMDS:
1159 /* TODO A31 has MIPI DSI but A31s does not */
1163 regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG,
1164 0x3 << shift, tcon->id << shift);
1169 static 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,
1175 static 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,
1181 static 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,
1189 static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
1190 .has_channel_0 = true,
1191 .has_channel_1 = true,
1192 .needs_de_be_mux = true,
1195 static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
1196 .has_channel_0 = true,
1197 .has_channel_1 = true,
1198 /* Same display pipeline structure as A10 */
1199 .set_mux = sun4i_a10_tcon_set_mux,
1202 static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
1203 .has_channel_0 = true,
1204 .has_lvds_alt = true,
1207 static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
1208 .supports_lvds = true,
1209 .has_channel_0 = true,
1212 static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
1213 .has_channel_1 = true,
1216 static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
1217 .has_channel_0 = true,
1220 static const struct sun4i_tcon_quirks sun9i_a80_tcon_lcd_quirks = {
1221 .has_channel_0 = true,
1222 .needs_edp_reset = true,
1225 static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks = {
1226 .has_channel_1 = true,
1227 .needs_edp_reset = true,
1230 /* sun4i_drv uses this list to check if a device node is a TCON */
1231 const 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 },
1245 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
1246 EXPORT_SYMBOL(sun4i_tcon_of_table);
1248 static struct platform_driver sun4i_tcon_platform_driver = {
1249 .probe = sun4i_tcon_probe,
1250 .remove = sun4i_tcon_remove,
1252 .name = "sun4i-tcon",
1253 .of_match_table = sun4i_tcon_of_table,
1256 module_platform_driver(sun4i_tcon_platform_driver);
1258 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
1259 MODULE_DESCRIPTION("Allwinner A10 Timing Controller Driver");
1260 MODULE_LICENSE("GPL");