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 ret = drm_vblank_init(drm, 1); 183 if (ret) { 184 dev_err(drm->dev, "failed to init vblank\n"); 185 goto out_config; 186 } 187 188 ret = mcde_display_init(drm); 189 if (ret) { 190 dev_err(drm->dev, "failed to init display\n"); 191 goto out_config; 192 } 193 194 /* 195 * Attach the DSI bridge 196 * 197 * TODO: when adding support for the DPI bridge or several DSI bridges, 198 * we selectively connect the bridge(s) here instead of this simple 199 * attachment. 200 */ 201 ret = drm_simple_display_pipe_attach_bridge(&mcde->pipe, 202 mcde->bridge); 203 if (ret) { 204 dev_err(drm->dev, "failed to attach display output bridge\n"); 205 goto out_config; 206 } 207 208 drm_mode_config_reset(drm); 209 drm_kms_helper_poll_init(drm); 210 drm_fbdev_generic_setup(drm, 32); 211 212 return 0; 213 214 out_config: 215 drm_mode_config_cleanup(drm); 216 return ret; 217 } 218 219 static void mcde_release(struct drm_device *drm) 220 { 221 struct mcde *mcde = drm->dev_private; 222 223 drm_mode_config_cleanup(drm); 224 drm_dev_fini(drm); 225 kfree(mcde); 226 } 227 228 DEFINE_DRM_GEM_CMA_FOPS(drm_fops); 229 230 static struct drm_driver mcde_drm_driver = { 231 .driver_features = 232 DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, 233 .release = mcde_release, 234 .lastclose = drm_fb_helper_lastclose, 235 .ioctls = NULL, 236 .fops = &drm_fops, 237 .name = "mcde", 238 .desc = DRIVER_DESC, 239 .date = "20180529", 240 .major = 1, 241 .minor = 0, 242 .patchlevel = 0, 243 .dumb_create = drm_gem_cma_dumb_create, 244 .gem_free_object_unlocked = drm_gem_cma_free_object, 245 .gem_vm_ops = &drm_gem_cma_vm_ops, 246 247 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 248 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 249 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, 250 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, 251 .gem_prime_vmap = drm_gem_cma_prime_vmap, 252 .gem_prime_vunmap = drm_gem_cma_prime_vunmap, 253 .gem_prime_mmap = drm_gem_cma_prime_mmap, 254 }; 255 256 static int mcde_drm_bind(struct device *dev) 257 { 258 struct drm_device *drm = dev_get_drvdata(dev); 259 int ret; 260 261 drm_mode_config_init(drm); 262 263 ret = component_bind_all(drm->dev, drm); 264 if (ret) { 265 dev_err(dev, "can't bind component devices\n"); 266 return ret; 267 } 268 269 ret = mcde_modeset_init(drm); 270 if (ret) 271 goto unbind; 272 273 ret = drm_dev_register(drm, 0); 274 if (ret < 0) 275 goto unbind; 276 277 return 0; 278 279 unbind: 280 component_unbind_all(drm->dev, drm); 281 return ret; 282 } 283 284 static void mcde_drm_unbind(struct device *dev) 285 { 286 struct drm_device *drm = dev_get_drvdata(dev); 287 288 drm_dev_unregister(drm); 289 drm_atomic_helper_shutdown(drm); 290 component_unbind_all(drm->dev, drm); 291 } 292 293 static const struct component_master_ops mcde_drm_comp_ops = { 294 .bind = mcde_drm_bind, 295 .unbind = mcde_drm_unbind, 296 }; 297 298 static struct platform_driver *const mcde_component_drivers[] = { 299 &mcde_dsi_driver, 300 }; 301 302 static int mcde_compare_dev(struct device *dev, void *data) 303 { 304 return dev == data; 305 } 306 307 static int mcde_probe(struct platform_device *pdev) 308 { 309 struct device *dev = &pdev->dev; 310 struct drm_device *drm; 311 struct mcde *mcde; 312 struct component_match *match = NULL; 313 struct resource *res; 314 u32 pid; 315 u32 val; 316 int irq; 317 int ret; 318 int i; 319 320 mcde = kzalloc(sizeof(*mcde), GFP_KERNEL); 321 if (!mcde) 322 return -ENOMEM; 323 mcde->dev = dev; 324 325 ret = drm_dev_init(&mcde->drm, &mcde_drm_driver, dev); 326 if (ret) { 327 kfree(mcde); 328 return ret; 329 } 330 drm = &mcde->drm; 331 drm->dev_private = mcde; 332 platform_set_drvdata(pdev, drm); 333 334 /* Enable continuous updates: this is what Linux' framebuffer expects */ 335 mcde->oneshot_mode = false; 336 drm->dev_private = mcde; 337 338 /* First obtain and turn on the main power */ 339 mcde->epod = devm_regulator_get(dev, "epod"); 340 if (IS_ERR(mcde->epod)) { 341 ret = PTR_ERR(mcde->epod); 342 dev_err(dev, "can't get EPOD regulator\n"); 343 goto dev_unref; 344 } 345 ret = regulator_enable(mcde->epod); 346 if (ret) { 347 dev_err(dev, "can't enable EPOD regulator\n"); 348 goto dev_unref; 349 } 350 mcde->vana = devm_regulator_get(dev, "vana"); 351 if (IS_ERR(mcde->vana)) { 352 ret = PTR_ERR(mcde->vana); 353 dev_err(dev, "can't get VANA regulator\n"); 354 goto regulator_epod_off; 355 } 356 ret = regulator_enable(mcde->vana); 357 if (ret) { 358 dev_err(dev, "can't enable VANA regulator\n"); 359 goto regulator_epod_off; 360 } 361 /* 362 * The vendor code uses ESRAM (onchip RAM) and need to activate 363 * the v-esram34 regulator, but we don't use that yet 364 */ 365 366 /* Clock the silicon so we can access the registers */ 367 mcde->mcde_clk = devm_clk_get(dev, "mcde"); 368 if (IS_ERR(mcde->mcde_clk)) { 369 dev_err(dev, "unable to get MCDE main clock\n"); 370 ret = PTR_ERR(mcde->mcde_clk); 371 goto regulator_off; 372 } 373 ret = clk_prepare_enable(mcde->mcde_clk); 374 if (ret) { 375 dev_err(dev, "failed to enable MCDE main clock\n"); 376 goto regulator_off; 377 } 378 dev_info(dev, "MCDE clk rate %lu Hz\n", clk_get_rate(mcde->mcde_clk)); 379 380 mcde->lcd_clk = devm_clk_get(dev, "lcd"); 381 if (IS_ERR(mcde->lcd_clk)) { 382 dev_err(dev, "unable to get LCD clock\n"); 383 ret = PTR_ERR(mcde->lcd_clk); 384 goto clk_disable; 385 } 386 mcde->hdmi_clk = devm_clk_get(dev, "hdmi"); 387 if (IS_ERR(mcde->hdmi_clk)) { 388 dev_err(dev, "unable to get HDMI clock\n"); 389 ret = PTR_ERR(mcde->hdmi_clk); 390 goto clk_disable; 391 } 392 393 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 394 mcde->regs = devm_ioremap_resource(dev, res); 395 if (IS_ERR(mcde->regs)) { 396 dev_err(dev, "no MCDE regs\n"); 397 ret = -EINVAL; 398 goto clk_disable; 399 } 400 401 irq = platform_get_irq(pdev, 0); 402 if (!irq) { 403 ret = -EINVAL; 404 goto clk_disable; 405 } 406 407 ret = devm_request_irq(dev, irq, mcde_irq, 0, "mcde", mcde); 408 if (ret) { 409 dev_err(dev, "failed to request irq %d\n", ret); 410 goto clk_disable; 411 } 412 413 /* 414 * Check hardware revision, we only support U8500v2 version 415 * as this was the only version used for mass market deployment, 416 * but surely you can add more versions if you have them and 417 * need them. 418 */ 419 pid = readl(mcde->regs + MCDE_PID); 420 dev_info(dev, "found MCDE HW revision %d.%d (dev %d, metal fix %d)\n", 421 (pid & MCDE_PID_MAJOR_VERSION_MASK) 422 >> MCDE_PID_MAJOR_VERSION_SHIFT, 423 (pid & MCDE_PID_MINOR_VERSION_MASK) 424 >> MCDE_PID_MINOR_VERSION_SHIFT, 425 (pid & MCDE_PID_DEVELOPMENT_VERSION_MASK) 426 >> MCDE_PID_DEVELOPMENT_VERSION_SHIFT, 427 (pid & MCDE_PID_METALFIX_VERSION_MASK) 428 >> MCDE_PID_METALFIX_VERSION_SHIFT); 429 if (pid != 0x03000800) { 430 dev_err(dev, "unsupported hardware revision\n"); 431 ret = -ENODEV; 432 goto clk_disable; 433 } 434 435 /* Set up the main control, watermark level at 7 */ 436 val = 7 << MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT; 437 /* 24 bits DPI: connect LSB Ch B to D[0:7] */ 438 val |= 3 << MCDE_CONF0_OUTMUX0_SHIFT; 439 /* TV out: connect LSB Ch B to D[8:15] */ 440 val |= 3 << MCDE_CONF0_OUTMUX1_SHIFT; 441 /* Don't care about this muxing */ 442 val |= 0 << MCDE_CONF0_OUTMUX2_SHIFT; 443 /* 24 bits DPI: connect MID Ch B to D[24:31] */ 444 val |= 4 << MCDE_CONF0_OUTMUX3_SHIFT; 445 /* 5: 24 bits DPI: connect MSB Ch B to D[32:39] */ 446 val |= 5 << MCDE_CONF0_OUTMUX4_SHIFT; 447 /* Syncmux bits zero: DPI channel A and B on output pins A and B resp */ 448 writel(val, mcde->regs + MCDE_CONF0); 449 450 /* Enable automatic clock gating */ 451 val = readl(mcde->regs + MCDE_CR); 452 val |= MCDE_CR_MCDEEN | MCDE_CR_AUTOCLKG_EN; 453 writel(val, mcde->regs + MCDE_CR); 454 455 /* Clear any pending interrupts */ 456 mcde_display_disable_irqs(mcde); 457 writel(0, mcde->regs + MCDE_IMSCERR); 458 writel(0xFFFFFFFF, mcde->regs + MCDE_RISERR); 459 460 /* Spawn child devices for the DSI ports */ 461 devm_of_platform_populate(dev); 462 463 /* Create something that will match the subdrivers when we bind */ 464 for (i = 0; i < ARRAY_SIZE(mcde_component_drivers); i++) { 465 struct device_driver *drv = &mcde_component_drivers[i]->driver; 466 struct device *p = NULL, *d; 467 468 while ((d = platform_find_device_by_driver(p, drv))) { 469 put_device(p); 470 component_match_add(dev, &match, mcde_compare_dev, d); 471 p = d; 472 } 473 put_device(p); 474 } 475 if (!match) { 476 dev_err(dev, "no matching components\n"); 477 ret = -ENODEV; 478 goto clk_disable; 479 } 480 if (IS_ERR(match)) { 481 dev_err(dev, "could not create component match\n"); 482 ret = PTR_ERR(match); 483 goto clk_disable; 484 } 485 ret = component_master_add_with_match(&pdev->dev, &mcde_drm_comp_ops, 486 match); 487 if (ret) { 488 dev_err(dev, "failed to add component master\n"); 489 goto clk_disable; 490 } 491 return 0; 492 493 clk_disable: 494 clk_disable_unprepare(mcde->mcde_clk); 495 regulator_off: 496 regulator_disable(mcde->vana); 497 regulator_epod_off: 498 regulator_disable(mcde->epod); 499 dev_unref: 500 drm_dev_put(drm); 501 return ret; 502 503 } 504 505 static int mcde_remove(struct platform_device *pdev) 506 { 507 struct drm_device *drm = platform_get_drvdata(pdev); 508 struct mcde *mcde = drm->dev_private; 509 510 component_master_del(&pdev->dev, &mcde_drm_comp_ops); 511 clk_disable_unprepare(mcde->mcde_clk); 512 regulator_disable(mcde->vana); 513 regulator_disable(mcde->epod); 514 drm_dev_put(drm); 515 516 return 0; 517 } 518 519 static const struct of_device_id mcde_of_match[] = { 520 { 521 .compatible = "ste,mcde", 522 }, 523 {}, 524 }; 525 526 static struct platform_driver mcde_driver = { 527 .driver = { 528 .name = "mcde", 529 .of_match_table = of_match_ptr(mcde_of_match), 530 }, 531 .probe = mcde_probe, 532 .remove = mcde_remove, 533 }; 534 535 static struct platform_driver *const component_drivers[] = { 536 &mcde_dsi_driver, 537 }; 538 539 static int __init mcde_drm_register(void) 540 { 541 int ret; 542 543 ret = platform_register_drivers(component_drivers, 544 ARRAY_SIZE(component_drivers)); 545 if (ret) 546 return ret; 547 548 return platform_driver_register(&mcde_driver); 549 } 550 551 static void __exit mcde_drm_unregister(void) 552 { 553 platform_unregister_drivers(component_drivers, 554 ARRAY_SIZE(component_drivers)); 555 platform_driver_unregister(&mcde_driver); 556 } 557 558 module_init(mcde_drm_register); 559 module_exit(mcde_drm_unregister); 560 561 MODULE_ALIAS("platform:mcde-drm"); 562 MODULE_DESCRIPTION(DRIVER_DESC); 563 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); 564 MODULE_LICENSE("GPL"); 565