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