1 /* 2 * Copyright (C) 2015 Free Electrons 3 * Copyright (C) 2015 NextThing Co 4 * 5 * Maxime Ripard <maxime.ripard@free-electrons.com> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 */ 12 13 #include <drm/drmP.h> 14 #include <drm/drm_atomic_helper.h> 15 #include <drm/drm_crtc.h> 16 #include <drm/drm_crtc_helper.h> 17 #include <drm/drm_encoder.h> 18 #include <drm/drm_modes.h> 19 #include <drm/drm_of.h> 20 21 #include <uapi/drm/drm_mode.h> 22 23 #include <linux/component.h> 24 #include <linux/ioport.h> 25 #include <linux/of_address.h> 26 #include <linux/of_device.h> 27 #include <linux/of_irq.h> 28 #include <linux/regmap.h> 29 #include <linux/reset.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 "sunxi_engine.h" 39 40 static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder) 41 { 42 struct drm_connector *connector; 43 struct drm_connector_list_iter iter; 44 45 drm_connector_list_iter_begin(encoder->dev, &iter); 46 drm_for_each_connector_iter(connector, &iter) 47 if (connector->encoder == encoder) { 48 drm_connector_list_iter_end(&iter); 49 return connector; 50 } 51 drm_connector_list_iter_end(&iter); 52 53 return NULL; 54 } 55 56 static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder) 57 { 58 struct drm_connector *connector; 59 struct drm_display_info *info; 60 61 connector = sun4i_tcon_get_connector(encoder); 62 if (!connector) 63 return -EINVAL; 64 65 info = &connector->display_info; 66 if (info->num_bus_formats != 1) 67 return -EINVAL; 68 69 switch (info->bus_formats[0]) { 70 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 71 return 18; 72 73 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: 74 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: 75 return 24; 76 } 77 78 return -EINVAL; 79 } 80 81 static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel, 82 bool enabled) 83 { 84 struct clk *clk; 85 86 switch (channel) { 87 case 0: 88 WARN_ON(!tcon->quirks->has_channel_0); 89 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, 90 SUN4I_TCON0_CTL_TCON_ENABLE, 91 enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0); 92 clk = tcon->dclk; 93 break; 94 case 1: 95 WARN_ON(!tcon->quirks->has_channel_1); 96 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, 97 SUN4I_TCON1_CTL_TCON_ENABLE, 98 enabled ? SUN4I_TCON1_CTL_TCON_ENABLE : 0); 99 clk = tcon->sclk1; 100 break; 101 default: 102 DRM_WARN("Unknown channel... doing nothing\n"); 103 return; 104 } 105 106 if (enabled) { 107 clk_prepare_enable(clk); 108 clk_rate_exclusive_get(clk); 109 } else { 110 clk_rate_exclusive_put(clk); 111 clk_disable_unprepare(clk); 112 } 113 } 114 115 static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, 116 const struct drm_encoder *encoder, 117 bool enabled) 118 { 119 if (enabled) { 120 u8 val; 121 122 regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, 123 SUN4I_TCON0_LVDS_IF_EN, 124 SUN4I_TCON0_LVDS_IF_EN); 125 126 /* 127 * As their name suggest, these values only apply to the A31 128 * and later SoCs. We'll have to rework this when merging 129 * support for the older SoCs. 130 */ 131 regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, 132 SUN6I_TCON0_LVDS_ANA0_C(2) | 133 SUN6I_TCON0_LVDS_ANA0_V(3) | 134 SUN6I_TCON0_LVDS_ANA0_PD(2) | 135 SUN6I_TCON0_LVDS_ANA0_EN_LDO); 136 udelay(2); 137 138 regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, 139 SUN6I_TCON0_LVDS_ANA0_EN_MB, 140 SUN6I_TCON0_LVDS_ANA0_EN_MB); 141 udelay(2); 142 143 regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, 144 SUN6I_TCON0_LVDS_ANA0_EN_DRVC, 145 SUN6I_TCON0_LVDS_ANA0_EN_DRVC); 146 147 if (sun4i_tcon_get_pixel_depth(encoder) == 18) 148 val = 7; 149 else 150 val = 0xf; 151 152 regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG, 153 SUN6I_TCON0_LVDS_ANA0_EN_DRVD(0xf), 154 SUN6I_TCON0_LVDS_ANA0_EN_DRVD(val)); 155 } else { 156 regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, 157 SUN4I_TCON0_LVDS_IF_EN, 0); 158 } 159 } 160 161 void sun4i_tcon_set_status(struct sun4i_tcon *tcon, 162 const struct drm_encoder *encoder, 163 bool enabled) 164 { 165 bool is_lvds = false; 166 int channel; 167 168 switch (encoder->encoder_type) { 169 case DRM_MODE_ENCODER_LVDS: 170 is_lvds = true; 171 /* Fallthrough */ 172 case DRM_MODE_ENCODER_DSI: 173 case DRM_MODE_ENCODER_NONE: 174 channel = 0; 175 break; 176 case DRM_MODE_ENCODER_TMDS: 177 case DRM_MODE_ENCODER_TVDAC: 178 channel = 1; 179 break; 180 default: 181 DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n"); 182 return; 183 } 184 185 if (is_lvds && !enabled) 186 sun4i_tcon_lvds_set_status(tcon, encoder, false); 187 188 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, 189 SUN4I_TCON_GCTL_TCON_ENABLE, 190 enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0); 191 192 if (is_lvds && enabled) 193 sun4i_tcon_lvds_set_status(tcon, encoder, true); 194 195 sun4i_tcon_channel_set_status(tcon, channel, enabled); 196 } 197 198 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable) 199 { 200 u32 mask, val = 0; 201 202 DRM_DEBUG_DRIVER("%sabling VBLANK interrupt\n", enable ? "En" : "Dis"); 203 204 mask = SUN4I_TCON_GINT0_VBLANK_ENABLE(0) | 205 SUN4I_TCON_GINT0_VBLANK_ENABLE(1) | 206 SUN4I_TCON_GINT0_TCON0_TRI_FINISH_ENABLE; 207 208 if (enable) 209 val = mask; 210 211 regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, mask, val); 212 } 213 EXPORT_SYMBOL(sun4i_tcon_enable_vblank); 214 215 /* 216 * This function is a helper for TCON output muxing. The TCON output 217 * muxing control register in earlier SoCs (without the TCON TOP block) 218 * are located in TCON0. This helper returns a pointer to TCON0's 219 * sun4i_tcon structure, or NULL if not found. 220 */ 221 static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm) 222 { 223 struct sun4i_drv *drv = drm->dev_private; 224 struct sun4i_tcon *tcon; 225 226 list_for_each_entry(tcon, &drv->tcon_list, list) 227 if (tcon->id == 0) 228 return tcon; 229 230 dev_warn(drm->dev, 231 "TCON0 not found, display output muxing may not work\n"); 232 233 return NULL; 234 } 235 236 void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel, 237 const struct drm_encoder *encoder) 238 { 239 int ret = -ENOTSUPP; 240 241 if (tcon->quirks->set_mux) 242 ret = tcon->quirks->set_mux(tcon, encoder); 243 244 DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n", 245 encoder->name, encoder->crtc->name, ret); 246 } 247 248 static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode, 249 int channel) 250 { 251 int delay = mode->vtotal - mode->vdisplay; 252 253 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 254 delay /= 2; 255 256 if (channel == 1) 257 delay -= 2; 258 259 delay = min(delay, 30); 260 261 DRM_DEBUG_DRIVER("TCON %d clock delay %u\n", channel, delay); 262 263 return delay; 264 } 265 266 static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon, 267 const struct drm_display_mode *mode) 268 { 269 /* Configure the dot clock */ 270 clk_set_rate(tcon->dclk, mode->crtc_clock * 1000); 271 272 /* Set the resolution */ 273 regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG, 274 SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) | 275 SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay)); 276 } 277 278 static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon, 279 struct mipi_dsi_device *device, 280 const struct drm_display_mode *mode) 281 { 282 u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format); 283 u8 lanes = device->lanes; 284 u32 block_space, start_delay; 285 u32 tcon_div; 286 287 tcon->dclk_min_div = 4; 288 tcon->dclk_max_div = 127; 289 290 sun4i_tcon0_mode_set_common(tcon, mode); 291 292 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, 293 SUN4I_TCON0_CTL_IF_MASK, 294 SUN4I_TCON0_CTL_IF_8080); 295 296 regmap_write(tcon->regs, SUN4I_TCON_ECC_FIFO_REG, 297 SUN4I_TCON_ECC_FIFO_EN); 298 299 regmap_write(tcon->regs, SUN4I_TCON0_CPU_IF_REG, 300 SUN4I_TCON0_CPU_IF_MODE_DSI | 301 SUN4I_TCON0_CPU_IF_TRI_FIFO_FLUSH | 302 SUN4I_TCON0_CPU_IF_TRI_FIFO_EN | 303 SUN4I_TCON0_CPU_IF_TRI_EN); 304 305 /* 306 * This looks suspicious, but it works... 307 * 308 * The datasheet says that this should be set higher than 20 * 309 * pixel cycle, but it's not clear what a pixel cycle is. 310 */ 311 regmap_read(tcon->regs, SUN4I_TCON0_DCLK_REG, &tcon_div); 312 tcon_div &= GENMASK(6, 0); 313 block_space = mode->htotal * bpp / (tcon_div * lanes); 314 block_space -= mode->hdisplay + 40; 315 316 regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG, 317 SUN4I_TCON0_CPU_TRI0_BLOCK_SPACE(block_space) | 318 SUN4I_TCON0_CPU_TRI0_BLOCK_SIZE(mode->hdisplay)); 319 320 regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI1_REG, 321 SUN4I_TCON0_CPU_TRI1_BLOCK_NUM(mode->vdisplay)); 322 323 start_delay = (mode->crtc_vtotal - mode->crtc_vdisplay - 10 - 1); 324 start_delay = start_delay * mode->crtc_htotal * 149; 325 start_delay = start_delay / (mode->crtc_clock / 1000) / 8; 326 regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI2_REG, 327 SUN4I_TCON0_CPU_TRI2_TRANS_START_SET(10) | 328 SUN4I_TCON0_CPU_TRI2_START_DELAY(start_delay)); 329 330 /* 331 * The Allwinner BSP has a comment that the period should be 332 * the display clock * 15, but uses an hardcoded 3000... 333 */ 334 regmap_write(tcon->regs, SUN4I_TCON_SAFE_PERIOD_REG, 335 SUN4I_TCON_SAFE_PERIOD_NUM(3000) | 336 SUN4I_TCON_SAFE_PERIOD_MODE(3)); 337 338 /* Enable the output on the pins */ 339 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 340 0xe0000000); 341 } 342 343 static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon, 344 const struct drm_encoder *encoder, 345 const struct drm_display_mode *mode) 346 { 347 unsigned int bp; 348 u8 clk_delay; 349 u32 reg, val = 0; 350 351 WARN_ON(!tcon->quirks->has_channel_0); 352 353 tcon->dclk_min_div = 7; 354 tcon->dclk_max_div = 7; 355 sun4i_tcon0_mode_set_common(tcon, mode); 356 357 /* Adjust clock delay */ 358 clk_delay = sun4i_tcon_get_clk_delay(mode, 0); 359 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, 360 SUN4I_TCON0_CTL_CLK_DELAY_MASK, 361 SUN4I_TCON0_CTL_CLK_DELAY(clk_delay)); 362 363 /* 364 * This is called a backporch in the register documentation, 365 * but it really is the back porch + hsync 366 */ 367 bp = mode->crtc_htotal - mode->crtc_hsync_start; 368 DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", 369 mode->crtc_htotal, bp); 370 371 /* Set horizontal display timings */ 372 regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG, 373 SUN4I_TCON0_BASIC1_H_TOTAL(mode->htotal) | 374 SUN4I_TCON0_BASIC1_H_BACKPORCH(bp)); 375 376 /* 377 * This is called a backporch in the register documentation, 378 * but it really is the back porch + hsync 379 */ 380 bp = mode->crtc_vtotal - mode->crtc_vsync_start; 381 DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n", 382 mode->crtc_vtotal, bp); 383 384 /* Set vertical display timings */ 385 regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG, 386 SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) | 387 SUN4I_TCON0_BASIC2_V_BACKPORCH(bp)); 388 389 reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 | 390 SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL | 391 SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL; 392 if (sun4i_tcon_get_pixel_depth(encoder) == 24) 393 reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS; 394 else 395 reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS; 396 397 regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg); 398 399 /* Setup the polarity of the various signals */ 400 if (!(mode->flags & DRM_MODE_FLAG_PHSYNC)) 401 val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE; 402 403 if (!(mode->flags & DRM_MODE_FLAG_PVSYNC)) 404 val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE; 405 406 regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val); 407 408 /* Map output pins to channel 0 */ 409 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, 410 SUN4I_TCON_GCTL_IOMAP_MASK, 411 SUN4I_TCON_GCTL_IOMAP_TCON0); 412 413 /* Enable the output on the pins */ 414 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000); 415 } 416 417 static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, 418 const struct drm_display_mode *mode) 419 { 420 unsigned int bp, hsync, vsync; 421 u8 clk_delay; 422 u32 val = 0; 423 424 WARN_ON(!tcon->quirks->has_channel_0); 425 426 tcon->dclk_min_div = 6; 427 tcon->dclk_max_div = 127; 428 sun4i_tcon0_mode_set_common(tcon, mode); 429 430 /* Adjust clock delay */ 431 clk_delay = sun4i_tcon_get_clk_delay(mode, 0); 432 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, 433 SUN4I_TCON0_CTL_CLK_DELAY_MASK, 434 SUN4I_TCON0_CTL_CLK_DELAY(clk_delay)); 435 436 /* 437 * This is called a backporch in the register documentation, 438 * but it really is the back porch + hsync 439 */ 440 bp = mode->crtc_htotal - mode->crtc_hsync_start; 441 DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", 442 mode->crtc_htotal, bp); 443 444 /* Set horizontal display timings */ 445 regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG, 446 SUN4I_TCON0_BASIC1_H_TOTAL(mode->crtc_htotal) | 447 SUN4I_TCON0_BASIC1_H_BACKPORCH(bp)); 448 449 /* 450 * This is called a backporch in the register documentation, 451 * but it really is the back porch + hsync 452 */ 453 bp = mode->crtc_vtotal - mode->crtc_vsync_start; 454 DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n", 455 mode->crtc_vtotal, bp); 456 457 /* Set vertical display timings */ 458 regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG, 459 SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) | 460 SUN4I_TCON0_BASIC2_V_BACKPORCH(bp)); 461 462 /* Set Hsync and Vsync length */ 463 hsync = mode->crtc_hsync_end - mode->crtc_hsync_start; 464 vsync = mode->crtc_vsync_end - mode->crtc_vsync_start; 465 DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync); 466 regmap_write(tcon->regs, SUN4I_TCON0_BASIC3_REG, 467 SUN4I_TCON0_BASIC3_V_SYNC(vsync) | 468 SUN4I_TCON0_BASIC3_H_SYNC(hsync)); 469 470 /* Setup the polarity of the various signals */ 471 if (mode->flags & DRM_MODE_FLAG_PHSYNC) 472 val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE; 473 474 if (mode->flags & DRM_MODE_FLAG_PVSYNC) 475 val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE; 476 477 regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG, 478 SUN4I_TCON0_IO_POL_HSYNC_POSITIVE | SUN4I_TCON0_IO_POL_VSYNC_POSITIVE, 479 val); 480 481 /* Map output pins to channel 0 */ 482 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, 483 SUN4I_TCON_GCTL_IOMAP_MASK, 484 SUN4I_TCON_GCTL_IOMAP_TCON0); 485 486 /* Enable the output on the pins */ 487 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0); 488 } 489 490 static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, 491 const struct drm_display_mode *mode) 492 { 493 unsigned int bp, hsync, vsync, vtotal; 494 u8 clk_delay; 495 u32 val; 496 497 WARN_ON(!tcon->quirks->has_channel_1); 498 499 /* Configure the dot clock */ 500 clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000); 501 502 /* Adjust clock delay */ 503 clk_delay = sun4i_tcon_get_clk_delay(mode, 1); 504 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, 505 SUN4I_TCON1_CTL_CLK_DELAY_MASK, 506 SUN4I_TCON1_CTL_CLK_DELAY(clk_delay)); 507 508 /* Set interlaced mode */ 509 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 510 val = SUN4I_TCON1_CTL_INTERLACE_ENABLE; 511 else 512 val = 0; 513 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, 514 SUN4I_TCON1_CTL_INTERLACE_ENABLE, 515 val); 516 517 /* Set the input resolution */ 518 regmap_write(tcon->regs, SUN4I_TCON1_BASIC0_REG, 519 SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay) | 520 SUN4I_TCON1_BASIC0_Y(mode->crtc_vdisplay)); 521 522 /* Set the upscaling resolution */ 523 regmap_write(tcon->regs, SUN4I_TCON1_BASIC1_REG, 524 SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay) | 525 SUN4I_TCON1_BASIC1_Y(mode->crtc_vdisplay)); 526 527 /* Set the output resolution */ 528 regmap_write(tcon->regs, SUN4I_TCON1_BASIC2_REG, 529 SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay) | 530 SUN4I_TCON1_BASIC2_Y(mode->crtc_vdisplay)); 531 532 /* Set horizontal display timings */ 533 bp = mode->crtc_htotal - mode->crtc_hsync_start; 534 DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", 535 mode->htotal, bp); 536 regmap_write(tcon->regs, SUN4I_TCON1_BASIC3_REG, 537 SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal) | 538 SUN4I_TCON1_BASIC3_H_BACKPORCH(bp)); 539 540 bp = mode->crtc_vtotal - mode->crtc_vsync_start; 541 DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n", 542 mode->crtc_vtotal, bp); 543 544 /* 545 * The vertical resolution needs to be doubled in all 546 * cases. We could use crtc_vtotal and always multiply by two, 547 * but that leads to a rounding error in interlace when vtotal 548 * is odd. 549 * 550 * This happens with TV's PAL for example, where vtotal will 551 * be 625, crtc_vtotal 312, and thus crtc_vtotal * 2 will be 552 * 624, which apparently confuses the hardware. 553 * 554 * To work around this, we will always use vtotal, and 555 * multiply by two only if we're not in interlace. 556 */ 557 vtotal = mode->vtotal; 558 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) 559 vtotal = vtotal * 2; 560 561 /* Set vertical display timings */ 562 regmap_write(tcon->regs, SUN4I_TCON1_BASIC4_REG, 563 SUN4I_TCON1_BASIC4_V_TOTAL(vtotal) | 564 SUN4I_TCON1_BASIC4_V_BACKPORCH(bp)); 565 566 /* Set Hsync and Vsync length */ 567 hsync = mode->crtc_hsync_end - mode->crtc_hsync_start; 568 vsync = mode->crtc_vsync_end - mode->crtc_vsync_start; 569 DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync); 570 regmap_write(tcon->regs, SUN4I_TCON1_BASIC5_REG, 571 SUN4I_TCON1_BASIC5_V_SYNC(vsync) | 572 SUN4I_TCON1_BASIC5_H_SYNC(hsync)); 573 574 /* Map output pins to channel 1 */ 575 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, 576 SUN4I_TCON_GCTL_IOMAP_MASK, 577 SUN4I_TCON_GCTL_IOMAP_TCON1); 578 } 579 580 void sun4i_tcon_mode_set(struct sun4i_tcon *tcon, 581 const struct drm_encoder *encoder, 582 const struct drm_display_mode *mode) 583 { 584 struct sun6i_dsi *dsi; 585 586 switch (encoder->encoder_type) { 587 case DRM_MODE_ENCODER_DSI: 588 /* 589 * This is not really elegant, but it's the "cleaner" 590 * way I could think of... 591 */ 592 dsi = encoder_to_sun6i_dsi(encoder); 593 sun4i_tcon0_mode_set_cpu(tcon, dsi->device, mode); 594 break; 595 case DRM_MODE_ENCODER_LVDS: 596 sun4i_tcon0_mode_set_lvds(tcon, encoder, mode); 597 break; 598 case DRM_MODE_ENCODER_NONE: 599 sun4i_tcon0_mode_set_rgb(tcon, mode); 600 sun4i_tcon_set_mux(tcon, 0, encoder); 601 break; 602 case DRM_MODE_ENCODER_TVDAC: 603 case DRM_MODE_ENCODER_TMDS: 604 sun4i_tcon1_mode_set(tcon, mode); 605 sun4i_tcon_set_mux(tcon, 1, encoder); 606 break; 607 default: 608 DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n"); 609 } 610 } 611 EXPORT_SYMBOL(sun4i_tcon_mode_set); 612 613 static void sun4i_tcon_finish_page_flip(struct drm_device *dev, 614 struct sun4i_crtc *scrtc) 615 { 616 unsigned long flags; 617 618 spin_lock_irqsave(&dev->event_lock, flags); 619 if (scrtc->event) { 620 drm_crtc_send_vblank_event(&scrtc->crtc, scrtc->event); 621 drm_crtc_vblank_put(&scrtc->crtc); 622 scrtc->event = NULL; 623 } 624 spin_unlock_irqrestore(&dev->event_lock, flags); 625 } 626 627 static irqreturn_t sun4i_tcon_handler(int irq, void *private) 628 { 629 struct sun4i_tcon *tcon = private; 630 struct drm_device *drm = tcon->drm; 631 struct sun4i_crtc *scrtc = tcon->crtc; 632 struct sunxi_engine *engine = scrtc->engine; 633 unsigned int status; 634 635 regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status); 636 637 if (!(status & (SUN4I_TCON_GINT0_VBLANK_INT(0) | 638 SUN4I_TCON_GINT0_VBLANK_INT(1) | 639 SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT))) 640 return IRQ_NONE; 641 642 drm_crtc_handle_vblank(&scrtc->crtc); 643 sun4i_tcon_finish_page_flip(drm, scrtc); 644 645 /* Acknowledge the interrupt */ 646 regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, 647 SUN4I_TCON_GINT0_VBLANK_INT(0) | 648 SUN4I_TCON_GINT0_VBLANK_INT(1) | 649 SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT, 650 0); 651 652 if (engine->ops->vblank_quirk) 653 engine->ops->vblank_quirk(engine); 654 655 return IRQ_HANDLED; 656 } 657 658 static int sun4i_tcon_init_clocks(struct device *dev, 659 struct sun4i_tcon *tcon) 660 { 661 tcon->clk = devm_clk_get(dev, "ahb"); 662 if (IS_ERR(tcon->clk)) { 663 dev_err(dev, "Couldn't get the TCON bus clock\n"); 664 return PTR_ERR(tcon->clk); 665 } 666 clk_prepare_enable(tcon->clk); 667 668 if (tcon->quirks->has_channel_0) { 669 tcon->sclk0 = devm_clk_get(dev, "tcon-ch0"); 670 if (IS_ERR(tcon->sclk0)) { 671 dev_err(dev, "Couldn't get the TCON channel 0 clock\n"); 672 return PTR_ERR(tcon->sclk0); 673 } 674 } 675 676 if (tcon->quirks->has_channel_1) { 677 tcon->sclk1 = devm_clk_get(dev, "tcon-ch1"); 678 if (IS_ERR(tcon->sclk1)) { 679 dev_err(dev, "Couldn't get the TCON channel 1 clock\n"); 680 return PTR_ERR(tcon->sclk1); 681 } 682 } 683 684 return 0; 685 } 686 687 static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon) 688 { 689 clk_disable_unprepare(tcon->clk); 690 } 691 692 static int sun4i_tcon_init_irq(struct device *dev, 693 struct sun4i_tcon *tcon) 694 { 695 struct platform_device *pdev = to_platform_device(dev); 696 int irq, ret; 697 698 irq = platform_get_irq(pdev, 0); 699 if (irq < 0) { 700 dev_err(dev, "Couldn't retrieve the TCON interrupt\n"); 701 return irq; 702 } 703 704 ret = devm_request_irq(dev, irq, sun4i_tcon_handler, 0, 705 dev_name(dev), tcon); 706 if (ret) { 707 dev_err(dev, "Couldn't request the IRQ\n"); 708 return ret; 709 } 710 711 return 0; 712 } 713 714 static struct regmap_config sun4i_tcon_regmap_config = { 715 .reg_bits = 32, 716 .val_bits = 32, 717 .reg_stride = 4, 718 .max_register = 0x800, 719 }; 720 721 static int sun4i_tcon_init_regmap(struct device *dev, 722 struct sun4i_tcon *tcon) 723 { 724 struct platform_device *pdev = to_platform_device(dev); 725 struct resource *res; 726 void __iomem *regs; 727 728 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 729 regs = devm_ioremap_resource(dev, res); 730 if (IS_ERR(regs)) 731 return PTR_ERR(regs); 732 733 tcon->regs = devm_regmap_init_mmio(dev, regs, 734 &sun4i_tcon_regmap_config); 735 if (IS_ERR(tcon->regs)) { 736 dev_err(dev, "Couldn't create the TCON regmap\n"); 737 return PTR_ERR(tcon->regs); 738 } 739 740 /* Make sure the TCON is disabled and all IRQs are off */ 741 regmap_write(tcon->regs, SUN4I_TCON_GCTL_REG, 0); 742 regmap_write(tcon->regs, SUN4I_TCON_GINT0_REG, 0); 743 regmap_write(tcon->regs, SUN4I_TCON_GINT1_REG, 0); 744 745 /* Disable IO lines and set them to tristate */ 746 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, ~0); 747 regmap_write(tcon->regs, SUN4I_TCON1_IO_TRI_REG, ~0); 748 749 return 0; 750 } 751 752 /* 753 * On SoCs with the old display pipeline design (Display Engine 1.0), 754 * the TCON is always tied to just one backend. Hence we can traverse 755 * the of_graph upwards to find the backend our tcon is connected to, 756 * and take its ID as our own. 757 * 758 * We can either identify backends from their compatible strings, which 759 * means maintaining a large list of them. Or, since the backend is 760 * registered and binded before the TCON, we can just go through the 761 * list of registered backends and compare the device node. 762 * 763 * As the structures now store engines instead of backends, here this 764 * function in fact searches the corresponding engine, and the ID is 765 * requested via the get_id function of the engine. 766 */ 767 static struct sunxi_engine * 768 sun4i_tcon_find_engine_traverse(struct sun4i_drv *drv, 769 struct device_node *node) 770 { 771 struct device_node *port, *ep, *remote; 772 struct sunxi_engine *engine = ERR_PTR(-EINVAL); 773 774 port = of_graph_get_port_by_id(node, 0); 775 if (!port) 776 return ERR_PTR(-EINVAL); 777 778 /* 779 * This only works if there is only one path from the TCON 780 * to any display engine. Otherwise the probe order of the 781 * TCONs and display engines is not guaranteed. They may 782 * either bind to the wrong one, or worse, bind to the same 783 * one if additional checks are not done. 784 * 785 * Bail out if there are multiple input connections. 786 */ 787 if (of_get_available_child_count(port) != 1) 788 goto out_put_port; 789 790 /* Get the first connection without specifying an ID */ 791 ep = of_get_next_available_child(port, NULL); 792 if (!ep) 793 goto out_put_port; 794 795 remote = of_graph_get_remote_port_parent(ep); 796 if (!remote) 797 goto out_put_ep; 798 799 /* does this node match any registered engines? */ 800 list_for_each_entry(engine, &drv->engine_list, list) 801 if (remote == engine->node) 802 goto out_put_remote; 803 804 /* keep looking through upstream ports */ 805 engine = sun4i_tcon_find_engine_traverse(drv, remote); 806 807 out_put_remote: 808 of_node_put(remote); 809 out_put_ep: 810 of_node_put(ep); 811 out_put_port: 812 of_node_put(port); 813 814 return engine; 815 } 816 817 /* 818 * The device tree binding says that the remote endpoint ID of any 819 * connection between components, up to and including the TCON, of 820 * the display pipeline should be equal to the actual ID of the local 821 * component. Thus we can look at any one of the input connections of 822 * the TCONs, and use that connection's remote endpoint ID as our own. 823 * 824 * Since the user of this function already finds the input port, 825 * the port is passed in directly without further checks. 826 */ 827 static int sun4i_tcon_of_get_id_from_port(struct device_node *port) 828 { 829 struct device_node *ep; 830 int ret = -EINVAL; 831 832 /* try finding an upstream endpoint */ 833 for_each_available_child_of_node(port, ep) { 834 struct device_node *remote; 835 u32 reg; 836 837 remote = of_graph_get_remote_endpoint(ep); 838 if (!remote) 839 continue; 840 841 ret = of_property_read_u32(remote, "reg", ®); 842 if (ret) 843 continue; 844 845 ret = reg; 846 } 847 848 return ret; 849 } 850 851 /* 852 * Once we know the TCON's id, we can look through the list of 853 * engines to find a matching one. We assume all engines have 854 * been probed and added to the list. 855 */ 856 static struct sunxi_engine *sun4i_tcon_get_engine_by_id(struct sun4i_drv *drv, 857 int id) 858 { 859 struct sunxi_engine *engine; 860 861 list_for_each_entry(engine, &drv->engine_list, list) 862 if (engine->id == id) 863 return engine; 864 865 return ERR_PTR(-EINVAL); 866 } 867 868 /* 869 * On SoCs with the old display pipeline design (Display Engine 1.0), 870 * we assumed the TCON was always tied to just one backend. However 871 * this proved not to be the case. On the A31, the TCON can select 872 * either backend as its source. On the A20 (and likely on the A10), 873 * the backend can choose which TCON to output to. 874 * 875 * The device tree binding says that the remote endpoint ID of any 876 * connection between components, up to and including the TCON, of 877 * the display pipeline should be equal to the actual ID of the local 878 * component. Thus we should be able to look at any one of the input 879 * connections of the TCONs, and use that connection's remote endpoint 880 * ID as our own. 881 * 882 * However the connections between the backend and TCON were assumed 883 * to be always singular, and their endpoit IDs were all incorrectly 884 * set to 0. This means for these old device trees, we cannot just look 885 * up the remote endpoint ID of a TCON input endpoint. TCON1 would be 886 * incorrectly identified as TCON0. 887 * 888 * This function first checks if the TCON node has 2 input endpoints. 889 * If so, then the device tree is a corrected version, and it will use 890 * sun4i_tcon_of_get_id() and sun4i_tcon_get_engine_by_id() from above 891 * to fetch the ID and engine directly. If not, then it is likely an 892 * old device trees, where the endpoint IDs were incorrect, but did not 893 * have endpoint connections between the backend and TCON across 894 * different display pipelines. It will fall back to the old method of 895 * traversing the of_graph to try and find a matching engine by device 896 * node. 897 * 898 * In the case of single display pipeline device trees, either method 899 * works. 900 */ 901 static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv, 902 struct device_node *node) 903 { 904 struct device_node *port; 905 struct sunxi_engine *engine; 906 907 port = of_graph_get_port_by_id(node, 0); 908 if (!port) 909 return ERR_PTR(-EINVAL); 910 911 /* 912 * Is this a corrected device tree with cross pipeline 913 * connections between the backend and TCON? 914 */ 915 if (of_get_child_count(port) > 1) { 916 /* Get our ID directly from an upstream endpoint */ 917 int id = sun4i_tcon_of_get_id_from_port(port); 918 919 /* Get our engine by matching our ID */ 920 engine = sun4i_tcon_get_engine_by_id(drv, id); 921 922 of_node_put(port); 923 return engine; 924 } 925 926 /* Fallback to old method by traversing input endpoints */ 927 of_node_put(port); 928 return sun4i_tcon_find_engine_traverse(drv, node); 929 } 930 931 static int sun4i_tcon_bind(struct device *dev, struct device *master, 932 void *data) 933 { 934 struct drm_device *drm = data; 935 struct sun4i_drv *drv = drm->dev_private; 936 struct sunxi_engine *engine; 937 struct device_node *remote; 938 struct sun4i_tcon *tcon; 939 struct reset_control *edp_rstc; 940 bool has_lvds_rst, has_lvds_alt, can_lvds; 941 int ret; 942 943 engine = sun4i_tcon_find_engine(drv, dev->of_node); 944 if (IS_ERR(engine)) { 945 dev_err(dev, "Couldn't find matching engine\n"); 946 return -EPROBE_DEFER; 947 } 948 949 tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL); 950 if (!tcon) 951 return -ENOMEM; 952 dev_set_drvdata(dev, tcon); 953 tcon->drm = drm; 954 tcon->dev = dev; 955 tcon->id = engine->id; 956 tcon->quirks = of_device_get_match_data(dev); 957 958 tcon->lcd_rst = devm_reset_control_get(dev, "lcd"); 959 if (IS_ERR(tcon->lcd_rst)) { 960 dev_err(dev, "Couldn't get our reset line\n"); 961 return PTR_ERR(tcon->lcd_rst); 962 } 963 964 if (tcon->quirks->needs_edp_reset) { 965 edp_rstc = devm_reset_control_get_shared(dev, "edp"); 966 if (IS_ERR(edp_rstc)) { 967 dev_err(dev, "Couldn't get edp reset line\n"); 968 return PTR_ERR(edp_rstc); 969 } 970 971 ret = reset_control_deassert(edp_rstc); 972 if (ret) { 973 dev_err(dev, "Couldn't deassert edp reset line\n"); 974 return ret; 975 } 976 } 977 978 /* Make sure our TCON is reset */ 979 ret = reset_control_reset(tcon->lcd_rst); 980 if (ret) { 981 dev_err(dev, "Couldn't deassert our reset line\n"); 982 return ret; 983 } 984 985 if (tcon->quirks->supports_lvds) { 986 /* 987 * This can only be made optional since we've had DT 988 * nodes without the LVDS reset properties. 989 * 990 * If the property is missing, just disable LVDS, and 991 * print a warning. 992 */ 993 tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds"); 994 if (IS_ERR(tcon->lvds_rst)) { 995 dev_err(dev, "Couldn't get our reset line\n"); 996 return PTR_ERR(tcon->lvds_rst); 997 } else if (tcon->lvds_rst) { 998 has_lvds_rst = true; 999 reset_control_reset(tcon->lvds_rst); 1000 } else { 1001 has_lvds_rst = false; 1002 } 1003 1004 /* 1005 * This can only be made optional since we've had DT 1006 * nodes without the LVDS reset properties. 1007 * 1008 * If the property is missing, just disable LVDS, and 1009 * print a warning. 1010 */ 1011 if (tcon->quirks->has_lvds_alt) { 1012 tcon->lvds_pll = devm_clk_get(dev, "lvds-alt"); 1013 if (IS_ERR(tcon->lvds_pll)) { 1014 if (PTR_ERR(tcon->lvds_pll) == -ENOENT) { 1015 has_lvds_alt = false; 1016 } else { 1017 dev_err(dev, "Couldn't get the LVDS PLL\n"); 1018 return PTR_ERR(tcon->lvds_pll); 1019 } 1020 } else { 1021 has_lvds_alt = true; 1022 } 1023 } 1024 1025 if (!has_lvds_rst || 1026 (tcon->quirks->has_lvds_alt && !has_lvds_alt)) { 1027 dev_warn(dev, "Missing LVDS properties, Please upgrade your DT\n"); 1028 dev_warn(dev, "LVDS output disabled\n"); 1029 can_lvds = false; 1030 } else { 1031 can_lvds = true; 1032 } 1033 } else { 1034 can_lvds = false; 1035 } 1036 1037 ret = sun4i_tcon_init_clocks(dev, tcon); 1038 if (ret) { 1039 dev_err(dev, "Couldn't init our TCON clocks\n"); 1040 goto err_assert_reset; 1041 } 1042 1043 ret = sun4i_tcon_init_regmap(dev, tcon); 1044 if (ret) { 1045 dev_err(dev, "Couldn't init our TCON regmap\n"); 1046 goto err_free_clocks; 1047 } 1048 1049 if (tcon->quirks->has_channel_0) { 1050 ret = sun4i_dclk_create(dev, tcon); 1051 if (ret) { 1052 dev_err(dev, "Couldn't create our TCON dot clock\n"); 1053 goto err_free_clocks; 1054 } 1055 } 1056 1057 ret = sun4i_tcon_init_irq(dev, tcon); 1058 if (ret) { 1059 dev_err(dev, "Couldn't init our TCON interrupts\n"); 1060 goto err_free_dotclock; 1061 } 1062 1063 tcon->crtc = sun4i_crtc_init(drm, engine, tcon); 1064 if (IS_ERR(tcon->crtc)) { 1065 dev_err(dev, "Couldn't create our CRTC\n"); 1066 ret = PTR_ERR(tcon->crtc); 1067 goto err_free_dotclock; 1068 } 1069 1070 /* 1071 * If we have an LVDS panel connected to the TCON, we should 1072 * just probe the LVDS connector. Otherwise, just probe RGB as 1073 * we used to. 1074 */ 1075 remote = of_graph_get_remote_node(dev->of_node, 1, 0); 1076 if (of_device_is_compatible(remote, "panel-lvds")) 1077 if (can_lvds) 1078 ret = sun4i_lvds_init(drm, tcon); 1079 else 1080 ret = -EINVAL; 1081 else 1082 ret = sun4i_rgb_init(drm, tcon); 1083 of_node_put(remote); 1084 1085 if (ret < 0) 1086 goto err_free_dotclock; 1087 1088 if (tcon->quirks->needs_de_be_mux) { 1089 /* 1090 * We assume there is no dynamic muxing of backends 1091 * and TCONs, so we select the backend with same ID. 1092 * 1093 * While dynamic selection might be interesting, since 1094 * the CRTC is tied to the TCON, while the layers are 1095 * tied to the backends, this means, we will need to 1096 * switch between groups of layers. There might not be 1097 * a way to represent this constraint in DRM. 1098 */ 1099 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, 1100 SUN4I_TCON0_CTL_SRC_SEL_MASK, 1101 tcon->id); 1102 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, 1103 SUN4I_TCON1_CTL_SRC_SEL_MASK, 1104 tcon->id); 1105 } 1106 1107 list_add_tail(&tcon->list, &drv->tcon_list); 1108 1109 return 0; 1110 1111 err_free_dotclock: 1112 if (tcon->quirks->has_channel_0) 1113 sun4i_dclk_free(tcon); 1114 err_free_clocks: 1115 sun4i_tcon_free_clocks(tcon); 1116 err_assert_reset: 1117 reset_control_assert(tcon->lcd_rst); 1118 return ret; 1119 } 1120 1121 static void sun4i_tcon_unbind(struct device *dev, struct device *master, 1122 void *data) 1123 { 1124 struct sun4i_tcon *tcon = dev_get_drvdata(dev); 1125 1126 list_del(&tcon->list); 1127 if (tcon->quirks->has_channel_0) 1128 sun4i_dclk_free(tcon); 1129 sun4i_tcon_free_clocks(tcon); 1130 } 1131 1132 static const struct component_ops sun4i_tcon_ops = { 1133 .bind = sun4i_tcon_bind, 1134 .unbind = sun4i_tcon_unbind, 1135 }; 1136 1137 static int sun4i_tcon_probe(struct platform_device *pdev) 1138 { 1139 struct device_node *node = pdev->dev.of_node; 1140 struct drm_bridge *bridge; 1141 struct drm_panel *panel; 1142 int ret; 1143 1144 ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge); 1145 if (ret == -EPROBE_DEFER) 1146 return ret; 1147 1148 return component_add(&pdev->dev, &sun4i_tcon_ops); 1149 } 1150 1151 static int sun4i_tcon_remove(struct platform_device *pdev) 1152 { 1153 component_del(&pdev->dev, &sun4i_tcon_ops); 1154 1155 return 0; 1156 } 1157 1158 /* platform specific TCON muxing callbacks */ 1159 static int sun4i_a10_tcon_set_mux(struct sun4i_tcon *tcon, 1160 const struct drm_encoder *encoder) 1161 { 1162 struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev); 1163 u32 shift; 1164 1165 if (!tcon0) 1166 return -EINVAL; 1167 1168 switch (encoder->encoder_type) { 1169 case DRM_MODE_ENCODER_TMDS: 1170 /* HDMI */ 1171 shift = 8; 1172 break; 1173 default: 1174 return -EINVAL; 1175 } 1176 1177 regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG, 1178 0x3 << shift, tcon->id << shift); 1179 1180 return 0; 1181 } 1182 1183 static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon, 1184 const struct drm_encoder *encoder) 1185 { 1186 u32 val; 1187 1188 if (encoder->encoder_type == DRM_MODE_ENCODER_TVDAC) 1189 val = 1; 1190 else 1191 val = 0; 1192 1193 /* 1194 * FIXME: Undocumented bits 1195 */ 1196 return regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, val); 1197 } 1198 1199 static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon, 1200 const struct drm_encoder *encoder) 1201 { 1202 struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev); 1203 u32 shift; 1204 1205 if (!tcon0) 1206 return -EINVAL; 1207 1208 switch (encoder->encoder_type) { 1209 case DRM_MODE_ENCODER_TMDS: 1210 /* HDMI */ 1211 shift = 8; 1212 break; 1213 default: 1214 /* TODO A31 has MIPI DSI but A31s does not */ 1215 return -EINVAL; 1216 } 1217 1218 regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG, 1219 0x3 << shift, tcon->id << shift); 1220 1221 return 0; 1222 } 1223 1224 static const struct sun4i_tcon_quirks sun4i_a10_quirks = { 1225 .has_channel_0 = true, 1226 .has_channel_1 = true, 1227 .set_mux = sun4i_a10_tcon_set_mux, 1228 }; 1229 1230 static const struct sun4i_tcon_quirks sun5i_a13_quirks = { 1231 .has_channel_0 = true, 1232 .has_channel_1 = true, 1233 .set_mux = sun5i_a13_tcon_set_mux, 1234 }; 1235 1236 static const struct sun4i_tcon_quirks sun6i_a31_quirks = { 1237 .has_channel_0 = true, 1238 .has_channel_1 = true, 1239 .has_lvds_alt = true, 1240 .needs_de_be_mux = true, 1241 .set_mux = sun6i_tcon_set_mux, 1242 }; 1243 1244 static const struct sun4i_tcon_quirks sun6i_a31s_quirks = { 1245 .has_channel_0 = true, 1246 .has_channel_1 = true, 1247 .needs_de_be_mux = true, 1248 }; 1249 1250 static const struct sun4i_tcon_quirks sun7i_a20_quirks = { 1251 .has_channel_0 = true, 1252 .has_channel_1 = true, 1253 /* Same display pipeline structure as A10 */ 1254 .set_mux = sun4i_a10_tcon_set_mux, 1255 }; 1256 1257 static const struct sun4i_tcon_quirks sun8i_a33_quirks = { 1258 .has_channel_0 = true, 1259 .has_lvds_alt = true, 1260 }; 1261 1262 static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { 1263 .supports_lvds = true, 1264 .has_channel_0 = true, 1265 }; 1266 1267 static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = { 1268 .has_channel_1 = true, 1269 }; 1270 1271 static const struct sun4i_tcon_quirks sun8i_v3s_quirks = { 1272 .has_channel_0 = true, 1273 }; 1274 1275 static const struct sun4i_tcon_quirks sun9i_a80_tcon_lcd_quirks = { 1276 .has_channel_0 = true, 1277 .needs_edp_reset = true, 1278 }; 1279 1280 static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks = { 1281 .has_channel_1 = true, 1282 .needs_edp_reset = true, 1283 }; 1284 1285 /* sun4i_drv uses this list to check if a device node is a TCON */ 1286 const struct of_device_id sun4i_tcon_of_table[] = { 1287 { .compatible = "allwinner,sun4i-a10-tcon", .data = &sun4i_a10_quirks }, 1288 { .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks }, 1289 { .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks }, 1290 { .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks }, 1291 { .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks }, 1292 { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks }, 1293 { .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks }, 1294 { .compatible = "allwinner,sun8i-a83t-tcon-tv", .data = &sun8i_a83t_tv_quirks }, 1295 { .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks }, 1296 { .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = &sun9i_a80_tcon_lcd_quirks }, 1297 { .compatible = "allwinner,sun9i-a80-tcon-tv", .data = &sun9i_a80_tcon_tv_quirks }, 1298 { } 1299 }; 1300 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table); 1301 EXPORT_SYMBOL(sun4i_tcon_of_table); 1302 1303 static struct platform_driver sun4i_tcon_platform_driver = { 1304 .probe = sun4i_tcon_probe, 1305 .remove = sun4i_tcon_remove, 1306 .driver = { 1307 .name = "sun4i-tcon", 1308 .of_match_table = sun4i_tcon_of_table, 1309 }, 1310 }; 1311 module_platform_driver(sun4i_tcon_platform_driver); 1312 1313 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); 1314 MODULE_DESCRIPTION("Allwinner A10 Timing Controller Driver"); 1315 MODULE_LICENSE("GPL"); 1316