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_modes.h> 18 #include <drm/drm_panel.h> 19 20 #include <linux/component.h> 21 #include <linux/ioport.h> 22 #include <linux/of_address.h> 23 #include <linux/of_graph.h> 24 #include <linux/of_irq.h> 25 #include <linux/regmap.h> 26 #include <linux/reset.h> 27 28 #include "sun4i_crtc.h" 29 #include "sun4i_dotclock.h" 30 #include "sun4i_drv.h" 31 #include "sun4i_rgb.h" 32 #include "sun4i_tcon.h" 33 34 void sun4i_tcon_disable(struct sun4i_tcon *tcon) 35 { 36 DRM_DEBUG_DRIVER("Disabling TCON\n"); 37 38 /* Disable the TCON */ 39 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, 40 SUN4I_TCON_GCTL_TCON_ENABLE, 0); 41 } 42 EXPORT_SYMBOL(sun4i_tcon_disable); 43 44 void sun4i_tcon_enable(struct sun4i_tcon *tcon) 45 { 46 DRM_DEBUG_DRIVER("Enabling TCON\n"); 47 48 /* Enable the TCON */ 49 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, 50 SUN4I_TCON_GCTL_TCON_ENABLE, 51 SUN4I_TCON_GCTL_TCON_ENABLE); 52 } 53 EXPORT_SYMBOL(sun4i_tcon_enable); 54 55 void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel) 56 { 57 /* Disable the TCON's channel */ 58 if (channel == 0) { 59 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, 60 SUN4I_TCON0_CTL_TCON_ENABLE, 0); 61 clk_disable_unprepare(tcon->dclk); 62 } else if (channel == 1) { 63 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, 64 SUN4I_TCON1_CTL_TCON_ENABLE, 0); 65 clk_disable_unprepare(tcon->sclk1); 66 } 67 } 68 EXPORT_SYMBOL(sun4i_tcon_channel_disable); 69 70 void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel) 71 { 72 /* Enable the TCON's channel */ 73 if (channel == 0) { 74 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, 75 SUN4I_TCON0_CTL_TCON_ENABLE, 76 SUN4I_TCON0_CTL_TCON_ENABLE); 77 clk_prepare_enable(tcon->dclk); 78 } else if (channel == 1) { 79 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, 80 SUN4I_TCON1_CTL_TCON_ENABLE, 81 SUN4I_TCON1_CTL_TCON_ENABLE); 82 clk_prepare_enable(tcon->sclk1); 83 } 84 } 85 EXPORT_SYMBOL(sun4i_tcon_channel_enable); 86 87 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable) 88 { 89 u32 mask, val = 0; 90 91 DRM_DEBUG_DRIVER("%sabling VBLANK interrupt\n", enable ? "En" : "Dis"); 92 93 mask = SUN4I_TCON_GINT0_VBLANK_ENABLE(0) | 94 SUN4I_TCON_GINT0_VBLANK_ENABLE(1); 95 96 if (enable) 97 val = mask; 98 99 regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, mask, val); 100 } 101 EXPORT_SYMBOL(sun4i_tcon_enable_vblank); 102 103 static int sun4i_tcon_get_clk_delay(struct drm_display_mode *mode, 104 int channel) 105 { 106 int delay = mode->vtotal - mode->vdisplay; 107 108 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 109 delay /= 2; 110 111 if (channel == 1) 112 delay -= 2; 113 114 delay = min(delay, 30); 115 116 DRM_DEBUG_DRIVER("TCON %d clock delay %u\n", channel, delay); 117 118 return delay; 119 } 120 121 void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon, 122 struct drm_display_mode *mode) 123 { 124 unsigned int bp, hsync, vsync; 125 u8 clk_delay; 126 u32 val = 0; 127 128 /* Adjust clock delay */ 129 clk_delay = sun4i_tcon_get_clk_delay(mode, 0); 130 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, 131 SUN4I_TCON0_CTL_CLK_DELAY_MASK, 132 SUN4I_TCON0_CTL_CLK_DELAY(clk_delay)); 133 134 /* Set the resolution */ 135 regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG, 136 SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) | 137 SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay)); 138 139 /* 140 * This is called a backporch in the register documentation, 141 * but it really is the front porch + hsync 142 */ 143 bp = mode->crtc_htotal - mode->crtc_hsync_start; 144 DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", 145 mode->crtc_htotal, bp); 146 147 /* Set horizontal display timings */ 148 regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG, 149 SUN4I_TCON0_BASIC1_H_TOTAL(mode->crtc_htotal) | 150 SUN4I_TCON0_BASIC1_H_BACKPORCH(bp)); 151 152 /* 153 * This is called a backporch in the register documentation, 154 * but it really is the front porch + hsync 155 */ 156 bp = mode->crtc_vtotal - mode->crtc_vsync_start; 157 DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n", 158 mode->crtc_vtotal, bp); 159 160 /* Set vertical display timings */ 161 regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG, 162 SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal) | 163 SUN4I_TCON0_BASIC2_V_BACKPORCH(bp)); 164 165 /* Set Hsync and Vsync length */ 166 hsync = mode->crtc_hsync_end - mode->crtc_hsync_start; 167 vsync = mode->crtc_vsync_end - mode->crtc_vsync_start; 168 DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync); 169 regmap_write(tcon->regs, SUN4I_TCON0_BASIC3_REG, 170 SUN4I_TCON0_BASIC3_V_SYNC(vsync) | 171 SUN4I_TCON0_BASIC3_H_SYNC(hsync)); 172 173 /* Setup the polarity of the various signals */ 174 if (!(mode->flags & DRM_MODE_FLAG_PHSYNC)) 175 val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE; 176 177 if (!(mode->flags & DRM_MODE_FLAG_PVSYNC)) 178 val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE; 179 180 regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG, 181 SUN4I_TCON0_IO_POL_HSYNC_POSITIVE | SUN4I_TCON0_IO_POL_VSYNC_POSITIVE, 182 val); 183 184 /* Map output pins to channel 0 */ 185 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, 186 SUN4I_TCON_GCTL_IOMAP_MASK, 187 SUN4I_TCON_GCTL_IOMAP_TCON0); 188 189 /* Enable the output on the pins */ 190 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0); 191 } 192 EXPORT_SYMBOL(sun4i_tcon0_mode_set); 193 194 void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, 195 struct drm_display_mode *mode) 196 { 197 unsigned int bp, hsync, vsync; 198 u8 clk_delay; 199 u32 val; 200 201 /* Adjust clock delay */ 202 clk_delay = sun4i_tcon_get_clk_delay(mode, 1); 203 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, 204 SUN4I_TCON1_CTL_CLK_DELAY_MASK, 205 SUN4I_TCON1_CTL_CLK_DELAY(clk_delay)); 206 207 /* Set interlaced mode */ 208 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 209 val = SUN4I_TCON1_CTL_INTERLACE_ENABLE; 210 else 211 val = 0; 212 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, 213 SUN4I_TCON1_CTL_INTERLACE_ENABLE, 214 val); 215 216 /* Set the input resolution */ 217 regmap_write(tcon->regs, SUN4I_TCON1_BASIC0_REG, 218 SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay) | 219 SUN4I_TCON1_BASIC0_Y(mode->crtc_vdisplay)); 220 221 /* Set the upscaling resolution */ 222 regmap_write(tcon->regs, SUN4I_TCON1_BASIC1_REG, 223 SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay) | 224 SUN4I_TCON1_BASIC1_Y(mode->crtc_vdisplay)); 225 226 /* Set the output resolution */ 227 regmap_write(tcon->regs, SUN4I_TCON1_BASIC2_REG, 228 SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay) | 229 SUN4I_TCON1_BASIC2_Y(mode->crtc_vdisplay)); 230 231 /* Set horizontal display timings */ 232 bp = mode->crtc_htotal - mode->crtc_hsync_end; 233 DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", 234 mode->htotal, bp); 235 regmap_write(tcon->regs, SUN4I_TCON1_BASIC3_REG, 236 SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal) | 237 SUN4I_TCON1_BASIC3_H_BACKPORCH(bp)); 238 239 /* Set vertical display timings */ 240 bp = mode->crtc_vtotal - mode->crtc_vsync_end; 241 DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n", 242 mode->vtotal, bp); 243 regmap_write(tcon->regs, SUN4I_TCON1_BASIC4_REG, 244 SUN4I_TCON1_BASIC4_V_TOTAL(mode->vtotal) | 245 SUN4I_TCON1_BASIC4_V_BACKPORCH(bp)); 246 247 /* Set Hsync and Vsync length */ 248 hsync = mode->crtc_hsync_end - mode->crtc_hsync_start; 249 vsync = mode->crtc_vsync_end - mode->crtc_vsync_start; 250 DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync); 251 regmap_write(tcon->regs, SUN4I_TCON1_BASIC5_REG, 252 SUN4I_TCON1_BASIC5_V_SYNC(vsync) | 253 SUN4I_TCON1_BASIC5_H_SYNC(hsync)); 254 255 /* Map output pins to channel 1 */ 256 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, 257 SUN4I_TCON_GCTL_IOMAP_MASK, 258 SUN4I_TCON_GCTL_IOMAP_TCON1); 259 260 /* 261 * FIXME: Undocumented bits 262 */ 263 if (tcon->has_mux) 264 regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, 1); 265 } 266 EXPORT_SYMBOL(sun4i_tcon1_mode_set); 267 268 static void sun4i_tcon_finish_page_flip(struct drm_device *dev, 269 struct sun4i_crtc *scrtc) 270 { 271 unsigned long flags; 272 273 spin_lock_irqsave(&dev->event_lock, flags); 274 if (scrtc->event) { 275 drm_crtc_send_vblank_event(&scrtc->crtc, scrtc->event); 276 drm_crtc_vblank_put(&scrtc->crtc); 277 scrtc->event = NULL; 278 } 279 spin_unlock_irqrestore(&dev->event_lock, flags); 280 } 281 282 static irqreturn_t sun4i_tcon_handler(int irq, void *private) 283 { 284 struct sun4i_tcon *tcon = private; 285 struct drm_device *drm = tcon->drm; 286 struct sun4i_drv *drv = drm->dev_private; 287 struct sun4i_crtc *scrtc = drv->crtc; 288 unsigned int status; 289 290 regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status); 291 292 if (!(status & (SUN4I_TCON_GINT0_VBLANK_INT(0) | 293 SUN4I_TCON_GINT0_VBLANK_INT(1)))) 294 return IRQ_NONE; 295 296 drm_crtc_handle_vblank(&scrtc->crtc); 297 sun4i_tcon_finish_page_flip(drm, scrtc); 298 299 /* Acknowledge the interrupt */ 300 regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, 301 SUN4I_TCON_GINT0_VBLANK_INT(0) | 302 SUN4I_TCON_GINT0_VBLANK_INT(1), 303 0); 304 305 return IRQ_HANDLED; 306 } 307 308 static int sun4i_tcon_init_clocks(struct device *dev, 309 struct sun4i_tcon *tcon) 310 { 311 tcon->clk = devm_clk_get(dev, "ahb"); 312 if (IS_ERR(tcon->clk)) { 313 dev_err(dev, "Couldn't get the TCON bus clock\n"); 314 return PTR_ERR(tcon->clk); 315 } 316 clk_prepare_enable(tcon->clk); 317 318 tcon->sclk0 = devm_clk_get(dev, "tcon-ch0"); 319 if (IS_ERR(tcon->sclk0)) { 320 dev_err(dev, "Couldn't get the TCON channel 0 clock\n"); 321 return PTR_ERR(tcon->sclk0); 322 } 323 324 tcon->sclk1 = devm_clk_get(dev, "tcon-ch1"); 325 if (IS_ERR(tcon->sclk1)) { 326 dev_err(dev, "Couldn't get the TCON channel 1 clock\n"); 327 return PTR_ERR(tcon->sclk1); 328 } 329 330 return sun4i_dclk_create(dev, tcon); 331 } 332 333 static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon) 334 { 335 sun4i_dclk_free(tcon); 336 clk_disable_unprepare(tcon->clk); 337 } 338 339 static int sun4i_tcon_init_irq(struct device *dev, 340 struct sun4i_tcon *tcon) 341 { 342 struct platform_device *pdev = to_platform_device(dev); 343 int irq, ret; 344 345 irq = platform_get_irq(pdev, 0); 346 if (irq < 0) { 347 dev_err(dev, "Couldn't retrieve the TCON interrupt\n"); 348 return irq; 349 } 350 351 ret = devm_request_irq(dev, irq, sun4i_tcon_handler, 0, 352 dev_name(dev), tcon); 353 if (ret) { 354 dev_err(dev, "Couldn't request the IRQ\n"); 355 return ret; 356 } 357 358 return 0; 359 } 360 361 static struct regmap_config sun4i_tcon_regmap_config = { 362 .reg_bits = 32, 363 .val_bits = 32, 364 .reg_stride = 4, 365 .max_register = 0x800, 366 }; 367 368 static int sun4i_tcon_init_regmap(struct device *dev, 369 struct sun4i_tcon *tcon) 370 { 371 struct platform_device *pdev = to_platform_device(dev); 372 struct resource *res; 373 void __iomem *regs; 374 375 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 376 regs = devm_ioremap_resource(dev, res); 377 if (IS_ERR(regs)) 378 return PTR_ERR(regs); 379 380 tcon->regs = devm_regmap_init_mmio(dev, regs, 381 &sun4i_tcon_regmap_config); 382 if (IS_ERR(tcon->regs)) { 383 dev_err(dev, "Couldn't create the TCON regmap\n"); 384 return PTR_ERR(tcon->regs); 385 } 386 387 /* Make sure the TCON is disabled and all IRQs are off */ 388 regmap_write(tcon->regs, SUN4I_TCON_GCTL_REG, 0); 389 regmap_write(tcon->regs, SUN4I_TCON_GINT0_REG, 0); 390 regmap_write(tcon->regs, SUN4I_TCON_GINT1_REG, 0); 391 392 /* Disable IO lines and set them to tristate */ 393 regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, ~0); 394 regmap_write(tcon->regs, SUN4I_TCON1_IO_TRI_REG, ~0); 395 396 return 0; 397 } 398 399 struct drm_panel *sun4i_tcon_find_panel(struct device_node *node) 400 { 401 struct device_node *port, *remote, *child; 402 struct device_node *end_node = NULL; 403 404 /* Inputs are listed first, then outputs */ 405 port = of_graph_get_port_by_id(node, 1); 406 407 /* 408 * Our first output is the RGB interface where the panel will 409 * be connected. 410 */ 411 for_each_child_of_node(port, child) { 412 u32 reg; 413 414 of_property_read_u32(child, "reg", ®); 415 if (reg == 0) 416 end_node = child; 417 } 418 419 if (!end_node) { 420 DRM_DEBUG_DRIVER("Missing panel endpoint\n"); 421 return ERR_PTR(-ENODEV); 422 } 423 424 remote = of_graph_get_remote_port_parent(end_node); 425 if (!remote) { 426 DRM_DEBUG_DRIVER("Unable to parse remote node\n"); 427 return ERR_PTR(-EINVAL); 428 } 429 430 return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER); 431 } 432 433 struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node) 434 { 435 struct device_node *port, *remote, *child; 436 struct device_node *end_node = NULL; 437 438 /* Inputs are listed first, then outputs */ 439 port = of_graph_get_port_by_id(node, 1); 440 441 /* 442 * Our first output is the RGB interface where the panel will 443 * be connected. 444 */ 445 for_each_child_of_node(port, child) { 446 u32 reg; 447 448 of_property_read_u32(child, "reg", ®); 449 if (reg == 0) 450 end_node = child; 451 } 452 453 if (!end_node) { 454 DRM_DEBUG_DRIVER("Missing bridge endpoint\n"); 455 return ERR_PTR(-ENODEV); 456 } 457 458 remote = of_graph_get_remote_port_parent(end_node); 459 if (!remote) { 460 DRM_DEBUG_DRIVER("Enable to parse remote node\n"); 461 return ERR_PTR(-EINVAL); 462 } 463 464 return of_drm_find_bridge(remote) ?: ERR_PTR(-EPROBE_DEFER); 465 } 466 467 static int sun4i_tcon_bind(struct device *dev, struct device *master, 468 void *data) 469 { 470 struct drm_device *drm = data; 471 struct sun4i_drv *drv = drm->dev_private; 472 struct sun4i_tcon *tcon; 473 int ret; 474 475 tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL); 476 if (!tcon) 477 return -ENOMEM; 478 dev_set_drvdata(dev, tcon); 479 drv->tcon = tcon; 480 tcon->drm = drm; 481 tcon->dev = dev; 482 483 if (of_device_is_compatible(dev->of_node, "allwinner,sun5i-a13-tcon")) 484 tcon->has_mux = true; 485 486 tcon->lcd_rst = devm_reset_control_get(dev, "lcd"); 487 if (IS_ERR(tcon->lcd_rst)) { 488 dev_err(dev, "Couldn't get our reset line\n"); 489 return PTR_ERR(tcon->lcd_rst); 490 } 491 492 /* Make sure our TCON is reset */ 493 if (!reset_control_status(tcon->lcd_rst)) 494 reset_control_assert(tcon->lcd_rst); 495 496 ret = reset_control_deassert(tcon->lcd_rst); 497 if (ret) { 498 dev_err(dev, "Couldn't deassert our reset line\n"); 499 return ret; 500 } 501 502 ret = sun4i_tcon_init_regmap(dev, tcon); 503 if (ret) { 504 dev_err(dev, "Couldn't init our TCON regmap\n"); 505 goto err_assert_reset; 506 } 507 508 ret = sun4i_tcon_init_clocks(dev, tcon); 509 if (ret) { 510 dev_err(dev, "Couldn't init our TCON clocks\n"); 511 goto err_assert_reset; 512 } 513 514 ret = sun4i_tcon_init_irq(dev, tcon); 515 if (ret) { 516 dev_err(dev, "Couldn't init our TCON interrupts\n"); 517 goto err_free_clocks; 518 } 519 520 ret = sun4i_rgb_init(drm); 521 if (ret < 0) 522 goto err_free_clocks; 523 524 return 0; 525 526 err_free_clocks: 527 sun4i_tcon_free_clocks(tcon); 528 err_assert_reset: 529 reset_control_assert(tcon->lcd_rst); 530 return ret; 531 } 532 533 static void sun4i_tcon_unbind(struct device *dev, struct device *master, 534 void *data) 535 { 536 struct sun4i_tcon *tcon = dev_get_drvdata(dev); 537 538 sun4i_tcon_free_clocks(tcon); 539 } 540 541 static struct component_ops sun4i_tcon_ops = { 542 .bind = sun4i_tcon_bind, 543 .unbind = sun4i_tcon_unbind, 544 }; 545 546 static int sun4i_tcon_probe(struct platform_device *pdev) 547 { 548 struct device_node *node = pdev->dev.of_node; 549 struct drm_bridge *bridge; 550 struct drm_panel *panel; 551 552 /* 553 * Neither the bridge or the panel is ready. 554 * Defer the probe. 555 */ 556 panel = sun4i_tcon_find_panel(node); 557 bridge = sun4i_tcon_find_bridge(node); 558 559 /* 560 * If we don't have a panel endpoint, just go on 561 */ 562 if ((PTR_ERR(panel) == -EPROBE_DEFER) && 563 (PTR_ERR(bridge) == -EPROBE_DEFER)) { 564 DRM_DEBUG_DRIVER("Still waiting for our panel/bridge. Deferring...\n"); 565 return -EPROBE_DEFER; 566 } 567 568 return component_add(&pdev->dev, &sun4i_tcon_ops); 569 } 570 571 static int sun4i_tcon_remove(struct platform_device *pdev) 572 { 573 component_del(&pdev->dev, &sun4i_tcon_ops); 574 575 return 0; 576 } 577 578 static const struct of_device_id sun4i_tcon_of_table[] = { 579 { .compatible = "allwinner,sun5i-a13-tcon" }, 580 { } 581 }; 582 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table); 583 584 static struct platform_driver sun4i_tcon_platform_driver = { 585 .probe = sun4i_tcon_probe, 586 .remove = sun4i_tcon_remove, 587 .driver = { 588 .name = "sun4i-tcon", 589 .of_match_table = sun4i_tcon_of_table, 590 }, 591 }; 592 module_platform_driver(sun4i_tcon_platform_driver); 593 594 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); 595 MODULE_DESCRIPTION("Allwinner A10 Timing Controller Driver"); 596 MODULE_LICENSE("GPL"); 597