Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
0004  * Author:Mark Yao <mark.yao@rock-chips.com>
0005  *
0006  * based on exynos_drm_drv.c
0007  */
0008 
0009 #include <linux/dma-mapping.h>
0010 #include <linux/pm_runtime.h>
0011 #include <linux/module.h>
0012 #include <linux/of_graph.h>
0013 #include <linux/of_platform.h>
0014 #include <linux/component.h>
0015 #include <linux/console.h>
0016 #include <linux/iommu.h>
0017 
0018 #include <drm/drm_aperture.h>
0019 #include <drm/drm_drv.h>
0020 #include <drm/drm_fb_helper.h>
0021 #include <drm/drm_gem_cma_helper.h>
0022 #include <drm/drm_of.h>
0023 #include <drm/drm_probe_helper.h>
0024 #include <drm/drm_vblank.h>
0025 
0026 #if defined(CONFIG_ARM_DMA_USE_IOMMU)
0027 #include <asm/dma-iommu.h>
0028 #else
0029 #define arm_iommu_detach_device(...)    ({ })
0030 #define arm_iommu_release_mapping(...)  ({ })
0031 #define to_dma_iommu_mapping(dev) NULL
0032 #endif
0033 
0034 #include "rockchip_drm_drv.h"
0035 #include "rockchip_drm_fb.h"
0036 #include "rockchip_drm_gem.h"
0037 
0038 #define DRIVER_NAME "rockchip"
0039 #define DRIVER_DESC "RockChip Soc DRM"
0040 #define DRIVER_DATE "20140818"
0041 #define DRIVER_MAJOR    1
0042 #define DRIVER_MINOR    0
0043 
0044 static const struct drm_driver rockchip_drm_driver;
0045 
0046 /*
0047  * Attach a (component) device to the shared drm dma mapping from master drm
0048  * device.  This is used by the VOPs to map GEM buffers to a common DMA
0049  * mapping.
0050  */
0051 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
0052                    struct device *dev)
0053 {
0054     struct rockchip_drm_private *private = drm_dev->dev_private;
0055     int ret;
0056 
0057     if (!private->domain)
0058         return 0;
0059 
0060     if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) {
0061         struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
0062 
0063         if (mapping) {
0064             arm_iommu_detach_device(dev);
0065             arm_iommu_release_mapping(mapping);
0066         }
0067     }
0068 
0069     ret = iommu_attach_device(private->domain, dev);
0070     if (ret) {
0071         DRM_DEV_ERROR(dev, "Failed to attach iommu device\n");
0072         return ret;
0073     }
0074 
0075     return 0;
0076 }
0077 
0078 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
0079                     struct device *dev)
0080 {
0081     struct rockchip_drm_private *private = drm_dev->dev_private;
0082 
0083     if (!private->domain)
0084         return;
0085 
0086     iommu_detach_device(private->domain, dev);
0087 }
0088 
0089 void rockchip_drm_dma_init_device(struct drm_device *drm_dev,
0090                   struct device *dev)
0091 {
0092     struct rockchip_drm_private *private = drm_dev->dev_private;
0093 
0094     if (!device_iommu_mapped(dev))
0095         private->iommu_dev = ERR_PTR(-ENODEV);
0096     else if (!private->iommu_dev)
0097         private->iommu_dev = dev;
0098 }
0099 
0100 static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
0101 {
0102     struct rockchip_drm_private *private = drm_dev->dev_private;
0103     struct iommu_domain_geometry *geometry;
0104     u64 start, end;
0105 
0106     if (IS_ERR_OR_NULL(private->iommu_dev))
0107         return 0;
0108 
0109     private->domain = iommu_domain_alloc(private->iommu_dev->bus);
0110     if (!private->domain)
0111         return -ENOMEM;
0112 
0113     geometry = &private->domain->geometry;
0114     start = geometry->aperture_start;
0115     end = geometry->aperture_end;
0116 
0117     DRM_DEBUG("IOMMU context initialized (aperture: %#llx-%#llx)\n",
0118           start, end);
0119     drm_mm_init(&private->mm, start, end - start + 1);
0120     mutex_init(&private->mm_lock);
0121 
0122     return 0;
0123 }
0124 
0125 static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
0126 {
0127     struct rockchip_drm_private *private = drm_dev->dev_private;
0128 
0129     if (!private->domain)
0130         return;
0131 
0132     drm_mm_takedown(&private->mm);
0133     iommu_domain_free(private->domain);
0134 }
0135 
0136 static int rockchip_drm_bind(struct device *dev)
0137 {
0138     struct drm_device *drm_dev;
0139     struct rockchip_drm_private *private;
0140     int ret;
0141 
0142     /* Remove existing drivers that may own the framebuffer memory. */
0143     ret = drm_aperture_remove_framebuffers(false, &rockchip_drm_driver);
0144     if (ret) {
0145         DRM_DEV_ERROR(dev,
0146                   "Failed to remove existing framebuffers - %d.\n",
0147                   ret);
0148         return ret;
0149     }
0150 
0151     drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev);
0152     if (IS_ERR(drm_dev))
0153         return PTR_ERR(drm_dev);
0154 
0155     dev_set_drvdata(dev, drm_dev);
0156 
0157     private = devm_kzalloc(drm_dev->dev, sizeof(*private), GFP_KERNEL);
0158     if (!private) {
0159         ret = -ENOMEM;
0160         goto err_free;
0161     }
0162 
0163     drm_dev->dev_private = private;
0164 
0165     ret = drmm_mode_config_init(drm_dev);
0166     if (ret)
0167         goto err_free;
0168 
0169     rockchip_drm_mode_config_init(drm_dev);
0170 
0171     /* Try to bind all sub drivers. */
0172     ret = component_bind_all(dev, drm_dev);
0173     if (ret)
0174         goto err_free;
0175 
0176     ret = rockchip_drm_init_iommu(drm_dev);
0177     if (ret)
0178         goto err_unbind_all;
0179 
0180     ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
0181     if (ret)
0182         goto err_iommu_cleanup;
0183 
0184     drm_mode_config_reset(drm_dev);
0185 
0186     /* init kms poll for handling hpd */
0187     drm_kms_helper_poll_init(drm_dev);
0188 
0189     ret = drm_dev_register(drm_dev, 0);
0190     if (ret)
0191         goto err_kms_helper_poll_fini;
0192 
0193     drm_fbdev_generic_setup(drm_dev, 0);
0194 
0195     return 0;
0196 err_kms_helper_poll_fini:
0197     drm_kms_helper_poll_fini(drm_dev);
0198 err_iommu_cleanup:
0199     rockchip_iommu_cleanup(drm_dev);
0200 err_unbind_all:
0201     component_unbind_all(dev, drm_dev);
0202 err_free:
0203     drm_dev_put(drm_dev);
0204     return ret;
0205 }
0206 
0207 static void rockchip_drm_unbind(struct device *dev)
0208 {
0209     struct drm_device *drm_dev = dev_get_drvdata(dev);
0210 
0211     drm_dev_unregister(drm_dev);
0212 
0213     drm_kms_helper_poll_fini(drm_dev);
0214 
0215     drm_atomic_helper_shutdown(drm_dev);
0216     component_unbind_all(dev, drm_dev);
0217     rockchip_iommu_cleanup(drm_dev);
0218 
0219     drm_dev_put(drm_dev);
0220 }
0221 
0222 DEFINE_DRM_GEM_FOPS(rockchip_drm_driver_fops);
0223 
0224 static const struct drm_driver rockchip_drm_driver = {
0225     .driver_features    = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
0226     .dumb_create        = rockchip_gem_dumb_create,
0227     .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
0228     .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
0229     .gem_prime_import_sg_table  = rockchip_gem_prime_import_sg_table,
0230     .gem_prime_mmap     = drm_gem_prime_mmap,
0231     .fops           = &rockchip_drm_driver_fops,
0232     .name   = DRIVER_NAME,
0233     .desc   = DRIVER_DESC,
0234     .date   = DRIVER_DATE,
0235     .major  = DRIVER_MAJOR,
0236     .minor  = DRIVER_MINOR,
0237 };
0238 
0239 #ifdef CONFIG_PM_SLEEP
0240 static int rockchip_drm_sys_suspend(struct device *dev)
0241 {
0242     struct drm_device *drm = dev_get_drvdata(dev);
0243 
0244     return drm_mode_config_helper_suspend(drm);
0245 }
0246 
0247 static int rockchip_drm_sys_resume(struct device *dev)
0248 {
0249     struct drm_device *drm = dev_get_drvdata(dev);
0250 
0251     return drm_mode_config_helper_resume(drm);
0252 }
0253 #endif
0254 
0255 static const struct dev_pm_ops rockchip_drm_pm_ops = {
0256     SET_SYSTEM_SLEEP_PM_OPS(rockchip_drm_sys_suspend,
0257                 rockchip_drm_sys_resume)
0258 };
0259 
0260 #define MAX_ROCKCHIP_SUB_DRIVERS 16
0261 static struct platform_driver *rockchip_sub_drivers[MAX_ROCKCHIP_SUB_DRIVERS];
0262 static int num_rockchip_sub_drivers;
0263 
0264 /*
0265  * Get the endpoint id of the remote endpoint of the given encoder. This
0266  * information is used by the VOP2 driver to identify the encoder.
0267  *
0268  * @rkencoder: The encoder to get the remote endpoint id from
0269  * @np: The encoder device node
0270  * @port: The number of the port leading to the VOP2
0271  * @reg: The endpoint number leading to the VOP2
0272  */
0273 int rockchip_drm_encoder_set_crtc_endpoint_id(struct rockchip_encoder *rkencoder,
0274                           struct device_node *np, int port, int reg)
0275 {
0276     struct of_endpoint ep;
0277     struct device_node *en, *ren;
0278     int ret;
0279 
0280     en = of_graph_get_endpoint_by_regs(np, port, reg);
0281     if (!en)
0282         return -ENOENT;
0283 
0284     ren = of_graph_get_remote_endpoint(en);
0285     if (!ren)
0286         return -ENOENT;
0287 
0288     ret = of_graph_parse_endpoint(ren, &ep);
0289     if (ret)
0290         return ret;
0291 
0292     rkencoder->crtc_endpoint_id = ep.id;
0293 
0294     return 0;
0295 }
0296 
0297 /*
0298  * Check if a vop endpoint is leading to a rockchip subdriver or bridge.
0299  * Should be called from the component bind stage of the drivers
0300  * to ensure that all subdrivers are probed.
0301  *
0302  * @ep: endpoint of a rockchip vop
0303  *
0304  * returns true if subdriver, false if external bridge and -ENODEV
0305  * if remote port does not contain a device.
0306  */
0307 int rockchip_drm_endpoint_is_subdriver(struct device_node *ep)
0308 {
0309     struct device_node *node = of_graph_get_remote_port_parent(ep);
0310     struct platform_device *pdev;
0311     struct device_driver *drv;
0312     int i;
0313 
0314     if (!node)
0315         return -ENODEV;
0316 
0317     /* status disabled will prevent creation of platform-devices */
0318     if (!of_device_is_available(node)) {
0319         of_node_put(node);
0320         return -ENODEV;
0321     }
0322 
0323     pdev = of_find_device_by_node(node);
0324     of_node_put(node);
0325 
0326     /* enabled non-platform-devices can immediately return here */
0327     if (!pdev)
0328         return false;
0329 
0330     /*
0331      * All rockchip subdrivers have probed at this point, so
0332      * any device not having a driver now is an external bridge.
0333      */
0334     drv = pdev->dev.driver;
0335     if (!drv) {
0336         platform_device_put(pdev);
0337         return false;
0338     }
0339 
0340     for (i = 0; i < num_rockchip_sub_drivers; i++) {
0341         if (rockchip_sub_drivers[i] == to_platform_driver(drv)) {
0342             platform_device_put(pdev);
0343             return true;
0344         }
0345     }
0346 
0347     platform_device_put(pdev);
0348     return false;
0349 }
0350 
0351 static void rockchip_drm_match_remove(struct device *dev)
0352 {
0353     struct device_link *link;
0354 
0355     list_for_each_entry(link, &dev->links.consumers, s_node)
0356         device_link_del(link);
0357 }
0358 
0359 static struct component_match *rockchip_drm_match_add(struct device *dev)
0360 {
0361     struct component_match *match = NULL;
0362     int i;
0363 
0364     for (i = 0; i < num_rockchip_sub_drivers; i++) {
0365         struct platform_driver *drv = rockchip_sub_drivers[i];
0366         struct device *p = NULL, *d;
0367 
0368         do {
0369             d = platform_find_device_by_driver(p, &drv->driver);
0370             put_device(p);
0371             p = d;
0372 
0373             if (!d)
0374                 break;
0375 
0376             device_link_add(dev, d, DL_FLAG_STATELESS);
0377             component_match_add(dev, &match, component_compare_dev, d);
0378         } while (true);
0379     }
0380 
0381     if (IS_ERR(match))
0382         rockchip_drm_match_remove(dev);
0383 
0384     return match ?: ERR_PTR(-ENODEV);
0385 }
0386 
0387 static const struct component_master_ops rockchip_drm_ops = {
0388     .bind = rockchip_drm_bind,
0389     .unbind = rockchip_drm_unbind,
0390 };
0391 
0392 static int rockchip_drm_platform_of_probe(struct device *dev)
0393 {
0394     struct device_node *np = dev->of_node;
0395     struct device_node *port;
0396     bool found = false;
0397     int i;
0398 
0399     if (!np)
0400         return -ENODEV;
0401 
0402     for (i = 0;; i++) {
0403         port = of_parse_phandle(np, "ports", i);
0404         if (!port)
0405             break;
0406 
0407         if (!of_device_is_available(port->parent)) {
0408             of_node_put(port);
0409             continue;
0410         }
0411 
0412         found = true;
0413         of_node_put(port);
0414     }
0415 
0416     if (i == 0) {
0417         DRM_DEV_ERROR(dev, "missing 'ports' property\n");
0418         return -ENODEV;
0419     }
0420 
0421     if (!found) {
0422         DRM_DEV_ERROR(dev,
0423                   "No available vop found for display-subsystem.\n");
0424         return -ENODEV;
0425     }
0426 
0427     return 0;
0428 }
0429 
0430 static int rockchip_drm_platform_probe(struct platform_device *pdev)
0431 {
0432     struct device *dev = &pdev->dev;
0433     struct component_match *match = NULL;
0434     int ret;
0435 
0436     ret = rockchip_drm_platform_of_probe(dev);
0437     if (ret)
0438         return ret;
0439 
0440     match = rockchip_drm_match_add(dev);
0441     if (IS_ERR(match))
0442         return PTR_ERR(match);
0443 
0444     ret = component_master_add_with_match(dev, &rockchip_drm_ops, match);
0445     if (ret < 0) {
0446         rockchip_drm_match_remove(dev);
0447         return ret;
0448     }
0449 
0450     return 0;
0451 }
0452 
0453 static int rockchip_drm_platform_remove(struct platform_device *pdev)
0454 {
0455     component_master_del(&pdev->dev, &rockchip_drm_ops);
0456 
0457     rockchip_drm_match_remove(&pdev->dev);
0458 
0459     return 0;
0460 }
0461 
0462 static void rockchip_drm_platform_shutdown(struct platform_device *pdev)
0463 {
0464     struct drm_device *drm = platform_get_drvdata(pdev);
0465 
0466     if (drm)
0467         drm_atomic_helper_shutdown(drm);
0468 }
0469 
0470 static const struct of_device_id rockchip_drm_dt_ids[] = {
0471     { .compatible = "rockchip,display-subsystem", },
0472     { /* sentinel */ },
0473 };
0474 MODULE_DEVICE_TABLE(of, rockchip_drm_dt_ids);
0475 
0476 static struct platform_driver rockchip_drm_platform_driver = {
0477     .probe = rockchip_drm_platform_probe,
0478     .remove = rockchip_drm_platform_remove,
0479     .shutdown = rockchip_drm_platform_shutdown,
0480     .driver = {
0481         .name = "rockchip-drm",
0482         .of_match_table = rockchip_drm_dt_ids,
0483         .pm = &rockchip_drm_pm_ops,
0484     },
0485 };
0486 
0487 #define ADD_ROCKCHIP_SUB_DRIVER(drv, cond) { \
0488     if (IS_ENABLED(cond) && \
0489         !WARN_ON(num_rockchip_sub_drivers >= MAX_ROCKCHIP_SUB_DRIVERS)) \
0490         rockchip_sub_drivers[num_rockchip_sub_drivers++] = &drv; \
0491 }
0492 
0493 static int __init rockchip_drm_init(void)
0494 {
0495     int ret;
0496 
0497     if (drm_firmware_drivers_only())
0498         return -ENODEV;
0499 
0500     num_rockchip_sub_drivers = 0;
0501     ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
0502     ADD_ROCKCHIP_SUB_DRIVER(vop2_platform_driver, CONFIG_ROCKCHIP_VOP2);
0503     ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
0504                 CONFIG_ROCKCHIP_LVDS);
0505     ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
0506                 CONFIG_ROCKCHIP_ANALOGIX_DP);
0507     ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP);
0508     ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver,
0509                 CONFIG_ROCKCHIP_DW_HDMI);
0510     ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_rockchip_driver,
0511                 CONFIG_ROCKCHIP_DW_MIPI_DSI);
0512     ADD_ROCKCHIP_SUB_DRIVER(inno_hdmi_driver, CONFIG_ROCKCHIP_INNO_HDMI);
0513     ADD_ROCKCHIP_SUB_DRIVER(rk3066_hdmi_driver,
0514                 CONFIG_ROCKCHIP_RK3066_HDMI);
0515 
0516     ret = platform_register_drivers(rockchip_sub_drivers,
0517                     num_rockchip_sub_drivers);
0518     if (ret)
0519         return ret;
0520 
0521     ret = platform_driver_register(&rockchip_drm_platform_driver);
0522     if (ret)
0523         goto err_unreg_drivers;
0524 
0525     return 0;
0526 
0527 err_unreg_drivers:
0528     platform_unregister_drivers(rockchip_sub_drivers,
0529                     num_rockchip_sub_drivers);
0530     return ret;
0531 }
0532 
0533 static void __exit rockchip_drm_fini(void)
0534 {
0535     platform_driver_unregister(&rockchip_drm_platform_driver);
0536 
0537     platform_unregister_drivers(rockchip_sub_drivers,
0538                     num_rockchip_sub_drivers);
0539 }
0540 
0541 module_init(rockchip_drm_init);
0542 module_exit(rockchip_drm_fini);
0543 
0544 MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>");
0545 MODULE_DESCRIPTION("ROCKCHIP DRM Driver");
0546 MODULE_LICENSE("GPL v2");