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