]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/sun4i: Add support for A80 TCONs
authorChen-Yu Tsai <wens@csie.org>
Thu, 15 Mar 2018 11:41:31 +0000 (19:41 +0800)
committerMaxime Ripard <maxime.ripard@bootlin.com>
Mon, 19 Mar 2018 14:37:21 +0000 (15:37 +0100)
The Allwinner A80 SoC has 2 documented TCONs. The display pipeline
diagram from the user manual shows a third TCON, but it's missing
an interrupt line, and its registers are not explained either.
It's also not used in Allwinner's vendor BSP.

The first TCON only has channel 0, for LCD panel output. The TCON
hardware setup is peculiar in that the eDP reset must also be
deasserted to allow access to the TCON. How the eDP module is wired
in the SoC itself is never explained.

The second TCON only has channel 1, and its output is connected to
the HDMI encoder block.

This patch adds a "needs_edp_reset" field to the tcon quirks structure,
and adds quirks and compatible strings for the 2 documented TCONs.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180315114136.24747-4-wens@csie.org
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/sun4i/sun4i_tcon.h

index 2809d0ccb1a7c27bf4c5971a52795aacda97430c..1a114e380f13ee8e13d970d18d57c8f4f930e093 100644 (file)
@@ -875,6 +875,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
        struct sunxi_engine *engine;
        struct device_node *remote;
        struct sun4i_tcon *tcon;
+       struct reset_control *edp_rstc;
        bool has_lvds_rst, has_lvds_alt, can_lvds;
        int ret;
 
@@ -899,6 +900,20 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
                return PTR_ERR(tcon->lcd_rst);
        }
 
+       if (tcon->quirks->needs_edp_reset) {
+               edp_rstc = devm_reset_control_get_shared(dev, "edp");
+               if (IS_ERR(edp_rstc)) {
+                       dev_err(dev, "Couldn't get edp reset line\n");
+                       return PTR_ERR(edp_rstc);
+               }
+
+               ret = reset_control_deassert(edp_rstc);
+               if (ret) {
+                       dev_err(dev, "Couldn't deassert edp reset line\n");
+                       return ret;
+               }
+       }
+
        /* Make sure our TCON is reset */
        ret = reset_control_reset(tcon->lcd_rst);
        if (ret) {
@@ -1191,6 +1206,16 @@ static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
        .has_channel_0          = true,
 };
 
+static const struct sun4i_tcon_quirks sun9i_a80_tcon_lcd_quirks = {
+       .has_channel_0  = true,
+       .needs_edp_reset = true,
+};
+
+static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks = {
+       .has_channel_1  = true,
+       .needs_edp_reset = true,
+};
+
 /* sun4i_drv uses this list to check if a device node is a TCON */
 const struct of_device_id sun4i_tcon_of_table[] = {
        { .compatible = "allwinner,sun4i-a10-tcon", .data = &sun4i_a10_quirks },
@@ -1202,6 +1227,8 @@ const struct of_device_id sun4i_tcon_of_table[] = {
        { .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks },
        { .compatible = "allwinner,sun8i-a83t-tcon-tv", .data = &sun8i_a83t_tv_quirks },
        { .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
+       { .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = &sun9i_a80_tcon_lcd_quirks },
+       { .compatible = "allwinner,sun9i-a80-tcon-tv", .data = &sun9i_a80_tcon_tv_quirks },
        { }
 };
 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
index 78d55e7cd2b3d286b6d16c19a94c28e55a50c91c..d3a945b7bb604330945cc4f07084b9d0dfc9dd34 100644 (file)
@@ -176,6 +176,7 @@ struct sun4i_tcon_quirks {
        bool    has_channel_1;  /* a33 does not have channel 1 */
        bool    has_lvds_alt;   /* Does the LVDS clock have a parent other than the TCON clock? */
        bool    needs_de_be_mux; /* sun6i needs mux to select backend */
+       bool    needs_edp_reset; /* a80 edp reset needed for tcon0 access */
 
        /* callback to handle tcon muxing options */
        int     (*set_mux)(struct sun4i_tcon *, const struct drm_encoder *);