]> git.karo-electronics.de Git - linux-beck.git/commitdiff
drm/msm/mdp5: Prepare new kms_init funcs
authorArchit Taneja <architt@codeaurora.org>
Tue, 14 Jun 2016 12:53:52 +0000 (18:23 +0530)
committerRob Clark <robdclark@gmail.com>
Sat, 16 Jul 2016 14:08:56 +0000 (10:08 -0400)
With MDP5 as a new device, we need to do less for MDP when initializing
modeset after all the components are bound.

Create mdp5_kms_init2/destroy2 funcs that inits modeset. These will
eventually replace the older kms_init/destroy funcs.

In the new kms_init2, the platform_device used is the one corresponding
to the new MDP5 platform_device. The new change here is that the irq is
now retrieved using irq_of_parse_and_map(), since MDP5 is a child interrupt
of the MDSS interrupt controller.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
drivers/gpu/drm/msm/msm_kms.h

index fcb1bf4508836ec10cf8348b2bb0d53ce77a2d93..9f69924ec32690b1e5d0ff06667a5f2d52c4de56 100644 (file)
@@ -16,6 +16,7 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/of_irq.h>
 
 #include "msm_drv.h"
 #include "msm_mmu.h"
@@ -133,6 +134,17 @@ static void mdp5_kms_destroy(struct msm_kms *kms)
        kfree(mdp5_kms);
 }
 
+static void mdp5_kms_destroy2(struct msm_kms *kms)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       struct msm_mmu *mmu = mdp5_kms->mmu;
+
+       if (mmu) {
+               mmu->funcs->detach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports));
+               mmu->funcs->destroy(mmu);
+       }
+}
+
 static const struct mdp_kms_funcs kms_funcs = {
        .base = {
                .hw_init         = mdp5_hw_init,
@@ -776,6 +788,109 @@ fail:
        return ERR_PTR(ret);
 }
 
+struct msm_kms *mdp5_kms_init2(struct drm_device *dev)
+{
+       struct msm_drm_private *priv = dev->dev_private;
+       struct platform_device *pdev;
+       struct mdp5_kms *mdp5_kms;
+       struct mdp5_cfg *config;
+       struct msm_kms *kms;
+       struct msm_mmu *mmu;
+       int irq, i, ret;
+
+       /* priv->kms would have been populated by the MDP5 driver */
+       kms = priv->kms;
+       if (!kms)
+               return NULL;
+
+       mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+
+       mdp_kms_init(&mdp5_kms->base, &kms_funcs);
+
+       pdev = mdp5_kms->pdev;
+
+       irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+       if (irq < 0) {
+               ret = irq;
+               dev_err(&pdev->dev, "failed to get irq: %d\n", ret);
+               goto fail;
+       }
+
+       kms->irq = irq;
+
+       config = mdp5_cfg_get_config(mdp5_kms->cfg);
+
+       /* make sure things are off before attaching iommu (bootloader could
+        * have left things on, in which case we'll start getting faults if
+        * we don't disable):
+        */
+       mdp5_enable(mdp5_kms);
+       for (i = 0; i < MDP5_INTF_NUM_MAX; i++) {
+               if (mdp5_cfg_intf_is_virtual(config->hw->intf.connect[i]) ||
+                   !config->hw->intf.base[i])
+                       continue;
+               mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(i), 0);
+
+               mdp5_write(mdp5_kms, REG_MDP5_INTF_FRAME_LINE_COUNT_EN(i), 0x3);
+       }
+       mdp5_disable(mdp5_kms);
+       mdelay(16);
+
+       if (config->platform.iommu) {
+               mmu = msm_iommu_new(&pdev->dev, config->platform.iommu);
+               if (IS_ERR(mmu)) {
+                       ret = PTR_ERR(mmu);
+                       dev_err(&pdev->dev, "failed to init iommu: %d\n", ret);
+                       iommu_domain_free(config->platform.iommu);
+                       goto fail;
+               }
+
+               ret = mmu->funcs->attach(mmu, iommu_ports,
+                               ARRAY_SIZE(iommu_ports));
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to attach iommu: %d\n",
+                               ret);
+                       mmu->funcs->destroy(mmu);
+                       goto fail;
+               }
+       } else {
+               dev_info(&pdev->dev,
+                        "no iommu, fallback to phys contig buffers for scanout\n");
+               mmu = NULL;
+       }
+       mdp5_kms->mmu = mmu;
+
+       mdp5_kms->id = msm_register_mmu(dev, mmu);
+       if (mdp5_kms->id < 0) {
+               ret = mdp5_kms->id;
+               dev_err(&pdev->dev, "failed to register mdp5 iommu: %d\n", ret);
+               goto fail;
+       }
+
+       ret = modeset_init(mdp5_kms);
+       if (ret) {
+               dev_err(&pdev->dev, "modeset_init failed: %d\n", ret);
+               goto fail;
+       }
+
+       dev->mode_config.min_width = 0;
+       dev->mode_config.min_height = 0;
+       dev->mode_config.max_width = config->hw->lm.max_width;
+       dev->mode_config.max_height = config->hw->lm.max_height;
+
+       dev->driver->get_vblank_timestamp = mdp5_get_vblank_timestamp;
+       dev->driver->get_scanout_position = mdp5_get_scanoutpos;
+       dev->driver->get_vblank_counter = mdp5_get_vblank_counter;
+       dev->max_vblank_count = 0xffffffff;
+       dev->vblank_disable_immediate = true;
+
+       return kms;
+fail:
+       if (kms)
+               mdp5_kms_destroy2(kms);
+       return ERR_PTR(ret);
+}
+
 static void mdp5_destroy(struct platform_device *pdev)
 {
        struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev);
index 40e41e5cdbc6fad17d970cb1b645ba90cf0cbe75..13f893d1a5181ded0bb0061ec6a667c1ce73e375 100644 (file)
@@ -73,6 +73,7 @@ static inline void msm_kms_init(struct msm_kms *kms,
 
 struct msm_kms *mdp4_kms_init(struct drm_device *dev);
 struct msm_kms *mdp5_kms_init(struct drm_device *dev);
+struct msm_kms *mdp5_kms_init2(struct drm_device *dev);
 int msm_mdss_init(struct drm_device *dev);
 void msm_mdss_destroy(struct drm_device *dev);