diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_drv.c')
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.c | 112 |
1 files changed, 108 insertions, 4 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index e913efa4ea0a..7a7421fb02b4 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c | |||
@@ -56,6 +56,10 @@ static char *vram; | |||
56 | MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU"); | 56 | MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU"); |
57 | module_param(vram, charp, 0); | 57 | module_param(vram, charp, 0); |
58 | 58 | ||
59 | /* | ||
60 | * Util/helpers: | ||
61 | */ | ||
62 | |||
59 | void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, | 63 | void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, |
60 | const char *dbgname) | 64 | const char *dbgname) |
61 | { | 65 | { |
@@ -143,6 +147,8 @@ static int msm_unload(struct drm_device *dev) | |||
143 | priv->vram.paddr, &attrs); | 147 | priv->vram.paddr, &attrs); |
144 | } | 148 | } |
145 | 149 | ||
150 | component_unbind_all(dev->dev, dev); | ||
151 | |||
146 | dev->dev_private = NULL; | 152 | dev->dev_private = NULL; |
147 | 153 | ||
148 | kfree(priv); | 154 | kfree(priv); |
@@ -175,6 +181,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags) | |||
175 | struct msm_kms *kms; | 181 | struct msm_kms *kms; |
176 | int ret; | 182 | int ret; |
177 | 183 | ||
184 | |||
178 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 185 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
179 | if (!priv) { | 186 | if (!priv) { |
180 | dev_err(dev->dev, "failed to allocate private data\n"); | 187 | dev_err(dev->dev, "failed to allocate private data\n"); |
@@ -226,6 +233,13 @@ static int msm_load(struct drm_device *dev, unsigned long flags) | |||
226 | (uint32_t)(priv->vram.paddr + size)); | 233 | (uint32_t)(priv->vram.paddr + size)); |
227 | } | 234 | } |
228 | 235 | ||
236 | platform_set_drvdata(pdev, dev); | ||
237 | |||
238 | /* Bind all our sub-components: */ | ||
239 | ret = component_bind_all(dev->dev, dev); | ||
240 | if (ret) | ||
241 | return ret; | ||
242 | |||
229 | switch (get_mdp_ver(pdev)) { | 243 | switch (get_mdp_ver(pdev)) { |
230 | case 4: | 244 | case 4: |
231 | kms = mdp4_kms_init(dev); | 245 | kms = mdp4_kms_init(dev); |
@@ -281,8 +295,6 @@ static int msm_load(struct drm_device *dev, unsigned long flags) | |||
281 | goto fail; | 295 | goto fail; |
282 | } | 296 | } |
283 | 297 | ||
284 | platform_set_drvdata(pdev, dev); | ||
285 | |||
286 | #ifdef CONFIG_DRM_MSM_FBDEV | 298 | #ifdef CONFIG_DRM_MSM_FBDEV |
287 | priv->fbdev = msm_fbdev_init(dev); | 299 | priv->fbdev = msm_fbdev_init(dev); |
288 | #endif | 300 | #endif |
@@ -824,18 +836,110 @@ static const struct dev_pm_ops msm_pm_ops = { | |||
824 | }; | 836 | }; |
825 | 837 | ||
826 | /* | 838 | /* |
839 | * Componentized driver support: | ||
840 | */ | ||
841 | |||
842 | #ifdef CONFIG_OF | ||
843 | /* NOTE: the CONFIG_OF case duplicates the same code as exynos or imx | ||
844 | * (or probably any other).. so probably some room for some helpers | ||
845 | */ | ||
846 | static int compare_of(struct device *dev, void *data) | ||
847 | { | ||
848 | return dev->of_node == data; | ||
849 | } | ||
850 | |||
851 | static int msm_drm_add_components(struct device *master, struct master *m) | ||
852 | { | ||
853 | struct device_node *np = master->of_node; | ||
854 | unsigned i; | ||
855 | int ret; | ||
856 | |||
857 | for (i = 0; ; i++) { | ||
858 | struct device_node *node; | ||
859 | |||
860 | node = of_parse_phandle(np, "connectors", i); | ||
861 | if (!node) | ||
862 | break; | ||
863 | |||
864 | ret = component_master_add_child(m, compare_of, node); | ||
865 | of_node_put(node); | ||
866 | |||
867 | if (ret) | ||
868 | return ret; | ||
869 | } | ||
870 | return 0; | ||
871 | } | ||
872 | #else | ||
873 | static int compare_dev(struct device *dev, void *data) | ||
874 | { | ||
875 | return dev == data; | ||
876 | } | ||
877 | |||
878 | static int msm_drm_add_components(struct device *master, struct master *m) | ||
879 | { | ||
880 | /* For non-DT case, it kinda sucks. We don't actually have a way | ||
881 | * to know whether or not we are waiting for certain devices (or if | ||
882 | * they are simply not present). But for non-DT we only need to | ||
883 | * care about apq8064/apq8060/etc (all mdp4/a3xx): | ||
884 | */ | ||
885 | static const char *devnames[] = { | ||
886 | "hdmi_msm.0", "kgsl-3d0.0", | ||
887 | }; | ||
888 | int i; | ||
889 | |||
890 | DBG("Adding components.."); | ||
891 | |||
892 | for (i = 0; i < ARRAY_SIZE(devnames); i++) { | ||
893 | struct device *dev; | ||
894 | int ret; | ||
895 | |||
896 | dev = bus_find_device_by_name(&platform_bus_type, | ||
897 | NULL, devnames[i]); | ||
898 | if (!dev) { | ||
899 | dev_info(master, "still waiting for %s\n", devnames[i]); | ||
900 | return -EPROBE_DEFER; | ||
901 | } | ||
902 | |||
903 | ret = component_master_add_child(m, compare_dev, dev); | ||
904 | if (ret) { | ||
905 | DBG("could not add child: %d", ret); | ||
906 | return ret; | ||
907 | } | ||
908 | } | ||
909 | |||
910 | return 0; | ||
911 | } | ||
912 | #endif | ||
913 | |||
914 | static int msm_drm_bind(struct device *dev) | ||
915 | { | ||
916 | return drm_platform_init(&msm_driver, to_platform_device(dev)); | ||
917 | } | ||
918 | |||
919 | static void msm_drm_unbind(struct device *dev) | ||
920 | { | ||
921 | drm_put_dev(platform_get_drvdata(to_platform_device(dev))); | ||
922 | } | ||
923 | |||
924 | static const struct component_master_ops msm_drm_ops = { | ||
925 | .add_components = msm_drm_add_components, | ||
926 | .bind = msm_drm_bind, | ||
927 | .unbind = msm_drm_unbind, | ||
928 | }; | ||
929 | |||
930 | /* | ||
827 | * Platform driver: | 931 | * Platform driver: |
828 | */ | 932 | */ |
829 | 933 | ||
830 | static int msm_pdev_probe(struct platform_device *pdev) | 934 | static int msm_pdev_probe(struct platform_device *pdev) |
831 | { | 935 | { |
832 | pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | 936 | pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); |
833 | return drm_platform_init(&msm_driver, pdev); | 937 | return component_master_add(&pdev->dev, &msm_drm_ops); |
834 | } | 938 | } |
835 | 939 | ||
836 | static int msm_pdev_remove(struct platform_device *pdev) | 940 | static int msm_pdev_remove(struct platform_device *pdev) |
837 | { | 941 | { |
838 | drm_put_dev(platform_get_drvdata(pdev)); | 942 | component_master_del(&pdev->dev, &msm_drm_ops); |
839 | 943 | ||
840 | return 0; | 944 | return 0; |
841 | } | 945 | } |