0001
0002
0003
0004
0005
0006
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);
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);
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
0245
0246
0247
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
0298 clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
0299
0300
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
0313 if (!connector)
0314 return;
0315
0316
0317
0318
0319
0320
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
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
0341 switch (bus_format) {
0342 case MEDIA_BUS_FMT_RGB565_1X16:
0343
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
0350 val |= SUN4I_TCON0_FRM_CTL_EN;
0351 break;
0352 }
0353
0354
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
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
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
0393
0394
0395
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
0418
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
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
0444 sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
0445
0446
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
0454
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
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
0467
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
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
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
0496 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
0497 SUN4I_TCON_GCTL_IOMAP_MASK,
0498 SUN4I_TCON_GCTL_IOMAP_TCON0);
0499
0500
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
0521 sun4i_tcon0_mode_set_dithering(tcon, connector);
0522
0523
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
0531
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
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
0544
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
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
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
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
0584 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
0585 SUN4I_TCON_GCTL_IOMAP_MASK,
0586 SUN4I_TCON_GCTL_IOMAP_TCON0);
0587
0588
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
0602 clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
0603
0604
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
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
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
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
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
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
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659 vtotal = mode->vtotal;
0660 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
0661 vtotal = vtotal * 2;
0662
0663
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
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
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
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
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
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
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
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
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
0872
0873
0874
0875
0876
0877
0878
0879
0880
0881
0882
0883
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
0900
0901
0902
0903
0904
0905
0906
0907 if (of_get_available_child_count(port) != 1)
0908 goto out_put_port;
0909
0910
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
0920 list_for_each_entry(engine, &drv->engine_list, list)
0921 if (remote == engine->node)
0922 goto out_put_remote;
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932 of_node_put(port);
0933 port = of_graph_get_remote_port(ep);
0934 if (!of_property_read_u32(port, "reg", ®) && reg > 0)
0935 reg -= 1;
0936
0937
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
0952
0953
0954
0955
0956
0957
0958
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
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", ®);
0975 if (ret)
0976 continue;
0977
0978 ret = reg;
0979 }
0980
0981 return ret;
0982 }
0983
0984
0985
0986
0987
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
1023
1024
1025
1026 list_for_each(pos, &drv->tcon_list)
1027 ++size;
1028
1029 return size;
1030 }
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
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
1077
1078
1079 if (of_get_child_count(port) > 1) {
1080 int id;
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
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
1100 engine = sun4i_tcon_get_engine_by_id(drv, id);
1101
1102 of_node_put(port);
1103 return engine;
1104 }
1105
1106
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
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
1168
1169
1170
1171
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
1186
1187
1188
1189
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
1253
1254
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
1273
1274
1275
1276
1277
1278
1279
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
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
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
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
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
1399 shift = 8;
1400 break;
1401 default:
1402
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
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
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
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
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");