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