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