diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_drv.c')
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.c | 132 |
1 files changed, 93 insertions, 39 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 86537692e45c..e6adafc7eff3 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -17,6 +17,7 @@ #include "msm_drv.h" #include "msm_gpu.h" +#include "msm_kms.h" static void msm_fb_output_poll_changed(struct drm_device *dev) { @@ -30,50 +31,19 @@ static const struct drm_mode_config_funcs mode_config_funcs = { .output_poll_changed = msm_fb_output_poll_changed, }; -static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev, - unsigned long iova, int flags, void *arg) -{ - DBG("*** fault: iova=%08lx, flags=%d", iova, flags); - return 0; -} - -int msm_register_iommu(struct drm_device *dev, struct iommu_domain *iommu) +int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu) { struct msm_drm_private *priv = dev->dev_private; - int idx = priv->num_iommus++; + int idx = priv->num_mmus++; - if (WARN_ON(idx >= ARRAY_SIZE(priv->iommus))) + if (WARN_ON(idx >= ARRAY_SIZE(priv->mmus))) return -EINVAL; - priv->iommus[idx] = iommu; - - iommu_set_fault_handler(iommu, msm_fault_handler, dev); - - /* need to iommu_attach_device() somewhere?? on resume?? */ + priv->mmus[idx] = mmu; return idx; } -int msm_iommu_attach(struct drm_device *dev, struct iommu_domain *iommu, - const char **names, int cnt) -{ - int i, ret; - - for (i = 0; i < cnt; i++) { - /* TODO maybe some day msm iommu won't require this hack: */ - struct device *msm_iommu_get_ctx(const char *ctx_name); - struct device *ctx = msm_iommu_get_ctx(names[i]); - if (!ctx) - continue; - ret = iommu_attach_device(iommu, ctx); - if (ret) { - dev_warn(dev->dev, "could not attach iommu to %s", names[i]); - return ret; - } - } - return 0; -} - #ifdef CONFIG_DRM_MSM_REGISTER_LOGGING static bool reglog = false; MODULE_PARM_DESC(reglog, "Enable register read/write logging"); @@ -82,6 +52,10 @@ module_param(reglog, bool, 0600); #define reglog 0 #endif +static char *vram; +MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU"); +module_param(vram, charp, 0); + void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, const char *dbgname) { @@ -161,6 +135,14 @@ static int msm_unload(struct drm_device *dev) mutex_unlock(&dev->struct_mutex); } + if (priv->vram.paddr) { + DEFINE_DMA_ATTRS(attrs); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); + drm_mm_takedown(&priv->vram.mm); + dma_free_attrs(dev->dev, priv->vram.size, NULL, + priv->vram.paddr, &attrs); + } + dev->dev_private = NULL; kfree(priv); @@ -168,6 +150,24 @@ static int msm_unload(struct drm_device *dev) return 0; } +static int get_mdp_ver(struct platform_device *pdev) +{ +#ifdef CONFIG_OF + const static struct of_device_id match_types[] = { { + .compatible = "qcom,mdss_mdp", + .data = (void *)5, + }, { + /* end node */ + } }; + struct device *dev = &pdev->dev; + const struct of_device_id *match; + match = of_match_node(match_types, dev->of_node); + if (match) + return (int)match->data; +#endif + return 4; +} + static int msm_load(struct drm_device *dev, unsigned long flags) { struct platform_device *pdev = dev->platformdev; @@ -191,7 +191,53 @@ static int msm_load(struct drm_device *dev, unsigned long flags) drm_mode_config_init(dev); - kms = mdp4_kms_init(dev); + /* if we have no IOMMU, then we need to use carveout allocator. + * Grab the entire CMA chunk carved out in early startup in + * mach-msm: + */ + if (!iommu_present(&platform_bus_type)) { + DEFINE_DMA_ATTRS(attrs); + unsigned long size; + void *p; + + DBG("using %s VRAM carveout", vram); + size = memparse(vram, NULL); + priv->vram.size = size; + + drm_mm_init(&priv->vram.mm, 0, (size >> PAGE_SHIFT) - 1); + + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + + /* note that for no-kernel-mapping, the vaddr returned + * is bogus, but non-null if allocation succeeded: + */ + p = dma_alloc_attrs(dev->dev, size, + &priv->vram.paddr, 0, &attrs); + if (!p) { + dev_err(dev->dev, "failed to allocate VRAM\n"); + priv->vram.paddr = 0; + ret = -ENOMEM; + goto fail; + } + + dev_info(dev->dev, "VRAM: %08x->%08x\n", + (uint32_t)priv->vram.paddr, + (uint32_t)(priv->vram.paddr + size)); + } + + switch (get_mdp_ver(pdev)) { + case 4: + kms = mdp4_kms_init(dev); + break; + case 5: + kms = mdp5_kms_init(dev); + break; + default: + kms = ERR_PTR(-ENODEV); + break; + } + if (IS_ERR(kms)) { /* * NOTE: once we have GPU support, having no kms should not @@ -326,7 +372,7 @@ static void msm_lastclose(struct drm_device *dev) } } -static irqreturn_t msm_irq(DRM_IRQ_ARGS) +static irqreturn_t msm_irq(int irq, void *arg) { struct drm_device *dev = arg; struct msm_drm_private *priv = dev->dev_private; @@ -415,7 +461,7 @@ static int msm_gem_show(struct drm_device *dev, struct seq_file *m) static int msm_mm_show(struct drm_device *dev, struct seq_file *m) { - return drm_mm_dump_table(m, dev->mm_private); + return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm); } static int msm_fb_show(struct drm_device *dev, struct seq_file *m) @@ -778,12 +824,13 @@ static const struct dev_pm_ops msm_pm_ops = { static int msm_pdev_probe(struct platform_device *pdev) { + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); return drm_platform_init(&msm_driver, pdev); } static int msm_pdev_remove(struct platform_device *pdev) { - drm_platform_exit(&msm_driver, pdev); + drm_put_dev(platform_get_drvdata(pdev)); return 0; } @@ -793,12 +840,19 @@ static const struct platform_device_id msm_id[] = { { } }; +static const struct of_device_id dt_match[] = { + { .compatible = "qcom,mdss_mdp" }, + {} +}; +MODULE_DEVICE_TABLE(of, dt_match); + static struct platform_driver msm_platform_driver = { .probe = msm_pdev_probe, .remove = msm_pdev_remove, .driver = { .owner = THIS_MODULE, .name = "msm", + .of_match_table = dt_match, .pm = &msm_pm_ops, }, .id_table = msm_id, |