Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2015 Free Electrons
0004  * Copyright (C) 2015 NextThing Co
0005  *
0006  * Maxime Ripard <maxime.ripard@free-electrons.com>
0007  */
0008 
0009 #include <linux/component.h>
0010 #include <linux/ioport.h>
0011 #include <linux/media-bus-format.h>
0012 #include <linux/module.h>
0013 #include <linux/of_address.h>
0014 #include <linux/of_device.h>
0015 #include <linux/of_irq.h>
0016 #include <linux/regmap.h>
0017 #include <linux/reset.h>
0018 
0019 #include <drm/drm_atomic_helper.h>
0020 #include <drm/drm_bridge.h>
0021 #include <drm/drm_connector.h>
0022 #include <drm/drm_crtc.h>
0023 #include <drm/drm_encoder.h>
0024 #include <drm/drm_modes.h>
0025 #include <drm/drm_of.h>
0026 #include <drm/drm_panel.h>
0027 #include <drm/drm_print.h>
0028 #include <drm/drm_probe_helper.h>
0029 #include <drm/drm_vblank.h>
0030 
0031 #include <uapi/drm/drm_mode.h>
0032 
0033 #include "sun4i_crtc.h"
0034 #include "sun4i_dotclock.h"
0035 #include "sun4i_drv.h"
0036 #include "sun4i_lvds.h"
0037 #include "sun4i_rgb.h"
0038 #include "sun4i_tcon.h"
0039 #include "sun6i_mipi_dsi.h"
0040 #include "sun8i_tcon_top.h"
0041 #include "sunxi_engine.h"
0042 
0043 static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
0044 {
0045     struct drm_connector *connector;
0046     struct drm_connector_list_iter iter;
0047 
0048     drm_connector_list_iter_begin(encoder->dev, &iter);
0049     drm_for_each_connector_iter(connector, &iter)
0050         if (connector->encoder == encoder) {
0051             drm_connector_list_iter_end(&iter);
0052             return connector;
0053         }
0054     drm_connector_list_iter_end(&iter);
0055 
0056     return NULL;
0057 }
0058 
0059 static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
0060 {
0061     struct drm_connector *connector;
0062     struct drm_display_info *info;
0063 
0064     connector = sun4i_tcon_get_connector(encoder);
0065     if (!connector)
0066         return -EINVAL;
0067 
0068     info = &connector->display_info;
0069     if (info->num_bus_formats != 1)
0070         return -EINVAL;
0071 
0072     switch (info->bus_formats[0]) {
0073     case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
0074         return 18;
0075 
0076     case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
0077     case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
0078         return 24;
0079     }
0080 
0081     return -EINVAL;
0082 }
0083 
0084 static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
0085                       bool enabled)
0086 {
0087     struct clk *clk;
0088 
0089     switch (channel) {
0090     case 0:
0091         WARN_ON(!tcon->quirks->has_channel_0);
0092         regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
0093                    SUN4I_TCON0_CTL_TCON_ENABLE,
0094                    enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0);
0095         clk = tcon->dclk;
0096         break;
0097     case 1:
0098         WARN_ON(!tcon->quirks->has_channel_1);
0099         regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
0100                    SUN4I_TCON1_CTL_TCON_ENABLE,
0101                    enabled ? SUN4I_TCON1_CTL_TCON_ENABLE : 0);
0102         clk = tcon->sclk1;
0103         break;
0104     default:
0105         DRM_WARN("Unknown channel... doing nothing\n");
0106         return;
0107     }
0108 
0109     if (enabled) {
0110         clk_prepare_enable(clk);
0111         clk_rate_exclusive_get(clk);
0112     } else {
0113         clk_rate_exclusive_put(clk);
0114         clk_disable_unprepare(clk);
0115     }
0116 }
0117 
0118 static void sun4i_tcon_setup_lvds_phy(struct sun4i_tcon *tcon,
0119                       const struct drm_encoder *encoder)
0120 {
0121     regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
0122              SUN4I_TCON0_LVDS_ANA0_CK_EN |
0123              SUN4I_TCON0_LVDS_ANA0_REG_V |
0124              SUN4I_TCON0_LVDS_ANA0_REG_C |
0125              SUN4I_TCON0_LVDS_ANA0_EN_MB |
0126              SUN4I_TCON0_LVDS_ANA0_PD |
0127              SUN4I_TCON0_LVDS_ANA0_DCHS);
0128 
0129     udelay(2); /* delay at least 1200 ns */
0130     regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG,
0131                SUN4I_TCON0_LVDS_ANA1_INIT,
0132                SUN4I_TCON0_LVDS_ANA1_INIT);
0133     udelay(1); /* delay at least 120 ns */
0134     regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG,
0135                SUN4I_TCON0_LVDS_ANA1_UPDATE,
0136                SUN4I_TCON0_LVDS_ANA1_UPDATE);
0137     regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
0138                SUN4I_TCON0_LVDS_ANA0_EN_MB,
0139                SUN4I_TCON0_LVDS_ANA0_EN_MB);
0140 }
0141 
0142 static void sun6i_tcon_setup_lvds_phy(struct sun4i_tcon *tcon,
0143                       const struct drm_encoder *encoder)
0144 {
0145     u8 val;
0146 
0147     regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
0148              SUN6I_TCON0_LVDS_ANA0_C(2) |
0149              SUN6I_TCON0_LVDS_ANA0_V(3) |
0150              SUN6I_TCON0_LVDS_ANA0_PD(2) |
0151              SUN6I_TCON0_LVDS_ANA0_EN_LDO);
0152     udelay(2);
0153 
0154     regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
0155                SUN6I_TCON0_LVDS_ANA0_EN_MB,
0156                SUN6I_TCON0_LVDS_ANA0_EN_MB);
0157     udelay(2);
0158 
0159     regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
0160                SUN6I_TCON0_LVDS_ANA0_EN_DRVC,
0161                SUN6I_TCON0_LVDS_ANA0_EN_DRVC);
0162 
0163     if (sun4i_tcon_get_pixel_depth(encoder) == 18)
0164         val = 7;
0165     else
0166         val = 0xf;
0167 
0168     regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
0169               SUN6I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
0170               SUN6I_TCON0_LVDS_ANA0_EN_DRVD(val));
0171 }
0172 
0173 static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon,
0174                        const struct drm_encoder *encoder,
0175                        bool enabled)
0176 {
0177     if (enabled) {
0178         regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
0179                    SUN4I_TCON0_LVDS_IF_EN,
0180                    SUN4I_TCON0_LVDS_IF_EN);
0181         if (tcon->quirks->setup_lvds_phy)
0182             tcon->quirks->setup_lvds_phy(tcon, encoder);
0183     } else {
0184         regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
0185                    SUN4I_TCON0_LVDS_IF_EN, 0);
0186     }
0187 }
0188 
0189 void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
0190                const struct drm_encoder *encoder,
0191                bool enabled)
0192 {
0193     bool is_lvds = false;
0194     int channel;
0195 
0196     switch (encoder->encoder_type) {
0197     case DRM_MODE_ENCODER_LVDS:
0198         is_lvds = true;
0199         fallthrough;
0200     case DRM_MODE_ENCODER_DSI:
0201     case DRM_MODE_ENCODER_NONE:
0202         channel = 0;
0203         break;
0204     case DRM_MODE_ENCODER_TMDS:
0205     case DRM_MODE_ENCODER_TVDAC:
0206         channel = 1;
0207         break;
0208     default:
0209         DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
0210         return;
0211     }
0212 
0213     if (is_lvds && !enabled)
0214         sun4i_tcon_lvds_set_status(tcon, encoder, false);
0215 
0216     regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
0217                SUN4I_TCON_GCTL_TCON_ENABLE,
0218                enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
0219 
0220     if (is_lvds && enabled)
0221         sun4i_tcon_lvds_set_status(tcon, encoder, true);
0222 
0223     sun4i_tcon_channel_set_status(tcon, channel, enabled);
0224 }
0225 
0226 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
0227 {
0228     u32 mask, val = 0;
0229 
0230     DRM_DEBUG_DRIVER("%sabling VBLANK interrupt\n", enable ? "En" : "Dis");
0231 
0232     mask = SUN4I_TCON_GINT0_VBLANK_ENABLE(0) |
0233         SUN4I_TCON_GINT0_VBLANK_ENABLE(1) |
0234         SUN4I_TCON_GINT0_TCON0_TRI_FINISH_ENABLE;
0235 
0236     if (enable)
0237         val = mask;
0238 
0239     regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, mask, val);
0240 }
0241 EXPORT_SYMBOL(sun4i_tcon_enable_vblank);
0242 
0243 /*
0244  * This function is a helper for TCON output muxing. The TCON output
0245  * muxing control register in earlier SoCs (without the TCON TOP block)
0246  * are located in TCON0. This helper returns a pointer to TCON0's
0247  * sun4i_tcon structure, or NULL if not found.
0248  */
0249 static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
0250 {
0251     struct sun4i_drv *drv = drm->dev_private;
0252     struct sun4i_tcon *tcon;
0253 
0254     list_for_each_entry(tcon, &drv->tcon_list, list)
0255         if (tcon->id == 0)
0256             return tcon;
0257 
0258     dev_warn(drm->dev,
0259          "TCON0 not found, display output muxing may not work\n");
0260 
0261     return NULL;
0262 }
0263 
0264 static void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
0265                    const struct drm_encoder *encoder)
0266 {
0267     int ret = -ENOTSUPP;
0268 
0269     if (tcon->quirks->set_mux)
0270         ret = tcon->quirks->set_mux(tcon, encoder);
0271 
0272     DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
0273              encoder->name, encoder->crtc->name, ret);
0274 }
0275 
0276 static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
0277                     int channel)
0278 {
0279     int delay = mode->vtotal - mode->vdisplay;
0280 
0281     if (mode->flags & DRM_MODE_FLAG_INTERLACE)
0282         delay /= 2;
0283 
0284     if (channel == 1)
0285         delay -= 2;
0286 
0287     delay = min(delay, 30);
0288 
0289     DRM_DEBUG_DRIVER("TCON %d clock delay %u\n", channel, delay);
0290 
0291     return delay;
0292 }
0293 
0294 static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
0295                     const struct drm_display_mode *mode)
0296 {
0297     /* Configure the dot clock */
0298     clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
0299 
0300     /* Set the resolution */
0301     regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
0302              SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
0303              SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
0304 }
0305 
0306 static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
0307                        const struct drm_connector *connector)
0308 {
0309     u32 bus_format = 0;
0310     u32 val = 0;
0311 
0312     /* XXX Would this ever happen? */
0313     if (!connector)
0314         return;
0315 
0316     /*
0317      * FIXME: Undocumented bits
0318      *
0319      * The whole dithering process and these parameters are not
0320      * explained in the vendor documents or BSP kernel code.
0321      */
0322     regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PR_REG, 0x11111111);
0323     regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PG_REG, 0x11111111);
0324     regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PB_REG, 0x11111111);
0325     regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LR_REG, 0x11111111);
0326     regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LG_REG, 0x11111111);
0327     regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LB_REG, 0x11111111);
0328     regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL0_REG, 0x01010000);
0329     regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL1_REG, 0x15151111);
0330     regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL2_REG, 0x57575555);
0331     regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL3_REG, 0x7f7f7777);
0332 
0333     /* Do dithering if panel only supports 6 bits per color */
0334     if (connector->display_info.bpc == 6)
0335         val |= SUN4I_TCON0_FRM_CTL_EN;
0336 
0337     if (connector->display_info.num_bus_formats == 1)
0338         bus_format = connector->display_info.bus_formats[0];
0339 
0340     /* Check the connection format */
0341     switch (bus_format) {
0342     case MEDIA_BUS_FMT_RGB565_1X16:
0343         /* R and B components are only 5 bits deep */
0344         val |= SUN4I_TCON0_FRM_CTL_MODE_R;
0345         val |= SUN4I_TCON0_FRM_CTL_MODE_B;
0346         fallthrough;
0347     case MEDIA_BUS_FMT_RGB666_1X18:
0348     case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
0349         /* Fall through: enable dithering */
0350         val |= SUN4I_TCON0_FRM_CTL_EN;
0351         break;
0352     }
0353 
0354     /* Write dithering settings */
0355     regmap_write(tcon->regs, SUN4I_TCON_FRM_CTL_REG, val);
0356 }
0357 
0358 static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
0359                      const struct drm_encoder *encoder,
0360                      const struct drm_display_mode *mode)
0361 {
0362     /* TODO support normal CPU interface modes */
0363     struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
0364     struct mipi_dsi_device *device = dsi->device;
0365     u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
0366     u8 lanes = device->lanes;
0367     u32 block_space, start_delay;
0368     u32 tcon_div;
0369 
0370     tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
0371     tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
0372 
0373     sun4i_tcon0_mode_set_common(tcon, mode);
0374 
0375     /* Set dithering if needed */
0376     sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
0377 
0378     regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
0379                SUN4I_TCON0_CTL_IF_MASK,
0380                SUN4I_TCON0_CTL_IF_8080);
0381 
0382     regmap_write(tcon->regs, SUN4I_TCON_ECC_FIFO_REG,
0383              SUN4I_TCON_ECC_FIFO_EN);
0384 
0385     regmap_write(tcon->regs, SUN4I_TCON0_CPU_IF_REG,
0386              SUN4I_TCON0_CPU_IF_MODE_DSI |
0387              SUN4I_TCON0_CPU_IF_TRI_FIFO_FLUSH |
0388              SUN4I_TCON0_CPU_IF_TRI_FIFO_EN |
0389              SUN4I_TCON0_CPU_IF_TRI_EN);
0390 
0391     /*
0392      * This looks suspicious, but it works...
0393      *
0394      * The datasheet says that this should be set higher than 20 *
0395      * pixel cycle, but it's not clear what a pixel cycle is.
0396      */
0397     regmap_read(tcon->regs, SUN4I_TCON0_DCLK_REG, &tcon_div);
0398     tcon_div &= GENMASK(6, 0);
0399     block_space = mode->htotal * bpp / (tcon_div * lanes);
0400     block_space -= mode->hdisplay + 40;
0401 
0402     regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
0403              SUN4I_TCON0_CPU_TRI0_BLOCK_SPACE(block_space) |
0404              SUN4I_TCON0_CPU_TRI0_BLOCK_SIZE(mode->hdisplay));
0405 
0406     regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI1_REG,
0407              SUN4I_TCON0_CPU_TRI1_BLOCK_NUM(mode->vdisplay));
0408 
0409     start_delay = (mode->crtc_vtotal - mode->crtc_vdisplay - 10 - 1);
0410     start_delay = start_delay * mode->crtc_htotal * 149;
0411     start_delay = start_delay / (mode->crtc_clock / 1000) / 8;
0412     regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI2_REG,
0413              SUN4I_TCON0_CPU_TRI2_TRANS_START_SET(10) |
0414              SUN4I_TCON0_CPU_TRI2_START_DELAY(start_delay));
0415 
0416     /*
0417      * The Allwinner BSP has a comment that the period should be
0418      * the display clock * 15, but uses an hardcoded 3000...
0419      */
0420     regmap_write(tcon->regs, SUN4I_TCON_SAFE_PERIOD_REG,
0421              SUN4I_TCON_SAFE_PERIOD_NUM(3000) |
0422              SUN4I_TCON_SAFE_PERIOD_MODE(3));
0423 
0424     /* Enable the output on the pins */
0425     regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG,
0426              0xe0000000);
0427 }
0428 
0429 static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
0430                       const struct drm_encoder *encoder,
0431                       const struct drm_display_mode *mode)
0432 {
0433     unsigned int bp;
0434     u8 clk_delay;
0435     u32 reg, val = 0;
0436 
0437     WARN_ON(!tcon->quirks->has_channel_0);
0438 
0439     tcon->dclk_min_div = 7;
0440     tcon->dclk_max_div = 7;
0441     sun4i_tcon0_mode_set_common(tcon, mode);
0442 
0443     /* Set dithering if needed */
0444     sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
0445 
0446     /* Adjust clock delay */
0447     clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
0448     regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
0449                SUN4I_TCON0_CTL_CLK_DELAY_MASK,
0450                SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
0451 
0452     /*
0453      * This is called a backporch in the register documentation,
0454      * but it really is the back porch + hsync
0455      */
0456     bp = mode->crtc_htotal - mode->crtc_hsync_start;
0457     DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
0458              mode->crtc_htotal, bp);
0459 
0460     /* Set horizontal display timings */
0461     regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
0462              SUN4I_TCON0_BASIC1_H_TOTAL(mode->htotal) |
0463              SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
0464 
0465     /*
0466      * This is called a backporch in the register documentation,
0467      * but it really is the back porch + hsync
0468      */
0469     bp = mode->crtc_vtotal - mode->crtc_vsync_start;
0470     DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
0471              mode->crtc_vtotal, bp);
0472 
0473     /* Set vertical display timings */
0474     regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
0475              SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
0476              SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
0477 
0478     reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0;
0479     if (sun4i_tcon_get_pixel_depth(encoder) == 24)
0480         reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
0481     else
0482         reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
0483 
0484     regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
0485 
0486     /* Setup the polarity of the various signals */
0487     if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
0488         val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
0489 
0490     if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
0491         val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
0492 
0493     regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
0494 
0495     /* Map output pins to channel 0 */
0496     regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
0497                SUN4I_TCON_GCTL_IOMAP_MASK,
0498                SUN4I_TCON_GCTL_IOMAP_TCON0);
0499 
0500     /* Enable the output on the pins */
0501     regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
0502 }
0503 
0504 static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
0505                      const struct drm_encoder *encoder,
0506                      const struct drm_display_mode *mode)
0507 {
0508     struct drm_connector *connector = sun4i_tcon_get_connector(encoder);
0509     const struct drm_display_info *info = &connector->display_info;
0510     unsigned int bp, hsync, vsync;
0511     u8 clk_delay;
0512     u32 val = 0;
0513 
0514     WARN_ON(!tcon->quirks->has_channel_0);
0515 
0516     tcon->dclk_min_div = tcon->quirks->dclk_min_div;
0517     tcon->dclk_max_div = 127;
0518     sun4i_tcon0_mode_set_common(tcon, mode);
0519 
0520     /* Set dithering if needed */
0521     sun4i_tcon0_mode_set_dithering(tcon, connector);
0522 
0523     /* Adjust clock delay */
0524     clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
0525     regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
0526                SUN4I_TCON0_CTL_CLK_DELAY_MASK,
0527                SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
0528 
0529     /*
0530      * This is called a backporch in the register documentation,
0531      * but it really is the back porch + hsync
0532      */
0533     bp = mode->crtc_htotal - mode->crtc_hsync_start;
0534     DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
0535              mode->crtc_htotal, bp);
0536 
0537     /* Set horizontal display timings */
0538     regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
0539              SUN4I_TCON0_BASIC1_H_TOTAL(mode->crtc_htotal) |
0540              SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
0541 
0542     /*
0543      * This is called a backporch in the register documentation,
0544      * but it really is the back porch + hsync
0545      */
0546     bp = mode->crtc_vtotal - mode->crtc_vsync_start;
0547     DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
0548              mode->crtc_vtotal, bp);
0549 
0550     /* Set vertical display timings */
0551     regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
0552              SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
0553              SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
0554 
0555     /* Set Hsync and Vsync length */
0556     hsync = mode->crtc_hsync_end - mode->crtc_hsync_start;
0557     vsync = mode->crtc_vsync_end - mode->crtc_vsync_start;
0558     DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync);
0559     regmap_write(tcon->regs, SUN4I_TCON0_BASIC3_REG,
0560              SUN4I_TCON0_BASIC3_V_SYNC(vsync) |
0561              SUN4I_TCON0_BASIC3_H_SYNC(hsync));
0562 
0563     /* Setup the polarity of the various signals */
0564     if (mode->flags & DRM_MODE_FLAG_PHSYNC)
0565         val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
0566 
0567     if (mode->flags & DRM_MODE_FLAG_PVSYNC)
0568         val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
0569 
0570     if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
0571         val |= SUN4I_TCON0_IO_POL_DE_NEGATIVE;
0572 
0573     if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
0574         val |= SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE;
0575 
0576     regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG,
0577                SUN4I_TCON0_IO_POL_HSYNC_POSITIVE |
0578                SUN4I_TCON0_IO_POL_VSYNC_POSITIVE |
0579                SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE |
0580                SUN4I_TCON0_IO_POL_DE_NEGATIVE,
0581                val);
0582 
0583     /* Map output pins to channel 0 */
0584     regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
0585                SUN4I_TCON_GCTL_IOMAP_MASK,
0586                SUN4I_TCON_GCTL_IOMAP_TCON0);
0587 
0588     /* Enable the output on the pins */
0589     regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
0590 }
0591 
0592 static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
0593                  const struct drm_display_mode *mode)
0594 {
0595     unsigned int bp, hsync, vsync, vtotal;
0596     u8 clk_delay;
0597     u32 val;
0598 
0599     WARN_ON(!tcon->quirks->has_channel_1);
0600 
0601     /* Configure the dot clock */
0602     clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
0603 
0604     /* Adjust clock delay */
0605     clk_delay = sun4i_tcon_get_clk_delay(mode, 1);
0606     regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
0607                SUN4I_TCON1_CTL_CLK_DELAY_MASK,
0608                SUN4I_TCON1_CTL_CLK_DELAY(clk_delay));
0609 
0610     /* Set interlaced mode */
0611     if (mode->flags & DRM_MODE_FLAG_INTERLACE)
0612         val = SUN4I_TCON1_CTL_INTERLACE_ENABLE;
0613     else
0614         val = 0;
0615     regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
0616                SUN4I_TCON1_CTL_INTERLACE_ENABLE,
0617                val);
0618 
0619     /* Set the input resolution */
0620     regmap_write(tcon->regs, SUN4I_TCON1_BASIC0_REG,
0621              SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay) |
0622              SUN4I_TCON1_BASIC0_Y(mode->crtc_vdisplay));
0623 
0624     /* Set the upscaling resolution */
0625     regmap_write(tcon->regs, SUN4I_TCON1_BASIC1_REG,
0626              SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay) |
0627              SUN4I_TCON1_BASIC1_Y(mode->crtc_vdisplay));
0628 
0629     /* Set the output resolution */
0630     regmap_write(tcon->regs, SUN4I_TCON1_BASIC2_REG,
0631              SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay) |
0632              SUN4I_TCON1_BASIC2_Y(mode->crtc_vdisplay));
0633 
0634     /* Set horizontal display timings */
0635     bp = mode->crtc_htotal - mode->crtc_hsync_start;
0636     DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
0637              mode->htotal, bp);
0638     regmap_write(tcon->regs, SUN4I_TCON1_BASIC3_REG,
0639              SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal) |
0640              SUN4I_TCON1_BASIC3_H_BACKPORCH(bp));
0641 
0642     bp = mode->crtc_vtotal - mode->crtc_vsync_start;
0643     DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
0644              mode->crtc_vtotal, bp);
0645 
0646     /*
0647      * The vertical resolution needs to be doubled in all
0648      * cases. We could use crtc_vtotal and always multiply by two,
0649      * but that leads to a rounding error in interlace when vtotal
0650      * is odd.
0651      *
0652      * This happens with TV's PAL for example, where vtotal will
0653      * be 625, crtc_vtotal 312, and thus crtc_vtotal * 2 will be
0654      * 624, which apparently confuses the hardware.
0655      *
0656      * To work around this, we will always use vtotal, and
0657      * multiply by two only if we're not in interlace.
0658      */
0659     vtotal = mode->vtotal;
0660     if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
0661         vtotal = vtotal * 2;
0662 
0663     /* Set vertical display timings */
0664     regmap_write(tcon->regs, SUN4I_TCON1_BASIC4_REG,
0665              SUN4I_TCON1_BASIC4_V_TOTAL(vtotal) |
0666              SUN4I_TCON1_BASIC4_V_BACKPORCH(bp));
0667 
0668     /* Set Hsync and Vsync length */
0669     hsync = mode->crtc_hsync_end - mode->crtc_hsync_start;
0670     vsync = mode->crtc_vsync_end - mode->crtc_vsync_start;
0671     DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync);
0672     regmap_write(tcon->regs, SUN4I_TCON1_BASIC5_REG,
0673              SUN4I_TCON1_BASIC5_V_SYNC(vsync) |
0674              SUN4I_TCON1_BASIC5_H_SYNC(hsync));
0675 
0676     /* Setup the polarity of multiple signals */
0677     if (tcon->quirks->polarity_in_ch0) {
0678         val = 0;
0679 
0680         if (mode->flags & DRM_MODE_FLAG_PHSYNC)
0681             val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
0682 
0683         if (mode->flags & DRM_MODE_FLAG_PVSYNC)
0684             val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
0685 
0686         regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
0687     } else {
0688         /* according to vendor driver, this bit must be always set */
0689         val = SUN4I_TCON1_IO_POL_UNKNOWN;
0690 
0691         if (mode->flags & DRM_MODE_FLAG_PHSYNC)
0692             val |= SUN4I_TCON1_IO_POL_HSYNC_POSITIVE;
0693 
0694         if (mode->flags & DRM_MODE_FLAG_PVSYNC)
0695             val |= SUN4I_TCON1_IO_POL_VSYNC_POSITIVE;
0696 
0697         regmap_write(tcon->regs, SUN4I_TCON1_IO_POL_REG, val);
0698     }
0699 
0700     /* Map output pins to channel 1 */
0701     regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
0702                SUN4I_TCON_GCTL_IOMAP_MASK,
0703                SUN4I_TCON_GCTL_IOMAP_TCON1);
0704 }
0705 
0706 void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
0707              const struct drm_encoder *encoder,
0708              const struct drm_display_mode *mode)
0709 {
0710     switch (encoder->encoder_type) {
0711     case DRM_MODE_ENCODER_DSI:
0712         /* DSI is tied to special case of CPU interface */
0713         sun4i_tcon0_mode_set_cpu(tcon, encoder, mode);
0714         break;
0715     case DRM_MODE_ENCODER_LVDS:
0716         sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
0717         break;
0718     case DRM_MODE_ENCODER_NONE:
0719         sun4i_tcon0_mode_set_rgb(tcon, encoder, mode);
0720         sun4i_tcon_set_mux(tcon, 0, encoder);
0721         break;
0722     case DRM_MODE_ENCODER_TVDAC:
0723     case DRM_MODE_ENCODER_TMDS:
0724         sun4i_tcon1_mode_set(tcon, mode);
0725         sun4i_tcon_set_mux(tcon, 1, encoder);
0726         break;
0727     default:
0728         DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
0729     }
0730 }
0731 EXPORT_SYMBOL(sun4i_tcon_mode_set);
0732 
0733 static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
0734                     struct sun4i_crtc *scrtc)
0735 {
0736     unsigned long flags;
0737 
0738     spin_lock_irqsave(&dev->event_lock, flags);
0739     if (scrtc->event) {
0740         drm_crtc_send_vblank_event(&scrtc->crtc, scrtc->event);
0741         drm_crtc_vblank_put(&scrtc->crtc);
0742         scrtc->event = NULL;
0743     }
0744     spin_unlock_irqrestore(&dev->event_lock, flags);
0745 }
0746 
0747 static irqreturn_t sun4i_tcon_handler(int irq, void *private)
0748 {
0749     struct sun4i_tcon *tcon = private;
0750     struct drm_device *drm = tcon->drm;
0751     struct sun4i_crtc *scrtc = tcon->crtc;
0752     struct sunxi_engine *engine = scrtc->engine;
0753     unsigned int status;
0754 
0755     regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status);
0756 
0757     if (!(status & (SUN4I_TCON_GINT0_VBLANK_INT(0) |
0758             SUN4I_TCON_GINT0_VBLANK_INT(1) |
0759             SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT)))
0760         return IRQ_NONE;
0761 
0762     drm_crtc_handle_vblank(&scrtc->crtc);
0763     sun4i_tcon_finish_page_flip(drm, scrtc);
0764 
0765     /* Acknowledge the interrupt */
0766     regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG,
0767                SUN4I_TCON_GINT0_VBLANK_INT(0) |
0768                SUN4I_TCON_GINT0_VBLANK_INT(1) |
0769                SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT,
0770                0);
0771 
0772     if (engine->ops->vblank_quirk)
0773         engine->ops->vblank_quirk(engine);
0774 
0775     return IRQ_HANDLED;
0776 }
0777 
0778 static int sun4i_tcon_init_clocks(struct device *dev,
0779                   struct sun4i_tcon *tcon)
0780 {
0781     tcon->clk = devm_clk_get(dev, "ahb");
0782     if (IS_ERR(tcon->clk)) {
0783         dev_err(dev, "Couldn't get the TCON bus clock\n");
0784         return PTR_ERR(tcon->clk);
0785     }
0786     clk_prepare_enable(tcon->clk);
0787 
0788     if (tcon->quirks->has_channel_0) {
0789         tcon->sclk0 = devm_clk_get(dev, "tcon-ch0");
0790         if (IS_ERR(tcon->sclk0)) {
0791             dev_err(dev, "Couldn't get the TCON channel 0 clock\n");
0792             return PTR_ERR(tcon->sclk0);
0793         }
0794     }
0795     clk_prepare_enable(tcon->sclk0);
0796 
0797     if (tcon->quirks->has_channel_1) {
0798         tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
0799         if (IS_ERR(tcon->sclk1)) {
0800             dev_err(dev, "Couldn't get the TCON channel 1 clock\n");
0801             return PTR_ERR(tcon->sclk1);
0802         }
0803     }
0804 
0805     return 0;
0806 }
0807 
0808 static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
0809 {
0810     clk_disable_unprepare(tcon->sclk0);
0811     clk_disable_unprepare(tcon->clk);
0812 }
0813 
0814 static int sun4i_tcon_init_irq(struct device *dev,
0815                    struct sun4i_tcon *tcon)
0816 {
0817     struct platform_device *pdev = to_platform_device(dev);
0818     int irq, ret;
0819 
0820     irq = platform_get_irq(pdev, 0);
0821     if (irq < 0)
0822         return irq;
0823 
0824     ret = devm_request_irq(dev, irq, sun4i_tcon_handler, 0,
0825                    dev_name(dev), tcon);
0826     if (ret) {
0827         dev_err(dev, "Couldn't request the IRQ\n");
0828         return ret;
0829     }
0830 
0831     return 0;
0832 }
0833 
0834 static const struct regmap_config sun4i_tcon_regmap_config = {
0835     .reg_bits   = 32,
0836     .val_bits   = 32,
0837     .reg_stride = 4,
0838     .max_register   = 0x800,
0839 };
0840 
0841 static int sun4i_tcon_init_regmap(struct device *dev,
0842                   struct sun4i_tcon *tcon)
0843 {
0844     struct platform_device *pdev = to_platform_device(dev);
0845     void __iomem *regs;
0846 
0847     regs = devm_platform_ioremap_resource(pdev, 0);
0848     if (IS_ERR(regs))
0849         return PTR_ERR(regs);
0850 
0851     tcon->regs = devm_regmap_init_mmio(dev, regs,
0852                        &sun4i_tcon_regmap_config);
0853     if (IS_ERR(tcon->regs)) {
0854         dev_err(dev, "Couldn't create the TCON regmap\n");
0855         return PTR_ERR(tcon->regs);
0856     }
0857 
0858     /* Make sure the TCON is disabled and all IRQs are off */
0859     regmap_write(tcon->regs, SUN4I_TCON_GCTL_REG, 0);
0860     regmap_write(tcon->regs, SUN4I_TCON_GINT0_REG, 0);
0861     regmap_write(tcon->regs, SUN4I_TCON_GINT1_REG, 0);
0862 
0863     /* Disable IO lines and set them to tristate */
0864     regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, ~0);
0865     regmap_write(tcon->regs, SUN4I_TCON1_IO_TRI_REG, ~0);
0866 
0867     return 0;
0868 }
0869 
0870 /*
0871  * On SoCs with the old display pipeline design (Display Engine 1.0),
0872  * the TCON is always tied to just one backend. Hence we can traverse
0873  * the of_graph upwards to find the backend our tcon is connected to,
0874  * and take its ID as our own.
0875  *
0876  * We can either identify backends from their compatible strings, which
0877  * means maintaining a large list of them. Or, since the backend is
0878  * registered and binded before the TCON, we can just go through the
0879  * list of registered backends and compare the device node.
0880  *
0881  * As the structures now store engines instead of backends, here this
0882  * function in fact searches the corresponding engine, and the ID is
0883  * requested via the get_id function of the engine.
0884  */
0885 static struct sunxi_engine *
0886 sun4i_tcon_find_engine_traverse(struct sun4i_drv *drv,
0887                 struct device_node *node,
0888                 u32 port_id)
0889 {
0890     struct device_node *port, *ep, *remote;
0891     struct sunxi_engine *engine = ERR_PTR(-EINVAL);
0892     u32 reg = 0;
0893 
0894     port = of_graph_get_port_by_id(node, port_id);
0895     if (!port)
0896         return ERR_PTR(-EINVAL);
0897 
0898     /*
0899      * This only works if there is only one path from the TCON
0900      * to any display engine. Otherwise the probe order of the
0901      * TCONs and display engines is not guaranteed. They may
0902      * either bind to the wrong one, or worse, bind to the same
0903      * one if additional checks are not done.
0904      *
0905      * Bail out if there are multiple input connections.
0906      */
0907     if (of_get_available_child_count(port) != 1)
0908         goto out_put_port;
0909 
0910     /* Get the first connection without specifying an ID */
0911     ep = of_get_next_available_child(port, NULL);
0912     if (!ep)
0913         goto out_put_port;
0914 
0915     remote = of_graph_get_remote_port_parent(ep);
0916     if (!remote)
0917         goto out_put_ep;
0918 
0919     /* does this node match any registered engines? */
0920     list_for_each_entry(engine, &drv->engine_list, list)
0921         if (remote == engine->node)
0922             goto out_put_remote;
0923 
0924     /*
0925      * According to device tree binding input ports have even id
0926      * number and output ports have odd id. Since component with
0927      * more than one input and one output (TCON TOP) exits, correct
0928      * remote input id has to be calculated by subtracting 1 from
0929      * remote output id. If this for some reason can't be done, 0
0930      * is used as input port id.
0931      */
0932     of_node_put(port);
0933     port = of_graph_get_remote_port(ep);
0934     if (!of_property_read_u32(port, "reg", &reg) && reg > 0)
0935         reg -= 1;
0936 
0937     /* keep looking through upstream ports */
0938     engine = sun4i_tcon_find_engine_traverse(drv, remote, reg);
0939 
0940 out_put_remote:
0941     of_node_put(remote);
0942 out_put_ep:
0943     of_node_put(ep);
0944 out_put_port:
0945     of_node_put(port);
0946 
0947     return engine;
0948 }
0949 
0950 /*
0951  * The device tree binding says that the remote endpoint ID of any
0952  * connection between components, up to and including the TCON, of
0953  * the display pipeline should be equal to the actual ID of the local
0954  * component. Thus we can look at any one of the input connections of
0955  * the TCONs, and use that connection's remote endpoint ID as our own.
0956  *
0957  * Since the user of this function already finds the input port,
0958  * the port is passed in directly without further checks.
0959  */
0960 static int sun4i_tcon_of_get_id_from_port(struct device_node *port)
0961 {
0962     struct device_node *ep;
0963     int ret = -EINVAL;
0964 
0965     /* try finding an upstream endpoint */
0966     for_each_available_child_of_node(port, ep) {
0967         struct device_node *remote;
0968         u32 reg;
0969 
0970         remote = of_graph_get_remote_endpoint(ep);
0971         if (!remote)
0972             continue;
0973 
0974         ret = of_property_read_u32(remote, "reg", &reg);
0975         if (ret)
0976             continue;
0977 
0978         ret = reg;
0979     }
0980 
0981     return ret;
0982 }
0983 
0984 /*
0985  * Once we know the TCON's id, we can look through the list of
0986  * engines to find a matching one. We assume all engines have
0987  * been probed and added to the list.
0988  */
0989 static struct sunxi_engine *sun4i_tcon_get_engine_by_id(struct sun4i_drv *drv,
0990                             int id)
0991 {
0992     struct sunxi_engine *engine;
0993 
0994     list_for_each_entry(engine, &drv->engine_list, list)
0995         if (engine->id == id)
0996             return engine;
0997 
0998     return ERR_PTR(-EINVAL);
0999 }
1000 
1001 static bool sun4i_tcon_connected_to_tcon_top(struct device_node *node)
1002 {
1003     struct device_node *remote;
1004     bool ret = false;
1005 
1006     remote = of_graph_get_remote_node(node, 0, -1);
1007     if (remote) {
1008         ret = !!(IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
1009              of_match_node(sun8i_tcon_top_of_table, remote));
1010         of_node_put(remote);
1011     }
1012 
1013     return ret;
1014 }
1015 
1016 static int sun4i_tcon_get_index(struct sun4i_drv *drv)
1017 {
1018     struct list_head *pos;
1019     int size = 0;
1020 
1021     /*
1022      * Because TCON is added to the list at the end of the probe
1023      * (after this function is called), index of the current TCON
1024      * will be same as current TCON list size.
1025      */
1026     list_for_each(pos, &drv->tcon_list)
1027         ++size;
1028 
1029     return size;
1030 }
1031 
1032 /*
1033  * On SoCs with the old display pipeline design (Display Engine 1.0),
1034  * we assumed the TCON was always tied to just one backend. However
1035  * this proved not to be the case. On the A31, the TCON can select
1036  * either backend as its source. On the A20 (and likely on the A10),
1037  * the backend can choose which TCON to output to.
1038  *
1039  * The device tree binding says that the remote endpoint ID of any
1040  * connection between components, up to and including the TCON, of
1041  * the display pipeline should be equal to the actual ID of the local
1042  * component. Thus we should be able to look at any one of the input
1043  * connections of the TCONs, and use that connection's remote endpoint
1044  * ID as our own.
1045  *
1046  * However  the connections between the backend and TCON were assumed
1047  * to be always singular, and their endpoit IDs were all incorrectly
1048  * set to 0. This means for these old device trees, we cannot just look
1049  * up the remote endpoint ID of a TCON input endpoint. TCON1 would be
1050  * incorrectly identified as TCON0.
1051  *
1052  * This function first checks if the TCON node has 2 input endpoints.
1053  * If so, then the device tree is a corrected version, and it will use
1054  * sun4i_tcon_of_get_id() and sun4i_tcon_get_engine_by_id() from above
1055  * to fetch the ID and engine directly. If not, then it is likely an
1056  * old device trees, where the endpoint IDs were incorrect, but did not
1057  * have endpoint connections between the backend and TCON across
1058  * different display pipelines. It will fall back to the old method of
1059  * traversing the  of_graph to try and find a matching engine by device
1060  * node.
1061  *
1062  * In the case of single display pipeline device trees, either method
1063  * works.
1064  */
1065 static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
1066                            struct device_node *node)
1067 {
1068     struct device_node *port;
1069     struct sunxi_engine *engine;
1070 
1071     port = of_graph_get_port_by_id(node, 0);
1072     if (!port)
1073         return ERR_PTR(-EINVAL);
1074 
1075     /*
1076      * Is this a corrected device tree with cross pipeline
1077      * connections between the backend and TCON?
1078      */
1079     if (of_get_child_count(port) > 1) {
1080         int id;
1081 
1082         /*
1083          * When pipeline has the same number of TCONs and engines which
1084          * are represented by frontends/backends (DE1) or mixers (DE2),
1085          * we match them by their respective IDs. However, if pipeline
1086          * contains TCON TOP, chances are that there are either more
1087          * TCONs than engines (R40) or TCONs with non-consecutive ids.
1088          * (H6). In that case it's easier just use TCON index in list
1089          * as an id. That means that on R40, any 2 TCONs can be enabled
1090          * in DT out of 4 (there are 2 mixers). Due to the design of
1091          * TCON TOP, remaining 2 TCONs can't be connected to anything
1092          * anyway.
1093          */
1094         if (sun4i_tcon_connected_to_tcon_top(node))
1095             id = sun4i_tcon_get_index(drv);
1096         else
1097             id = sun4i_tcon_of_get_id_from_port(port);
1098 
1099         /* Get our engine by matching our ID */
1100         engine = sun4i_tcon_get_engine_by_id(drv, id);
1101 
1102         of_node_put(port);
1103         return engine;
1104     }
1105 
1106     /* Fallback to old method by traversing input endpoints */
1107     of_node_put(port);
1108     return sun4i_tcon_find_engine_traverse(drv, node, 0);
1109 }
1110 
1111 static int sun4i_tcon_bind(struct device *dev, struct device *master,
1112                void *data)
1113 {
1114     struct drm_device *drm = data;
1115     struct sun4i_drv *drv = drm->dev_private;
1116     struct sunxi_engine *engine;
1117     struct device_node *remote;
1118     struct sun4i_tcon *tcon;
1119     struct reset_control *edp_rstc;
1120     bool has_lvds_rst, has_lvds_alt, can_lvds;
1121     int ret;
1122 
1123     engine = sun4i_tcon_find_engine(drv, dev->of_node);
1124     if (IS_ERR(engine)) {
1125         dev_err(dev, "Couldn't find matching engine\n");
1126         return -EPROBE_DEFER;
1127     }
1128 
1129     tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
1130     if (!tcon)
1131         return -ENOMEM;
1132     dev_set_drvdata(dev, tcon);
1133     tcon->drm = drm;
1134     tcon->dev = dev;
1135     tcon->id = engine->id;
1136     tcon->quirks = of_device_get_match_data(dev);
1137 
1138     tcon->lcd_rst = devm_reset_control_get(dev, "lcd");
1139     if (IS_ERR(tcon->lcd_rst)) {
1140         dev_err(dev, "Couldn't get our reset line\n");
1141         return PTR_ERR(tcon->lcd_rst);
1142     }
1143 
1144     if (tcon->quirks->needs_edp_reset) {
1145         edp_rstc = devm_reset_control_get_shared(dev, "edp");
1146         if (IS_ERR(edp_rstc)) {
1147             dev_err(dev, "Couldn't get edp reset line\n");
1148             return PTR_ERR(edp_rstc);
1149         }
1150 
1151         ret = reset_control_deassert(edp_rstc);
1152         if (ret) {
1153             dev_err(dev, "Couldn't deassert edp reset line\n");
1154             return ret;
1155         }
1156     }
1157 
1158     /* Make sure our TCON is reset */
1159     ret = reset_control_reset(tcon->lcd_rst);
1160     if (ret) {
1161         dev_err(dev, "Couldn't deassert our reset line\n");
1162         return ret;
1163     }
1164 
1165     if (tcon->quirks->supports_lvds) {
1166         /*
1167          * This can only be made optional since we've had DT
1168          * nodes without the LVDS reset properties.
1169          *
1170          * If the property is missing, just disable LVDS, and
1171          * print a warning.
1172          */
1173         tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
1174         if (IS_ERR(tcon->lvds_rst)) {
1175             dev_err(dev, "Couldn't get our reset line\n");
1176             return PTR_ERR(tcon->lvds_rst);
1177         } else if (tcon->lvds_rst) {
1178             has_lvds_rst = true;
1179             reset_control_reset(tcon->lvds_rst);
1180         } else {
1181             has_lvds_rst = false;
1182         }
1183 
1184         /*
1185          * This can only be made optional since we've had DT
1186          * nodes without the LVDS reset properties.
1187          *
1188          * If the property is missing, just disable LVDS, and
1189          * print a warning.
1190          */
1191         if (tcon->quirks->has_lvds_alt) {
1192             tcon->lvds_pll = devm_clk_get(dev, "lvds-alt");
1193             if (IS_ERR(tcon->lvds_pll)) {
1194                 if (PTR_ERR(tcon->lvds_pll) == -ENOENT) {
1195                     has_lvds_alt = false;
1196                 } else {
1197                     dev_err(dev, "Couldn't get the LVDS PLL\n");
1198                     return PTR_ERR(tcon->lvds_pll);
1199                 }
1200             } else {
1201                 has_lvds_alt = true;
1202             }
1203         }
1204 
1205         if (!has_lvds_rst ||
1206             (tcon->quirks->has_lvds_alt && !has_lvds_alt)) {
1207             dev_warn(dev, "Missing LVDS properties, Please upgrade your DT\n");
1208             dev_warn(dev, "LVDS output disabled\n");
1209             can_lvds = false;
1210         } else {
1211             can_lvds = true;
1212         }
1213     } else {
1214         can_lvds = false;
1215     }
1216 
1217     ret = sun4i_tcon_init_clocks(dev, tcon);
1218     if (ret) {
1219         dev_err(dev, "Couldn't init our TCON clocks\n");
1220         goto err_assert_reset;
1221     }
1222 
1223     ret = sun4i_tcon_init_regmap(dev, tcon);
1224     if (ret) {
1225         dev_err(dev, "Couldn't init our TCON regmap\n");
1226         goto err_free_clocks;
1227     }
1228 
1229     if (tcon->quirks->has_channel_0) {
1230         ret = sun4i_dclk_create(dev, tcon);
1231         if (ret) {
1232             dev_err(dev, "Couldn't create our TCON dot clock\n");
1233             goto err_free_clocks;
1234         }
1235     }
1236 
1237     ret = sun4i_tcon_init_irq(dev, tcon);
1238     if (ret) {
1239         dev_err(dev, "Couldn't init our TCON interrupts\n");
1240         goto err_free_dotclock;
1241     }
1242 
1243     tcon->crtc = sun4i_crtc_init(drm, engine, tcon);
1244     if (IS_ERR(tcon->crtc)) {
1245         dev_err(dev, "Couldn't create our CRTC\n");
1246         ret = PTR_ERR(tcon->crtc);
1247         goto err_free_dotclock;
1248     }
1249 
1250     if (tcon->quirks->has_channel_0) {
1251         /*
1252          * If we have an LVDS panel connected to the TCON, we should
1253          * just probe the LVDS connector. Otherwise, just probe RGB as
1254          * we used to.
1255          */
1256         remote = of_graph_get_remote_node(dev->of_node, 1, 0);
1257         if (of_device_is_compatible(remote, "panel-lvds"))
1258             if (can_lvds)
1259                 ret = sun4i_lvds_init(drm, tcon);
1260             else
1261                 ret = -EINVAL;
1262         else
1263             ret = sun4i_rgb_init(drm, tcon);
1264         of_node_put(remote);
1265 
1266         if (ret < 0)
1267             goto err_free_dotclock;
1268     }
1269 
1270     if (tcon->quirks->needs_de_be_mux) {
1271         /*
1272          * We assume there is no dynamic muxing of backends
1273          * and TCONs, so we select the backend with same ID.
1274          *
1275          * While dynamic selection might be interesting, since
1276          * the CRTC is tied to the TCON, while the layers are
1277          * tied to the backends, this means, we will need to
1278          * switch between groups of layers. There might not be
1279          * a way to represent this constraint in DRM.
1280          */
1281         regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
1282                    SUN4I_TCON0_CTL_SRC_SEL_MASK,
1283                    tcon->id);
1284         regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
1285                    SUN4I_TCON1_CTL_SRC_SEL_MASK,
1286                    tcon->id);
1287     }
1288 
1289     list_add_tail(&tcon->list, &drv->tcon_list);
1290 
1291     return 0;
1292 
1293 err_free_dotclock:
1294     if (tcon->quirks->has_channel_0)
1295         sun4i_dclk_free(tcon);
1296 err_free_clocks:
1297     sun4i_tcon_free_clocks(tcon);
1298 err_assert_reset:
1299     reset_control_assert(tcon->lcd_rst);
1300     return ret;
1301 }
1302 
1303 static void sun4i_tcon_unbind(struct device *dev, struct device *master,
1304                   void *data)
1305 {
1306     struct sun4i_tcon *tcon = dev_get_drvdata(dev);
1307 
1308     list_del(&tcon->list);
1309     if (tcon->quirks->has_channel_0)
1310         sun4i_dclk_free(tcon);
1311     sun4i_tcon_free_clocks(tcon);
1312 }
1313 
1314 static const struct component_ops sun4i_tcon_ops = {
1315     .bind   = sun4i_tcon_bind,
1316     .unbind = sun4i_tcon_unbind,
1317 };
1318 
1319 static int sun4i_tcon_probe(struct platform_device *pdev)
1320 {
1321     struct device_node *node = pdev->dev.of_node;
1322     const struct sun4i_tcon_quirks *quirks;
1323     struct drm_bridge *bridge;
1324     struct drm_panel *panel;
1325     int ret;
1326 
1327     quirks = of_device_get_match_data(&pdev->dev);
1328 
1329     /* panels and bridges are present only on TCONs with channel 0 */
1330     if (quirks->has_channel_0) {
1331         ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
1332         if (ret == -EPROBE_DEFER)
1333             return ret;
1334     }
1335 
1336     return component_add(&pdev->dev, &sun4i_tcon_ops);
1337 }
1338 
1339 static int sun4i_tcon_remove(struct platform_device *pdev)
1340 {
1341     component_del(&pdev->dev, &sun4i_tcon_ops);
1342 
1343     return 0;
1344 }
1345 
1346 /* platform specific TCON muxing callbacks */
1347 static int sun4i_a10_tcon_set_mux(struct sun4i_tcon *tcon,
1348                   const struct drm_encoder *encoder)
1349 {
1350     struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
1351     u32 shift;
1352 
1353     if (!tcon0)
1354         return -EINVAL;
1355 
1356     switch (encoder->encoder_type) {
1357     case DRM_MODE_ENCODER_TMDS:
1358         /* HDMI */
1359         shift = 8;
1360         break;
1361     default:
1362         return -EINVAL;
1363     }
1364 
1365     regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG,
1366                0x3 << shift, tcon->id << shift);
1367 
1368     return 0;
1369 }
1370 
1371 static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
1372                   const struct drm_encoder *encoder)
1373 {
1374     u32 val;
1375 
1376     if (encoder->encoder_type == DRM_MODE_ENCODER_TVDAC)
1377         val = 1;
1378     else
1379         val = 0;
1380 
1381     /*
1382      * FIXME: Undocumented bits
1383      */
1384     return regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, val);
1385 }
1386 
1387 static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
1388                   const struct drm_encoder *encoder)
1389 {
1390     struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
1391     u32 shift;
1392 
1393     if (!tcon0)
1394         return -EINVAL;
1395 
1396     switch (encoder->encoder_type) {
1397     case DRM_MODE_ENCODER_TMDS:
1398         /* HDMI */
1399         shift = 8;
1400         break;
1401     default:
1402         /* TODO A31 has MIPI DSI but A31s does not */
1403         return -EINVAL;
1404     }
1405 
1406     regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG,
1407                0x3 << shift, tcon->id << shift);
1408 
1409     return 0;
1410 }
1411 
1412 static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
1413                      const struct drm_encoder *encoder)
1414 {
1415     struct device_node *port, *remote;
1416     struct platform_device *pdev;
1417     int id, ret;
1418 
1419     /* find TCON TOP platform device and TCON id */
1420 
1421     port = of_graph_get_port_by_id(tcon->dev->of_node, 0);
1422     if (!port)
1423         return -EINVAL;
1424 
1425     id = sun4i_tcon_of_get_id_from_port(port);
1426     of_node_put(port);
1427 
1428     remote = of_graph_get_remote_node(tcon->dev->of_node, 0, -1);
1429     if (!remote)
1430         return -EINVAL;
1431 
1432     pdev = of_find_device_by_node(remote);
1433     of_node_put(remote);
1434     if (!pdev)
1435         return -EINVAL;
1436 
1437     if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
1438         encoder->encoder_type == DRM_MODE_ENCODER_TMDS) {
1439         ret = sun8i_tcon_top_set_hdmi_src(&pdev->dev, id);
1440         if (ret) {
1441             put_device(&pdev->dev);
1442             return ret;
1443         }
1444     }
1445 
1446     if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP)) {
1447         ret = sun8i_tcon_top_de_config(&pdev->dev, tcon->id, id);
1448         if (ret) {
1449             put_device(&pdev->dev);
1450             return ret;
1451         }
1452     }
1453 
1454     return 0;
1455 }
1456 
1457 static const struct sun4i_tcon_quirks sun4i_a10_quirks = {
1458     .has_channel_0      = true,
1459     .has_channel_1      = true,
1460     .dclk_min_div       = 4,
1461     .set_mux        = sun4i_a10_tcon_set_mux,
1462 };
1463 
1464 static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
1465     .has_channel_0      = true,
1466     .has_channel_1      = true,
1467     .dclk_min_div       = 4,
1468     .set_mux        = sun5i_a13_tcon_set_mux,
1469 };
1470 
1471 static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
1472     .has_channel_0      = true,
1473     .has_channel_1      = true,
1474     .has_lvds_alt       = true,
1475     .needs_de_be_mux    = true,
1476     .dclk_min_div       = 1,
1477     .set_mux        = sun6i_tcon_set_mux,
1478 };
1479 
1480 static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
1481     .has_channel_0      = true,
1482     .has_channel_1      = true,
1483     .needs_de_be_mux    = true,
1484     .dclk_min_div       = 1,
1485 };
1486 
1487 static const struct sun4i_tcon_quirks sun7i_a20_tcon0_quirks = {
1488     .supports_lvds      = true,
1489     .has_channel_0      = true,
1490     .has_channel_1      = true,
1491     .dclk_min_div       = 4,
1492     /* Same display pipeline structure as A10 */
1493     .set_mux        = sun4i_a10_tcon_set_mux,
1494     .setup_lvds_phy     = sun4i_tcon_setup_lvds_phy,
1495 };
1496 
1497 static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
1498     .has_channel_0      = true,
1499     .has_channel_1      = true,
1500     .dclk_min_div       = 4,
1501     /* Same display pipeline structure as A10 */
1502     .set_mux        = sun4i_a10_tcon_set_mux,
1503 };
1504 
1505 static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
1506     .has_channel_0      = true,
1507     .has_lvds_alt       = true,
1508     .dclk_min_div       = 1,
1509     .setup_lvds_phy     = sun6i_tcon_setup_lvds_phy,
1510     .supports_lvds      = true,
1511 };
1512 
1513 static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
1514     .supports_lvds      = true,
1515     .has_channel_0      = true,
1516     .dclk_min_div       = 1,
1517     .setup_lvds_phy     = sun6i_tcon_setup_lvds_phy,
1518 };
1519 
1520 static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
1521     .has_channel_1      = true,
1522 };
1523 
1524 static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks = {
1525     .has_channel_1      = true,
1526     .polarity_in_ch0    = true,
1527     .set_mux        = sun8i_r40_tcon_tv_set_mux,
1528 };
1529 
1530 static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
1531     .has_channel_0      = true,
1532     .dclk_min_div       = 1,
1533 };
1534 
1535 static const struct sun4i_tcon_quirks sun9i_a80_tcon_lcd_quirks = {
1536     .has_channel_0      = true,
1537     .needs_edp_reset    = true,
1538     .dclk_min_div       = 1,
1539 };
1540 
1541 static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks = {
1542     .has_channel_1  = true,
1543     .needs_edp_reset = true,
1544 };
1545 
1546 static const struct sun4i_tcon_quirks sun20i_d1_lcd_quirks = {
1547     .has_channel_0      = true,
1548     .dclk_min_div       = 1,
1549     .set_mux        = sun8i_r40_tcon_tv_set_mux,
1550 };
1551 
1552 /* sun4i_drv uses this list to check if a device node is a TCON */
1553 const struct of_device_id sun4i_tcon_of_table[] = {
1554     { .compatible = "allwinner,sun4i-a10-tcon", .data = &sun4i_a10_quirks },
1555     { .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
1556     { .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
1557     { .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
1558     { .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks },
1559     { .compatible = "allwinner,sun7i-a20-tcon0", .data = &sun7i_a20_tcon0_quirks },
1560     { .compatible = "allwinner,sun7i-a20-tcon1", .data = &sun7i_a20_quirks },
1561     { .compatible = "allwinner,sun8i-a23-tcon", .data = &sun8i_a33_quirks },
1562     { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
1563     { .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks },
1564     { .compatible = "allwinner,sun8i-a83t-tcon-tv", .data = &sun8i_a83t_tv_quirks },
1565     { .compatible = "allwinner,sun8i-r40-tcon-tv", .data = &sun8i_r40_tv_quirks },
1566     { .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
1567     { .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = &sun9i_a80_tcon_lcd_quirks },
1568     { .compatible = "allwinner,sun9i-a80-tcon-tv", .data = &sun9i_a80_tcon_tv_quirks },
1569     { .compatible = "allwinner,sun20i-d1-tcon-lcd", .data = &sun20i_d1_lcd_quirks },
1570     { .compatible = "allwinner,sun20i-d1-tcon-tv", .data = &sun8i_r40_tv_quirks },
1571     { }
1572 };
1573 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
1574 EXPORT_SYMBOL(sun4i_tcon_of_table);
1575 
1576 static struct platform_driver sun4i_tcon_platform_driver = {
1577     .probe      = sun4i_tcon_probe,
1578     .remove     = sun4i_tcon_remove,
1579     .driver     = {
1580         .name       = "sun4i-tcon",
1581         .of_match_table = sun4i_tcon_of_table,
1582     },
1583 };
1584 module_platform_driver(sun4i_tcon_platform_driver);
1585 
1586 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
1587 MODULE_DESCRIPTION("Allwinner A10 Timing Controller Driver");
1588 MODULE_LICENSE("GPL");