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 static struct component_match *rockchip_drm_match_add(struct device *dev) 358 { 359 struct component_match *match = NULL; 360 int i; 361 362 for (i = 0; i < num_rockchip_sub_drivers; i++) { 363 struct platform_driver *drv = rockchip_sub_drivers[i]; 364 struct device *p = NULL, *d; 365 366 do { 367 d = platform_find_device_by_driver(p, &drv->driver); 368 put_device(p); 369 p = d; 370 371 if (!d) 372 break; 373 374 device_link_add(dev, d, DL_FLAG_STATELESS); 375 component_match_add(dev, &match, component_compare_dev, d); 376 } while (true); 377 } 378 379 if (IS_ERR(match)) 380 rockchip_drm_match_remove(dev); 381 382 return match ?: ERR_PTR(-ENODEV); 383 } 384 385 static const struct component_master_ops rockchip_drm_ops = { 386 .bind = rockchip_drm_bind, 387 .unbind = rockchip_drm_unbind, 388 }; 389 390 static int rockchip_drm_platform_of_probe(struct device *dev) 391 { 392 struct device_node *np = dev->of_node; 393 struct device_node *port; 394 bool found = false; 395 int i; 396 397 if (!np) 398 return -ENODEV; 399 400 for (i = 0;; i++) { 401 port = of_parse_phandle(np, "ports", i); 402 if (!port) 403 break; 404 405 if (!of_device_is_available(port->parent)) { 406 of_node_put(port); 407 continue; 408 } 409 410 found = true; 411 of_node_put(port); 412 } 413 414 if (i == 0) { 415 DRM_DEV_ERROR(dev, "missing 'ports' property\n"); 416 return -ENODEV; 417 } 418 419 if (!found) { 420 DRM_DEV_ERROR(dev, 421 "No available vop found for display-subsystem.\n"); 422 return -ENODEV; 423 } 424 425 return 0; 426 } 427 428 static int rockchip_drm_platform_probe(struct platform_device *pdev) 429 { 430 struct device *dev = &pdev->dev; 431 struct component_match *match = NULL; 432 int ret; 433 434 ret = rockchip_drm_platform_of_probe(dev); 435 if (ret) 436 return ret; 437 438 match = rockchip_drm_match_add(dev); 439 if (IS_ERR(match)) 440 return PTR_ERR(match); 441 442 ret = component_master_add_with_match(dev, &rockchip_drm_ops, match); 443 if (ret < 0) { 444 rockchip_drm_match_remove(dev); 445 return ret; 446 } 447 448 return 0; 449 } 450 451 static void rockchip_drm_platform_remove(struct platform_device *pdev) 452 { 453 component_master_del(&pdev->dev, &rockchip_drm_ops); 454 455 rockchip_drm_match_remove(&pdev->dev); 456 } 457 458 static void rockchip_drm_platform_shutdown(struct platform_device *pdev) 459 { 460 struct drm_device *drm = platform_get_drvdata(pdev); 461 462 if (drm) 463 drm_atomic_helper_shutdown(drm); 464 } 465 466 static const struct of_device_id rockchip_drm_dt_ids[] = { 467 { .compatible = "rockchip,display-subsystem", }, 468 { /* sentinel */ }, 469 }; 470 MODULE_DEVICE_TABLE(of, rockchip_drm_dt_ids); 471 472 static struct platform_driver rockchip_drm_platform_driver = { 473 .probe = rockchip_drm_platform_probe, 474 .remove_new = rockchip_drm_platform_remove, 475 .shutdown = rockchip_drm_platform_shutdown, 476 .driver = { 477 .name = "rockchip-drm", 478 .of_match_table = rockchip_drm_dt_ids, 479 .pm = &rockchip_drm_pm_ops, 480 }, 481 }; 482 483 #define ADD_ROCKCHIP_SUB_DRIVER(drv, cond) { \ 484 if (IS_ENABLED(cond) && \ 485 !WARN_ON(num_rockchip_sub_drivers >= MAX_ROCKCHIP_SUB_DRIVERS)) \ 486 rockchip_sub_drivers[num_rockchip_sub_drivers++] = &drv; \ 487 } 488 489 static int __init rockchip_drm_init(void) 490 { 491 int ret; 492 493 if (drm_firmware_drivers_only()) 494 return -ENODEV; 495 496 num_rockchip_sub_drivers = 0; 497 ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP); 498 ADD_ROCKCHIP_SUB_DRIVER(vop2_platform_driver, CONFIG_ROCKCHIP_VOP2); 499 ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver, 500 CONFIG_ROCKCHIP_LVDS); 501 ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver, 502 CONFIG_ROCKCHIP_ANALOGIX_DP); 503 ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP); 504 ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver, 505 CONFIG_ROCKCHIP_DW_HDMI); 506 ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_rockchip_driver, 507 CONFIG_ROCKCHIP_DW_MIPI_DSI); 508 ADD_ROCKCHIP_SUB_DRIVER(inno_hdmi_driver, CONFIG_ROCKCHIP_INNO_HDMI); 509 ADD_ROCKCHIP_SUB_DRIVER(rk3066_hdmi_driver, 510 CONFIG_ROCKCHIP_RK3066_HDMI); 511 512 ret = platform_register_drivers(rockchip_sub_drivers, 513 num_rockchip_sub_drivers); 514 if (ret) 515 return ret; 516 517 ret = platform_driver_register(&rockchip_drm_platform_driver); 518 if (ret) 519 goto err_unreg_drivers; 520 521 return 0; 522 523 err_unreg_drivers: 524 platform_unregister_drivers(rockchip_sub_drivers, 525 num_rockchip_sub_drivers); 526 return ret; 527 } 528 529 static void __exit rockchip_drm_fini(void) 530 { 531 platform_driver_unregister(&rockchip_drm_platform_driver); 532 533 platform_unregister_drivers(rockchip_sub_drivers, 534 num_rockchip_sub_drivers); 535 } 536 537 module_init(rockchip_drm_init); 538 module_exit(rockchip_drm_fini); 539 540 MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>"); 541 MODULE_DESCRIPTION("ROCKCHIP DRM Driver"); 542 MODULE_LICENSE("GPL v2"); 543