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