struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev, void __iomem *mmio_base, const struct mdp5_cfg_hw *hw_cfg) { struct mdp5_ctl_manager *ctl_mgr; const struct mdp5_ctl_block *ctl_cfg = &hw_cfg->ctl; unsigned long flags; int c, ret; ctl_mgr = kzalloc(sizeof(*ctl_mgr), GFP_KERNEL); if (!ctl_mgr) { dev_err(dev->dev, "failed to allocate CTL manager\n"); ret = -ENOMEM; goto fail; } if (unlikely(WARN_ON(ctl_cfg->count > MAX_CTL))) { dev_err(dev->dev, "Increase static pool size to at least %d\n", ctl_cfg->count); ret = -ENOSPC; goto fail; } /* initialize the CTL manager: */ ctl_mgr->dev = dev; ctl_mgr->nlm = hw_cfg->lm.count; ctl_mgr->nctl = ctl_cfg->count; ctl_mgr->flush_hw_mask = ctl_cfg->flush_hw_mask; spin_lock_init(&ctl_mgr->pool_lock); /* initialize each CTL of the pool: */ spin_lock_irqsave(&ctl_mgr->pool_lock, flags); for (c = 0; c < ctl_mgr->nctl; c++) { struct mdp5_ctl *ctl = &ctl_mgr->ctls[c]; if (WARN_ON(!ctl_cfg->base[c])) { dev_err(dev->dev, "CTL_%d: base is null!\n", c); ret = -EINVAL; goto fail; } ctl->ctlm = ctl_mgr; ctl->id = c; ctl->reg_offset = ctl_cfg->base[c]; ctl->busy = false; spin_lock_init(&ctl->hw_lock); } spin_unlock_irqrestore(&ctl_mgr->pool_lock, flags); DBG("Pool of %d CTLs created.", ctl_mgr->nctl); return ctl_mgr; fail: if (ctl_mgr) mdp5_ctlm_destroy(ctl_mgr); return ERR_PTR(ret); }
static void mdp5_destroy(struct platform_device *pdev) { struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev); int i; if (mdp5_kms->ctlm) mdp5_ctlm_destroy(mdp5_kms->ctlm); if (mdp5_kms->smp) mdp5_smp_destroy(mdp5_kms->smp); if (mdp5_kms->cfg) mdp5_cfg_destroy(mdp5_kms->cfg); for (i = 0; i < mdp5_kms->num_intfs; i++) kfree(mdp5_kms->intfs[i]); if (mdp5_kms->rpm_enabled) pm_runtime_disable(&pdev->dev); kfree(mdp5_kms->state); }
static void mdp5_destroy(struct platform_device *pdev) { struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev); int i; if (mdp5_kms->ctlm) mdp5_ctlm_destroy(mdp5_kms->ctlm); if (mdp5_kms->smp) mdp5_smp_destroy(mdp5_kms->smp); if (mdp5_kms->cfg) mdp5_cfg_destroy(mdp5_kms->cfg); for (i = 0; i < mdp5_kms->num_intfs; i++) kfree(mdp5_kms->intfs[i]); if (mdp5_kms->rpm_enabled) pm_runtime_disable(&pdev->dev); drm_atomic_private_obj_fini(&mdp5_kms->glob_state); drm_modeset_lock_fini(&mdp5_kms->glob_state_lock); }
static void mdp5_destroy(struct msm_kms *kms) { struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); struct msm_mmu *mmu = mdp5_kms->mmu; mdp5_irq_domain_fini(mdp5_kms); if (mmu) { mmu->funcs->detach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports)); mmu->funcs->destroy(mmu); } if (mdp5_kms->ctlm) mdp5_ctlm_destroy(mdp5_kms->ctlm); if (mdp5_kms->smp) mdp5_smp_destroy(mdp5_kms->smp); if (mdp5_kms->cfg) mdp5_cfg_destroy(mdp5_kms->cfg); kfree(mdp5_kms); }
struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev, void __iomem *mmio_base, struct mdp5_cfg_handler *cfg_hnd) { struct mdp5_ctl_manager *ctl_mgr; const struct mdp5_cfg_hw *hw_cfg = mdp5_cfg_get_hw_config(cfg_hnd); int rev = mdp5_cfg_get_hw_rev(cfg_hnd); unsigned dsi_cnt = 0; const struct mdp5_ctl_block *ctl_cfg = &hw_cfg->ctl; unsigned long flags; int c, ret; ctl_mgr = kzalloc(sizeof(*ctl_mgr), GFP_KERNEL); if (!ctl_mgr) { DRM_DEV_ERROR(dev->dev, "failed to allocate CTL manager\n"); ret = -ENOMEM; goto fail; } if (unlikely(WARN_ON(ctl_cfg->count > MAX_CTL))) { DRM_DEV_ERROR(dev->dev, "Increase static pool size to at least %d\n", ctl_cfg->count); ret = -ENOSPC; goto fail; } /* initialize the CTL manager: */ ctl_mgr->dev = dev; ctl_mgr->nlm = hw_cfg->lm.count; ctl_mgr->nctl = ctl_cfg->count; ctl_mgr->flush_hw_mask = ctl_cfg->flush_hw_mask; spin_lock_init(&ctl_mgr->pool_lock); /* initialize each CTL of the pool: */ spin_lock_irqsave(&ctl_mgr->pool_lock, flags); for (c = 0; c < ctl_mgr->nctl; c++) { struct mdp5_ctl *ctl = &ctl_mgr->ctls[c]; if (WARN_ON(!ctl_cfg->base[c])) { DRM_DEV_ERROR(dev->dev, "CTL_%d: base is null!\n", c); ret = -EINVAL; spin_unlock_irqrestore(&ctl_mgr->pool_lock, flags); goto fail; } ctl->ctlm = ctl_mgr; ctl->id = c; ctl->reg_offset = ctl_cfg->base[c]; ctl->status = 0; spin_lock_init(&ctl->hw_lock); } /* * In Dual DSI case, CTL0 and CTL1 are always assigned to two DSI * interfaces to support single FLUSH feature (Flush CTL0 and CTL1 when * only write into CTL0's FLUSH register) to keep two DSI pipes in sync. * Single FLUSH is supported from hw rev v3.0. */ for (c = 0; c < ARRAY_SIZE(hw_cfg->intf.connect); c++) if (hw_cfg->intf.connect[c] == INTF_DSI) dsi_cnt++; if ((rev >= 3) && (dsi_cnt > 1)) { ctl_mgr->single_flush_supported = true; /* Reserve CTL0/1 for INTF1/2 */ ctl_mgr->ctls[0].status |= CTL_STAT_BOOKED; ctl_mgr->ctls[1].status |= CTL_STAT_BOOKED; } spin_unlock_irqrestore(&ctl_mgr->pool_lock, flags); DBG("Pool of %d CTLs created.", ctl_mgr->nctl); return ctl_mgr; fail: if (ctl_mgr) mdp5_ctlm_destroy(ctl_mgr); return ERR_PTR(ret); }