1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd 4 * Author:Mark Yao <mark.yao@rock-chips.com> 5 * 6 * based on exynos_drm_drv.c 7 */ 8 9 #include <linux/dma-mapping.h> 10 #include <linux/platform_device.h> 11 #include <linux/pm_runtime.h> 12 #include <linux/module.h> 13 #include <linux/of_graph.h> 14 #include <linux/of_platform.h> 15 #include <linux/component.h> 16 #include <linux/console.h> 17 #include <linux/iommu.h> 18 19 #include <drm/drm_aperture.h> 20 #include <drm/drm_drv.h> 21 #include <drm/drm_fbdev_dma.h> 22 #include <drm/drm_gem_dma_helper.h> 23 #include <drm/drm_of.h> 24 #include <drm/drm_probe_helper.h> 25 #include <drm/drm_vblank.h> 26 27 #if defined(CONFIG_ARM_DMA_USE_IOMMU) 28 #include <asm/dma-iommu.h> 29 #else 30 #define arm_iommu_detach_device(...) ({ }) 31 #define arm_iommu_release_mapping(...) ({ }) 32 #define to_dma_iommu_mapping(dev) NULL 33 #endif 34 35 #include "rockchip_drm_drv.h" 36 #include "rockchip_drm_fb.h" 37 #include "rockchip_drm_gem.h" 38 39 #define DRIVER_NAME "rockchip" 40 #define DRIVER_DESC "RockChip Soc DRM" 41 #define DRIVER_DATE "20140818" 42 #define DRIVER_MAJOR 1 43 #define DRIVER_MINOR 0 44 45 static const struct drm_driver rockchip_drm_driver; 46 47 /* 48 * Attach a (component) device to the shared drm dma mapping from master drm 49 * device. This is used by the VOPs to map GEM buffers to a common DMA 50 * mapping. 51 */ 52 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, 53 struct device *dev) 54 { 55 struct rockchip_drm_private *private = drm_dev->dev_private; 56 int ret; 57 58 if (!private->domain) 59 return 0; 60 61 if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) { 62 struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev); 63 64 if (mapping) { 65 arm_iommu_detach_device(dev); 66 arm_iommu_release_mapping(mapping); 67 } 68 } 69 70 ret = iommu_attach_device(private->domain, dev); 71 if (ret) { 72 DRM_DEV_ERROR(dev, "Failed to attach iommu device\n"); 73 return ret; 74 } 75 76 return 0; 77 } 78 79 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, 80 struct device *dev) 81 { 82 struct rockchip_drm_private *private = drm_dev->dev_private; 83 84 if (!private->domain) 85 return; 86 87 iommu_detach_device(private->domain, dev); 88 } 89 90 void rockchip_drm_dma_init_device(struct drm_device *drm_dev, 91 struct device *dev) 92 { 93 struct rockchip_drm_private *private = drm_dev->dev_private; 94 95 if (!device_iommu_mapped(dev)) 96 private->iommu_dev = ERR_PTR(-ENODEV); 97 else if (!private->iommu_dev) 98 private->iommu_dev = dev; 99 } 100 101 static int rockchip_drm_init_iommu(struct drm_device *drm_dev) 102 { 103 struct rockchip_drm_private *private = drm_dev->dev_private; 104 struct iommu_domain_geometry *geometry; 105 u64 start, end; 106 107 if (IS_ERR_OR_NULL(private->iommu_dev)) 108 return 0; 109 110 private->domain = iommu_domain_alloc(private->iommu_dev->bus); 111 if (!private->domain) 112 return -ENOMEM; 113 114 geometry = &private->domain->geometry; 115 start = geometry->aperture_start; 116 end = geometry->aperture_end; 117 118 DRM_DEBUG("IOMMU context initialized (aperture: %#llx-%#llx)\n", 119 start, end); 120 drm_mm_init(&private->mm, start, end - start + 1); 121 mutex_init(&private->mm_lock); 122 123 return 0; 124 } 125 126 static void rockchip_iommu_cleanup(struct drm_device *drm_dev) 127 { 128 struct rockchip_drm_private *private = drm_dev->dev_private; 129 130 if (!private->domain) 131 return; 132 133 drm_mm_takedown(&private->mm); 134 iommu_domain_free(private->domain); 135 } 136 137 static int rockchip_drm_bind(struct device *dev) 138 { 139 struct drm_device *drm_dev; 140 struct rockchip_drm_private *private; 141 int ret; 142 143 /* Remove existing drivers that may own the framebuffer memory. */ 144 ret = drm_aperture_remove_framebuffers(&rockchip_drm_driver); 145 if (ret) { 146 DRM_DEV_ERROR(dev, 147 "Failed to remove existing framebuffers - %d.\n", 148 ret); 149 return ret; 150 } 151 152 drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev); 153 if (IS_ERR(drm_dev)) 154 return PTR_ERR(drm_dev); 155 156 dev_set_drvdata(dev, drm_dev); 157 158 private = devm_kzalloc(drm_dev->dev, sizeof(*private), GFP_KERNEL); 159 if (!private) { 160 ret = -ENOMEM; 161 goto err_free; 162 } 163 164 drm_dev->dev_private = private; 165 166 ret = drmm_mode_config_init(drm_dev); 167 if (ret) 168 goto err_free; 169 170 rockchip_drm_mode_config_init(drm_dev); 171 172 /* Try to bind all sub drivers. */ 173 ret = component_bind_all(dev, drm_dev); 174 if (ret) 175 goto err_free; 176 177 ret = rockchip_drm_init_iommu(drm_dev); 178 if (ret) 179 goto err_unbind_all; 180 181 ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc); 182 if (ret) 183 goto err_iommu_cleanup; 184 185 drm_mode_config_reset(drm_dev); 186 187 /* init kms poll for handling hpd */ 188 drm_kms_helper_poll_init(drm_dev); 189 190 ret = drm_dev_register(drm_dev, 0); 191 if (ret) 192 goto err_kms_helper_poll_fini; 193 194 drm_fbdev_dma_setup(drm_dev, 0); 195 196 return 0; 197 err_kms_helper_poll_fini: 198 drm_kms_helper_poll_fini(drm_dev); 199 err_iommu_cleanup: 200 rockchip_iommu_cleanup(drm_dev); 201 err_unbind_all: 202 component_unbind_all(dev, drm_dev); 203 err_free: 204 drm_dev_put(drm_dev); 205 return ret; 206 } 207 208 static void rockchip_drm_unbind(struct device *dev) 209 { 210 struct drm_device *drm_dev = dev_get_drvdata(dev); 211 212 drm_dev_unregister(drm_dev); 213 214 drm_kms_helper_poll_fini(drm_dev); 215 216 drm_atomic_helper_shutdown(drm_dev); 217 component_unbind_all(dev, drm_dev); 218 rockchip_iommu_cleanup(drm_dev); 219 220 drm_dev_put(drm_dev); 221 } 222 223 DEFINE_DRM_GEM_FOPS(rockchip_drm_driver_fops); 224 225 static const struct drm_driver rockchip_drm_driver = { 226 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, 227 .dumb_create = rockchip_gem_dumb_create, 228 .gem_prime_import_sg_table = rockchip_gem_prime_import_sg_table, 229 .fops = &rockchip_drm_driver_fops, 230 .name = DRIVER_NAME, 231 .desc = DRIVER_DESC, 232 .date = DRIVER_DATE, 233 .major = DRIVER_MAJOR, 234 .minor = DRIVER_MINOR, 235 }; 236 237 #ifdef CONFIG_PM_SLEEP 238 static int rockchip_drm_sys_suspend(struct device *dev) 239 { 240 struct drm_device *drm = dev_get_drvdata(dev); 241 242 return drm_mode_config_helper_suspend(drm); 243 } 244 245 static int rockchip_drm_sys_resume(struct device *dev) 246 { 247 struct drm_device *drm = dev_get_drvdata(dev); 248 249 return drm_mode_config_helper_resume(drm); 250 } 251 #endif 252 253 static const struct dev_pm_ops rockchip_drm_pm_ops = { 254 SET_SYSTEM_SLEEP_PM_OPS(rockchip_drm_sys_suspend, 255 rockchip_drm_sys_resume) 256 }; 257 258 #define MAX_ROCKCHIP_SUB_DRIVERS 16 259 static struct platform_driver *rockchip_sub_drivers[MAX_ROCKCHIP_SUB_DRIVERS]; 260 static int num_rockchip_sub_drivers; 261 262 /* 263 * Get the endpoint id of the remote endpoint of the given encoder. This 264 * information is used by the VOP2 driver to identify the encoder. 265 * 266 * @rkencoder: The encoder to get the remote endpoint id from 267 * @np: The encoder device node 268 * @port: The number of the port leading to the VOP2 269 * @reg: The endpoint number leading to the VOP2 270 */ 271 int rockchip_drm_encoder_set_crtc_endpoint_id(struct rockchip_encoder *rkencoder, 272 struct device_node *np, int port, int reg) 273 { 274 struct of_endpoint ep; 275 struct device_node *en, *ren; 276 int ret; 277 278 en = of_graph_get_endpoint_by_regs(np, port, reg); 279 if (!en) 280 return -ENOENT; 281 282 ren = of_graph_get_remote_endpoint(en); 283 if (!ren) 284 return -ENOENT; 285 286 ret = of_graph_parse_endpoint(ren, &ep); 287 if (ret) 288 return ret; 289 290 rkencoder->crtc_endpoint_id = ep.id; 291 292 return 0; 293 } 294 295 /* 296 * Check if a vop endpoint is leading to a rockchip subdriver or bridge. 297 * Should be called from the component bind stage of the drivers 298 * to ensure that all subdrivers are probed. 299 * 300 * @ep: endpoint of a rockchip vop 301 * 302 * returns true if subdriver, false if external bridge and -ENODEV 303 * if remote port does not contain a device. 304 */ 305 int rockchip_drm_endpoint_is_subdriver(struct device_node *ep) 306 { 307 struct device_node *node = of_graph_get_remote_port_parent(ep); 308 struct platform_device *pdev; 309 struct device_driver *drv; 310 int i; 311 312 if (!node) 313 return -ENODEV; 314 315 /* status disabled will prevent creation of platform-devices */ 316 if (!of_device_is_available(node)) { 317 of_node_put(node); 318 return -ENODEV; 319 } 320 321 pdev = of_find_device_by_node(node); 322 of_node_put(node); 323 324 /* enabled non-platform-devices can immediately return here */ 325 if (!pdev) 326 return false; 327 328 /* 329 * All rockchip subdrivers have probed at this point, so 330 * any device not having a driver now is an external bridge. 331 */ 332 drv = pdev->dev.driver; 333 if (!drv) { 334 platform_device_put(pdev); 335 return false; 336 } 337 338 for (i = 0; i < num_rockchip_sub_drivers; i++) { 339 if (rockchip_sub_drivers[i] == to_platform_driver(drv)) { 340 platform_device_put(pdev); 341 return true; 342 } 343 } 344 345 platform_device_put(pdev); 346 return false; 347 } 348 349 static void rockchip_drm_match_remove(struct device *dev) 350 { 351 struct device_link *link; 352 353 list_for_each_entry(link, &dev->links.consumers, s_node) 354 device_link_del(link); 355 } 356 357 /* list of preferred vop devices */ 358 static const char *const rockchip_drm_match_preferred[] = { 359 "rockchip,rk3399-vop-big", 360 NULL, 361 }; 362 363 static struct component_match *rockchip_drm_match_add(struct device *dev) 364 { 365 struct component_match *match = NULL; 366 struct device_node *port; 367 int i; 368 369 /* add preferred vop device match before adding driver device matches */ 370 for (i = 0; ; i++) { 371 port = of_parse_phandle(dev->of_node, "ports", i); 372 if (!port) 373 break; 374 375 if (of_device_is_available(port->parent) && 376 of_device_compatible_match(port->parent, 377 rockchip_drm_match_preferred)) 378 drm_of_component_match_add(dev, &match, 379 component_compare_of, 380 port->parent); 381 382 of_node_put(port); 383 } 384 385 for (i = 0; i < num_rockchip_sub_drivers; i++) { 386 struct platform_driver *drv = rockchip_sub_drivers[i]; 387 struct device *p = NULL, *d; 388 389 do { 390 d = platform_find_device_by_driver(p, &drv->driver); 391 put_device(p); 392 p = d; 393 394 if (!d) 395 break; 396 397 device_link_add(dev, d, DL_FLAG_STATELESS); 398 component_match_add(dev, &match, component_compare_dev, d); 399 } while (true); 400 } 401 402 if (IS_ERR(match)) 403 rockchip_drm_match_remove(dev); 404 405 return match ?: ERR_PTR(-ENODEV); 406 } 407 408 static const struct component_master_ops rockchip_drm_ops = { 409 .bind = rockchip_drm_bind, 410 .unbind = rockchip_drm_unbind, 411 }; 412 413 static int rockchip_drm_platform_of_probe(struct device *dev) 414 { 415 struct device_node *np = dev->of_node; 416 struct device_node *port; 417 bool found = false; 418 int i; 419 420 if (!np) 421 return -ENODEV; 422 423 for (i = 0;; i++) { 424 port = of_parse_phandle(np, "ports", i); 425 if (!port) 426 break; 427 428 if (!of_device_is_available(port->parent)) { 429 of_node_put(port); 430 continue; 431 } 432 433 found = true; 434 of_node_put(port); 435 } 436 437 if (i == 0) { 438 DRM_DEV_ERROR(dev, "missing 'ports' property\n"); 439 return -ENODEV; 440 } 441 442 if (!found) { 443 DRM_DEV_ERROR(dev, 444 "No available vop found for display-subsystem.\n"); 445 return -ENODEV; 446 } 447 448 return 0; 449 } 450 451 static int rockchip_drm_platform_probe(struct platform_device *pdev) 452 { 453 struct device *dev = &pdev->dev; 454 struct component_match *match = NULL; 455 int ret; 456 457 ret = rockchip_drm_platform_of_probe(dev); 458 if (ret) 459 return ret; 460 461 match = rockchip_drm_match_add(dev); 462 if (IS_ERR(match)) 463 return PTR_ERR(match); 464 465 ret = component_master_add_with_match(dev, &rockchip_drm_ops, match); 466 if (ret < 0) { 467 rockchip_drm_match_remove(dev); 468 return ret; 469 } 470 471 return 0; 472 } 473 474 static void rockchip_drm_platform_remove(struct platform_device *pdev) 475 { 476 component_master_del(&pdev->dev, &rockchip_drm_ops); 477 478 rockchip_drm_match_remove(&pdev->dev); 479 } 480 481 static void rockchip_drm_platform_shutdown(struct platform_device *pdev) 482 { 483 struct drm_device *drm = platform_get_drvdata(pdev); 484 485 if (drm) 486 drm_atomic_helper_shutdown(drm); 487 } 488 489 static const struct of_device_id rockchip_drm_dt_ids[] = { 490 { .compatible = "rockchip,display-subsystem", }, 491 { /* sentinel */ }, 492 }; 493 MODULE_DEVICE_TABLE(of, rockchip_drm_dt_ids); 494 495 static struct platform_driver rockchip_drm_platform_driver = { 496 .probe = rockchip_drm_platform_probe, 497 .remove_new = rockchip_drm_platform_remove, 498 .shutdown = rockchip_drm_platform_shutdown, 499 .driver = { 500 .name = "rockchip-drm", 501 .of_match_table = rockchip_drm_dt_ids, 502 .pm = &rockchip_drm_pm_ops, 503 }, 504 }; 505 506 #define ADD_ROCKCHIP_SUB_DRIVER(drv, cond) { \ 507 if (IS_ENABLED(cond) && \ 508 !WARN_ON(num_rockchip_sub_drivers >= MAX_ROCKCHIP_SUB_DRIVERS)) \ 509 rockchip_sub_drivers[num_rockchip_sub_drivers++] = &drv; \ 510 } 511 512 static int __init rockchip_drm_init(void) 513 { 514 int ret; 515 516 if (drm_firmware_drivers_only()) 517 return -ENODEV; 518 519 num_rockchip_sub_drivers = 0; 520 ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP); 521 ADD_ROCKCHIP_SUB_DRIVER(vop2_platform_driver, CONFIG_ROCKCHIP_VOP2); 522 ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver, 523 CONFIG_ROCKCHIP_LVDS); 524 ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver, 525 CONFIG_ROCKCHIP_ANALOGIX_DP); 526 ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP); 527 ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver, 528 CONFIG_ROCKCHIP_DW_HDMI); 529 ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_rockchip_driver, 530 CONFIG_ROCKCHIP_DW_MIPI_DSI); 531 ADD_ROCKCHIP_SUB_DRIVER(inno_hdmi_driver, CONFIG_ROCKCHIP_INNO_HDMI); 532 ADD_ROCKCHIP_SUB_DRIVER(rk3066_hdmi_driver, 533 CONFIG_ROCKCHIP_RK3066_HDMI); 534 535 ret = platform_register_drivers(rockchip_sub_drivers, 536 num_rockchip_sub_drivers); 537 if (ret) 538 return ret; 539 540 ret = platform_driver_register(&rockchip_drm_platform_driver); 541 if (ret) 542 goto err_unreg_drivers; 543 544 return 0; 545 546 err_unreg_drivers: 547 platform_unregister_drivers(rockchip_sub_drivers, 548 num_rockchip_sub_drivers); 549 return ret; 550 } 551 552 static void __exit rockchip_drm_fini(void) 553 { 554 platform_driver_unregister(&rockchip_drm_platform_driver); 555 556 platform_unregister_drivers(rockchip_sub_drivers, 557 num_rockchip_sub_drivers); 558 } 559 560 module_init(rockchip_drm_init); 561 module_exit(rockchip_drm_fini); 562 563 MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>"); 564 MODULE_DESCRIPTION("ROCKCHIP DRM Driver"); 565 MODULE_LICENSE("GPL v2"); 566