]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/gpu/drm/msm/msm_drv.c
Merge tag 'for-usb-linus-2014-02-04' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / msm / msm_drv.c
index 86537692e45c4efaeae162d32753cf5613216954..e6adafc7eff3177b789395f6bc81f4ab62042e11 100644 (file)
@@ -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,