1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2018 Linus Walleij <linus.walleij@linaro.org> 4 * Parts of this file were based on the MCDE driver by Marcus Lorentzon 5 * (C) ST-Ericsson SA 2013 6 */ 7 8 /** 9 * DOC: ST-Ericsson MCDE Driver 10 * 11 * The MCDE (short for multi-channel display engine) is a graphics 12 * controller found in the Ux500 chipsets, such as NovaThor U8500. 13 * It was initially conceptualized by ST Microelectronics for the 14 * successor of the Nomadik line, STn8500 but productified in the 15 * ST-Ericsson U8500 where is was used for mass-market deployments 16 * in Android phones from Samsung and Sony Ericsson. 17 * 18 * It can do 1080p30 on SDTV CCIR656, DPI-2, DBI-2 or DSI for 19 * panels with or without frame buffering and can convert most 20 * input formats including most variants of RGB and YUV. 21 * 22 * The hardware has four display pipes, and the layout is a little 23 * bit like this: 24 * 25 * Memory -> Overlay -> Channel -> FIFO -> 5 formatters -> DSI/DPI 26 * External 0..5 0..3 A,B, 3 x DSI bridge 27 * source 0..9 C0,C1 2 x DPI 28 * 29 * FIFOs A and B are for LCD and HDMI while FIFO CO/C1 are for 30 * panels with embedded buffer. 31 * 3 of the formatters are for DSI. 32 * 2 of the formatters are for DPI. 33 * 34 * Behind the formatters are the DSI or DPI ports that route to 35 * the external pins of the chip. As there are 3 DSI ports and one 36 * DPI port, it is possible to configure up to 4 display pipelines 37 * (effectively using channels 0..3) for concurrent use. 38 * 39 * In the current DRM/KMS setup, we use one external source, one overlay, 40 * one FIFO and one formatter which we connect to the simple CMA framebuffer 41 * helpers. We then provide a bridge to the DSI port, and on the DSI port 42 * bridge we connect hang a panel bridge or other bridge. This may be subject 43 * to change as we exploit more of the hardware capabilities. 44 * 45 * TODO: 46 * - Enabled damaged rectangles using drm_plane_enable_fb_damage_clips() 47 * so we can selectively just transmit the damaged area to a 48 * command-only display. 49 * - Enable mixing of more planes, possibly at the cost of moving away 50 * from using the simple framebuffer pipeline. 51 * - Enable output to bridges such as the AV8100 HDMI encoder from 52 * the DSI bridge. 53 */ 54 55 #include <linux/clk.h> 56 #include <linux/component.h> 57 #include <linux/dma-buf.h> 58 #include <linux/irq.h> 59 #include <linux/io.h> 60 #include <linux/module.h> 61 #include <linux/of_platform.h> 62 #include <linux/platform_device.h> 63 #include <linux/regulator/consumer.h> 64 #include <linux/slab.h> 65 66 #include <drm/drm_atomic_helper.h> 67 #include <drm/drm_bridge.h> 68 #include <drm/drm_drv.h> 69 #include <drm/drm_fb_cma_helper.h> 70 #include <drm/drm_fb_helper.h> 71 #include <drm/drm_gem.h> 72 #include <drm/drm_gem_cma_helper.h> 73 #include <drm/drm_gem_framebuffer_helper.h> 74 #include <drm/drm_of.h> 75 #include <drm/drm_probe_helper.h> 76 #include <drm/drm_panel.h> 77 #include <drm/drm_vblank.h> 78 79 #include "mcde_drm.h" 80 81 #define DRIVER_DESC "DRM module for MCDE" 82 83 #define MCDE_CR 0x00000000 84 #define MCDE_CR_IFIFOEMPTYLINECOUNT_V422_SHIFT 0 85 #define MCDE_CR_IFIFOEMPTYLINECOUNT_V422_MASK 0x0000003F 86 #define MCDE_CR_IFIFOCTRLEN BIT(15) 87 #define MCDE_CR_UFRECOVERY_MODE_V422 BIT(16) 88 #define MCDE_CR_WRAP_MODE_V422_SHIFT BIT(17) 89 #define MCDE_CR_AUTOCLKG_EN BIT(30) 90 #define MCDE_CR_MCDEEN BIT(31) 91 92 #define MCDE_CONF0 0x00000004 93 #define MCDE_CONF0_SYNCMUX0 BIT(0) 94 #define MCDE_CONF0_SYNCMUX1 BIT(1) 95 #define MCDE_CONF0_SYNCMUX2 BIT(2) 96 #define MCDE_CONF0_SYNCMUX3 BIT(3) 97 #define MCDE_CONF0_SYNCMUX4 BIT(4) 98 #define MCDE_CONF0_SYNCMUX5 BIT(5) 99 #define MCDE_CONF0_SYNCMUX6 BIT(6) 100 #define MCDE_CONF0_SYNCMUX7 BIT(7) 101 #define MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT 12 102 #define MCDE_CONF0_IFIFOCTRLWTRMRKLVL_MASK 0x00007000 103 #define MCDE_CONF0_OUTMUX0_SHIFT 16 104 #define MCDE_CONF0_OUTMUX0_MASK 0x00070000 105 #define MCDE_CONF0_OUTMUX1_SHIFT 19 106 #define MCDE_CONF0_OUTMUX1_MASK 0x00380000 107 #define MCDE_CONF0_OUTMUX2_SHIFT 22 108 #define MCDE_CONF0_OUTMUX2_MASK 0x01C00000 109 #define MCDE_CONF0_OUTMUX3_SHIFT 25 110 #define MCDE_CONF0_OUTMUX3_MASK 0x0E000000 111 #define MCDE_CONF0_OUTMUX4_SHIFT 28 112 #define MCDE_CONF0_OUTMUX4_MASK 0x70000000 113 114 #define MCDE_SSP 0x00000008 115 #define MCDE_AIS 0x00000100 116 #define MCDE_IMSCERR 0x00000110 117 #define MCDE_RISERR 0x00000120 118 #define MCDE_MISERR 0x00000130 119 #define MCDE_SISERR 0x00000140 120 121 #define MCDE_PID 0x000001FC 122 #define MCDE_PID_METALFIX_VERSION_SHIFT 0 123 #define MCDE_PID_METALFIX_VERSION_MASK 0x000000FF 124 #define MCDE_PID_DEVELOPMENT_VERSION_SHIFT 8 125 #define MCDE_PID_DEVELOPMENT_VERSION_MASK 0x0000FF00 126 #define MCDE_PID_MINOR_VERSION_SHIFT 16 127 #define MCDE_PID_MINOR_VERSION_MASK 0x00FF0000 128 #define MCDE_PID_MAJOR_VERSION_SHIFT 24 129 #define MCDE_PID_MAJOR_VERSION_MASK 0xFF000000 130 131 static const struct drm_mode_config_funcs mcde_mode_config_funcs = { 132 .fb_create = drm_gem_fb_create_with_dirty, 133 .atomic_check = drm_atomic_helper_check, 134 .atomic_commit = drm_atomic_helper_commit, 135 }; 136 137 static const struct drm_mode_config_helper_funcs mcde_mode_config_helpers = { 138 /* 139 * Using this function is necessary to commit atomic updates 140 * that need the CRTC to be enabled before a commit, as is 141 * the case with e.g. DSI displays. 142 */ 143 .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, 144 }; 145 146 static irqreturn_t mcde_irq(int irq, void *data) 147 { 148 struct mcde *mcde = data; 149 u32 val; 150 151 val = readl(mcde->regs + MCDE_MISERR); 152 153 mcde_display_irq(mcde); 154 155 if (val) 156 dev_info(mcde->dev, "some error IRQ\n"); 157 writel(val, mcde->regs + MCDE_RISERR); 158 159 return IRQ_HANDLED; 160 } 161 162 static int mcde_modeset_init(struct drm_device *drm) 163 { 164 struct drm_mode_config *mode_config; 165 struct mcde *mcde = drm->dev_private; 166 int ret; 167 168 if (!mcde->bridge) { 169 dev_err(drm->dev, "no display output bridge yet\n"); 170 return -EPROBE_DEFER; 171 } 172 173 mode_config = &drm->mode_config; 174 mode_config->funcs = &mcde_mode_config_funcs; 175 mode_config->helper_private = &mcde_mode_config_helpers; 176 /* This hardware can do 1080p */ 177 mode_config->min_width = 1; 178 mode_config->max_width = 1920; 179 mode_config->min_height = 1; 180 mode_config->max_height = 1080; 181 182 /* 183 * Currently we only support vblank handling on the DSI bridge, using 184 * TE synchronization. If TE sync is not set up, it is still possible 185 * to push out a single update on demand, but this is hard for DRM to 186 * exploit. 187 */ 188 if (mcde->te_sync) { 189 ret = drm_vblank_init(drm, 1); 190 if (ret) { 191 dev_err(drm->dev, "failed to init vblank\n"); 192 goto out_config; 193 } 194 } 195 196 ret = mcde_display_init(drm); 197 if (ret) { 198 dev_err(drm->dev, "failed to init display\n"); 199 goto out_config; 200 } 201 202 /* 203 * Attach the DSI bridge 204 * 205 * TODO: when adding support for the DPI bridge or several DSI bridges, 206 * we selectively connect the bridge(s) here instead of this simple 207 * attachment. 208 */ 209 ret = drm_simple_display_pipe_attach_bridge(&mcde->pipe, 210 mcde->bridge); 211 if (ret) { 212 dev_err(drm->dev, "failed to attach display output bridge\n"); 213 goto out_config; 214 } 215 216 drm_mode_config_reset(drm); 217 drm_kms_helper_poll_init(drm); 218 drm_fbdev_generic_setup(drm, 32); 219 220 return 0; 221 222 out_config: 223 drm_mode_config_cleanup(drm); 224 return ret; 225 } 226 227 static void mcde_release(struct drm_device *drm) 228 { 229 struct mcde *mcde = drm->dev_private; 230 231 drm_mode_config_cleanup(drm); 232 drm_dev_fini(drm); 233 kfree(mcde); 234 } 235 236 DEFINE_DRM_GEM_CMA_FOPS(drm_fops); 237 238 static struct drm_driver mcde_drm_driver = { 239 .driver_features = 240 DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, 241 .release = mcde_release, 242 .lastclose = drm_fb_helper_lastclose, 243 .ioctls = NULL, 244 .fops = &drm_fops, 245 .name = "mcde", 246 .desc = DRIVER_DESC, 247 .date = "20180529", 248 .major = 1, 249 .minor = 0, 250 .patchlevel = 0, 251 .dumb_create = drm_gem_cma_dumb_create, 252 .gem_free_object_unlocked = drm_gem_cma_free_object, 253 .gem_vm_ops = &drm_gem_cma_vm_ops, 254 255 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 256 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 257 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, 258 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, 259 .gem_prime_vmap = drm_gem_cma_prime_vmap, 260 .gem_prime_vunmap = drm_gem_cma_prime_vunmap, 261 .gem_prime_mmap = drm_gem_cma_prime_mmap, 262 }; 263 264 static int mcde_drm_bind(struct device *dev) 265 { 266 struct drm_device *drm = dev_get_drvdata(dev); 267 int ret; 268 269 drm_mode_config_init(drm); 270 271 ret = component_bind_all(drm->dev, drm); 272 if (ret) { 273 dev_err(dev, "can't bind component devices\n"); 274 return ret; 275 } 276 277 ret = mcde_modeset_init(drm); 278 if (ret) 279 goto unbind; 280 281 ret = drm_dev_register(drm, 0); 282 if (ret < 0) 283 goto unbind; 284 285 return 0; 286 287 unbind: 288 component_unbind_all(drm->dev, drm); 289 return ret; 290 } 291 292 static void mcde_drm_unbind(struct device *dev) 293 { 294 struct drm_device *drm = dev_get_drvdata(dev); 295 296 drm_dev_unregister(drm); 297 drm_atomic_helper_shutdown(drm); 298 component_unbind_all(drm->dev, drm); 299 } 300 301 static const struct component_master_ops mcde_drm_comp_ops = { 302 .bind = mcde_drm_bind, 303 .unbind = mcde_drm_unbind, 304 }; 305 306 static struct platform_driver *const mcde_component_drivers[] = { 307 &mcde_dsi_driver, 308 }; 309 310 static int mcde_compare_dev(struct device *dev, void *data) 311 { 312 return dev == data; 313 } 314 315 static int mcde_probe(struct platform_device *pdev) 316 { 317 struct device *dev = &pdev->dev; 318 struct drm_device *drm; 319 struct mcde *mcde; 320 struct component_match *match = NULL; 321 struct resource *res; 322 u32 pid; 323 u32 val; 324 int irq; 325 int ret; 326 int i; 327 328 mcde = kzalloc(sizeof(*mcde), GFP_KERNEL); 329 if (!mcde) 330 return -ENOMEM; 331 mcde->dev = dev; 332 333 ret = drm_dev_init(&mcde->drm, &mcde_drm_driver, dev); 334 if (ret) { 335 kfree(mcde); 336 return ret; 337 } 338 drm = &mcde->drm; 339 drm->dev_private = mcde; 340 platform_set_drvdata(pdev, drm); 341 342 /* Enable use of the TE signal and interrupt */ 343 mcde->te_sync = true; 344 /* Enable continuous updates: this is what Linux' framebuffer expects */ 345 mcde->oneshot_mode = false; 346 drm->dev_private = mcde; 347 348 /* First obtain and turn on the main power */ 349 mcde->epod = devm_regulator_get(dev, "epod"); 350 if (IS_ERR(mcde->epod)) { 351 ret = PTR_ERR(mcde->epod); 352 dev_err(dev, "can't get EPOD regulator\n"); 353 goto dev_unref; 354 } 355 ret = regulator_enable(mcde->epod); 356 if (ret) { 357 dev_err(dev, "can't enable EPOD regulator\n"); 358 goto dev_unref; 359 } 360 mcde->vana = devm_regulator_get(dev, "vana"); 361 if (IS_ERR(mcde->vana)) { 362 ret = PTR_ERR(mcde->vana); 363 dev_err(dev, "can't get VANA regulator\n"); 364 goto regulator_epod_off; 365 } 366 ret = regulator_enable(mcde->vana); 367 if (ret) { 368 dev_err(dev, "can't enable VANA regulator\n"); 369 goto regulator_epod_off; 370 } 371 /* 372 * The vendor code uses ESRAM (onchip RAM) and need to activate 373 * the v-esram34 regulator, but we don't use that yet 374 */ 375 376 /* Clock the silicon so we can access the registers */ 377 mcde->mcde_clk = devm_clk_get(dev, "mcde"); 378 if (IS_ERR(mcde->mcde_clk)) { 379 dev_err(dev, "unable to get MCDE main clock\n"); 380 ret = PTR_ERR(mcde->mcde_clk); 381 goto regulator_off; 382 } 383 ret = clk_prepare_enable(mcde->mcde_clk); 384 if (ret) { 385 dev_err(dev, "failed to enable MCDE main clock\n"); 386 goto regulator_off; 387 } 388 dev_info(dev, "MCDE clk rate %lu Hz\n", clk_get_rate(mcde->mcde_clk)); 389 390 mcde->lcd_clk = devm_clk_get(dev, "lcd"); 391 if (IS_ERR(mcde->lcd_clk)) { 392 dev_err(dev, "unable to get LCD clock\n"); 393 ret = PTR_ERR(mcde->lcd_clk); 394 goto clk_disable; 395 } 396 mcde->hdmi_clk = devm_clk_get(dev, "hdmi"); 397 if (IS_ERR(mcde->hdmi_clk)) { 398 dev_err(dev, "unable to get HDMI clock\n"); 399 ret = PTR_ERR(mcde->hdmi_clk); 400 goto clk_disable; 401 } 402 403 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 404 mcde->regs = devm_ioremap_resource(dev, res); 405 if (IS_ERR(mcde->regs)) { 406 dev_err(dev, "no MCDE regs\n"); 407 ret = -EINVAL; 408 goto clk_disable; 409 } 410 411 irq = platform_get_irq(pdev, 0); 412 if (!irq) { 413 ret = -EINVAL; 414 goto clk_disable; 415 } 416 417 ret = devm_request_irq(dev, irq, mcde_irq, 0, "mcde", mcde); 418 if (ret) { 419 dev_err(dev, "failed to request irq %d\n", ret); 420 goto clk_disable; 421 } 422 423 /* 424 * Check hardware revision, we only support U8500v2 version 425 * as this was the only version used for mass market deployment, 426 * but surely you can add more versions if you have them and 427 * need them. 428 */ 429 pid = readl(mcde->regs + MCDE_PID); 430 dev_info(dev, "found MCDE HW revision %d.%d (dev %d, metal fix %d)\n", 431 (pid & MCDE_PID_MAJOR_VERSION_MASK) 432 >> MCDE_PID_MAJOR_VERSION_SHIFT, 433 (pid & MCDE_PID_MINOR_VERSION_MASK) 434 >> MCDE_PID_MINOR_VERSION_SHIFT, 435 (pid & MCDE_PID_DEVELOPMENT_VERSION_MASK) 436 >> MCDE_PID_DEVELOPMENT_VERSION_SHIFT, 437 (pid & MCDE_PID_METALFIX_VERSION_MASK) 438 >> MCDE_PID_METALFIX_VERSION_SHIFT); 439 if (pid != 0x03000800) { 440 dev_err(dev, "unsupported hardware revision\n"); 441 ret = -ENODEV; 442 goto clk_disable; 443 } 444 445 /* Set up the main control, watermark level at 7 */ 446 val = 7 << MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT; 447 /* 24 bits DPI: connect LSB Ch B to D[0:7] */ 448 val |= 3 << MCDE_CONF0_OUTMUX0_SHIFT; 449 /* TV out: connect LSB Ch B to D[8:15] */ 450 val |= 3 << MCDE_CONF0_OUTMUX1_SHIFT; 451 /* Don't care about this muxing */ 452 val |= 0 << MCDE_CONF0_OUTMUX2_SHIFT; 453 /* 24 bits DPI: connect MID Ch B to D[24:31] */ 454 val |= 4 << MCDE_CONF0_OUTMUX3_SHIFT; 455 /* 5: 24 bits DPI: connect MSB Ch B to D[32:39] */ 456 val |= 5 << MCDE_CONF0_OUTMUX4_SHIFT; 457 /* Syncmux bits zero: DPI channel A and B on output pins A and B resp */ 458 writel(val, mcde->regs + MCDE_CONF0); 459 460 /* Enable automatic clock gating */ 461 val = readl(mcde->regs + MCDE_CR); 462 val |= MCDE_CR_MCDEEN | MCDE_CR_AUTOCLKG_EN; 463 writel(val, mcde->regs + MCDE_CR); 464 465 /* Clear any pending interrupts */ 466 mcde_display_disable_irqs(mcde); 467 writel(0, mcde->regs + MCDE_IMSCERR); 468 writel(0xFFFFFFFF, mcde->regs + MCDE_RISERR); 469 470 /* Spawn child devices for the DSI ports */ 471 devm_of_platform_populate(dev); 472 473 /* Create something that will match the subdrivers when we bind */ 474 for (i = 0; i < ARRAY_SIZE(mcde_component_drivers); i++) { 475 struct device_driver *drv = &mcde_component_drivers[i]->driver; 476 struct device *p = NULL, *d; 477 478 while ((d = platform_find_device_by_driver(p, drv))) { 479 put_device(p); 480 component_match_add(dev, &match, mcde_compare_dev, d); 481 p = d; 482 } 483 put_device(p); 484 } 485 if (!match) { 486 dev_err(dev, "no matching components\n"); 487 return -ENODEV; 488 } 489 if (IS_ERR(match)) { 490 dev_err(dev, "could not create component match\n"); 491 ret = PTR_ERR(match); 492 goto clk_disable; 493 } 494 ret = component_master_add_with_match(&pdev->dev, &mcde_drm_comp_ops, 495 match); 496 if (ret) { 497 dev_err(dev, "failed to add component master\n"); 498 goto clk_disable; 499 } 500 return 0; 501 502 clk_disable: 503 clk_disable_unprepare(mcde->mcde_clk); 504 regulator_off: 505 regulator_disable(mcde->vana); 506 regulator_epod_off: 507 regulator_disable(mcde->epod); 508 dev_unref: 509 drm_dev_put(drm); 510 return ret; 511 512 } 513 514 static int mcde_remove(struct platform_device *pdev) 515 { 516 struct drm_device *drm = platform_get_drvdata(pdev); 517 struct mcde *mcde = drm->dev_private; 518 519 component_master_del(&pdev->dev, &mcde_drm_comp_ops); 520 clk_disable_unprepare(mcde->mcde_clk); 521 regulator_disable(mcde->vana); 522 regulator_disable(mcde->epod); 523 drm_dev_put(drm); 524 525 return 0; 526 } 527 528 static const struct of_device_id mcde_of_match[] = { 529 { 530 .compatible = "ste,mcde", 531 }, 532 {}, 533 }; 534 535 static struct platform_driver mcde_driver = { 536 .driver = { 537 .name = "mcde", 538 .of_match_table = of_match_ptr(mcde_of_match), 539 }, 540 .probe = mcde_probe, 541 .remove = mcde_remove, 542 }; 543 544 static struct platform_driver *const component_drivers[] = { 545 &mcde_dsi_driver, 546 }; 547 548 static int __init mcde_drm_register(void) 549 { 550 int ret; 551 552 ret = platform_register_drivers(component_drivers, 553 ARRAY_SIZE(component_drivers)); 554 if (ret) 555 return ret; 556 557 return platform_driver_register(&mcde_driver); 558 } 559 560 static void __exit mcde_drm_unregister(void) 561 { 562 platform_unregister_drivers(component_drivers, 563 ARRAY_SIZE(component_drivers)); 564 platform_driver_unregister(&mcde_driver); 565 } 566 567 module_init(mcde_drm_register); 568 module_exit(mcde_drm_unregister); 569 570 MODULE_ALIAS("platform:mcde-drm"); 571 MODULE_DESCRIPTION(DRIVER_DESC); 572 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); 573 MODULE_LICENSE("GPL"); 574