int msm_hdmi_pll_8960_init(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct hdmi_pll_8960 *pll; struct clk *clk; int i; /* sanity check: */ for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++) if (WARN_ON(freqtbl[i].rate < freqtbl[i + 1].rate)) return -EINVAL; pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); if (!pll) return -ENOMEM; pll->mmio = msm_ioremap(pdev, "hdmi_pll", "HDMI_PLL"); if (IS_ERR(pll->mmio)) { dev_err(dev, "failed to map pll base\n"); return -ENOMEM; } pll->pdev = pdev; pll->clk_hw.init = &pll_init; clk = devm_clk_register(dev, &pll->clk_hw); if (IS_ERR(clk)) { dev_err(dev, "failed to register pll clock\n"); return -EINVAL; } return 0; }
struct hdmi_phy *hdmi_phy_8x74_init(struct hdmi *hdmi) { struct hdmi_phy_8x74 *phy_8x74; struct hdmi_phy *phy = NULL; int ret; phy_8x74 = kzalloc(sizeof(*phy_8x74), GFP_KERNEL); if (!phy_8x74) { ret = -ENOMEM; goto fail; } phy = &phy_8x74->base; phy->funcs = &hdmi_phy_8x74_funcs; phy_8x74->hdmi = hdmi; /* for 8x74, the phy mmio is mapped separately: */ phy_8x74->mmio = msm_ioremap(hdmi->pdev, "phy_physical", "HDMI_8x74"); if (IS_ERR(phy_8x74->mmio)) { ret = PTR_ERR(phy_8x74->mmio); goto fail; } return phy; fail: if (phy) hdmi_phy_8x74_destroy(phy); return ERR_PTR(ret); }
static int msm_hdmi_phy_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct hdmi_phy *phy; int ret; phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); if (!phy) return -ENODEV; phy->cfg = (struct hdmi_phy_cfg *)of_device_get_match_data(dev); if (!phy->cfg) return -ENODEV; phy->mmio = msm_ioremap(pdev, "hdmi_phy", "HDMI_PHY"); if (IS_ERR(phy->mmio)) { dev_err(dev, "%s: failed to map phy base\n", __func__); return -ENOMEM; } phy->pdev = pdev; ret = msm_hdmi_phy_resource_init(phy); if (ret) return ret; pm_runtime_enable(&pdev->dev); ret = msm_hdmi_phy_resource_enable(phy); if (ret) return ret; ret = msm_hdmi_phy_pll_init(pdev, phy->cfg->type); if (ret) { dev_err(dev, "couldn't init PLL\n"); msm_hdmi_phy_resource_disable(phy); return ret; } msm_hdmi_phy_resource_disable(phy); platform_set_drvdata(pdev, phy); return 0; }
struct msm_kms *mdp4_kms_init(struct drm_device *dev) { struct platform_device *pdev = to_platform_device(dev->dev); struct mdp4_platform_config *config = mdp4_get_config(pdev); struct mdp4_kms *mdp4_kms; struct msm_kms *kms = NULL; struct msm_gem_address_space *aspace; int irq, ret; mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL); if (!mdp4_kms) { dev_err(dev->dev, "failed to allocate kms\n"); ret = -ENOMEM; goto fail; } mdp_kms_init(&mdp4_kms->base, &kms_funcs); kms = &mdp4_kms->base.base; mdp4_kms->dev = dev; mdp4_kms->mmio = msm_ioremap(pdev, NULL, "MDP4"); if (IS_ERR(mdp4_kms->mmio)) { ret = PTR_ERR(mdp4_kms->mmio); goto fail; } irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = irq; dev_err(dev->dev, "failed to get irq: %d\n", ret); goto fail; } kms->irq = irq; /* NOTE: driver for this regulator still missing upstream.. use * _get_exclusive() and ignore the error if it does not exist * (and hope that the bootloader left it on for us) */ mdp4_kms->vdd = devm_regulator_get_exclusive(&pdev->dev, "vdd"); if (IS_ERR(mdp4_kms->vdd)) mdp4_kms->vdd = NULL; if (mdp4_kms->vdd) { ret = regulator_enable(mdp4_kms->vdd); if (ret) { dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret); goto fail; } } mdp4_kms->clk = devm_clk_get(&pdev->dev, "core_clk"); if (IS_ERR(mdp4_kms->clk)) { dev_err(dev->dev, "failed to get core_clk\n"); ret = PTR_ERR(mdp4_kms->clk); goto fail; } mdp4_kms->pclk = devm_clk_get(&pdev->dev, "iface_clk"); if (IS_ERR(mdp4_kms->pclk)) mdp4_kms->pclk = NULL; // XXX if (rev >= MDP_REV_42) { ??? mdp4_kms->lut_clk = devm_clk_get(&pdev->dev, "lut_clk"); if (IS_ERR(mdp4_kms->lut_clk)) { dev_err(dev->dev, "failed to get lut_clk\n"); ret = PTR_ERR(mdp4_kms->lut_clk); goto fail; } mdp4_kms->axi_clk = devm_clk_get(&pdev->dev, "bus_clk"); if (IS_ERR(mdp4_kms->axi_clk)) { dev_err(dev->dev, "failed to get axi_clk\n"); ret = PTR_ERR(mdp4_kms->axi_clk); goto fail; } clk_set_rate(mdp4_kms->clk, config->max_clk); clk_set_rate(mdp4_kms->lut_clk, config->max_clk); pm_runtime_enable(dev->dev); mdp4_kms->rpm_enabled = true; /* 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): */ mdp4_enable(mdp4_kms); mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0); mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0); mdp4_write(mdp4_kms, REG_MDP4_DSI_ENABLE, 0); mdp4_disable(mdp4_kms); mdelay(16); if (config->iommu) { aspace = msm_gem_address_space_create(&pdev->dev, config->iommu, "mdp4"); if (IS_ERR(aspace)) { ret = PTR_ERR(aspace); goto fail; } kms->aspace = aspace; ret = aspace->mmu->funcs->attach(aspace->mmu, iommu_ports, ARRAY_SIZE(iommu_ports)); if (ret) goto fail; } else { dev_info(dev->dev, "no iommu, fallback to phys " "contig buffers for scanout\n"); aspace = NULL; } ret = modeset_init(mdp4_kms); if (ret) { dev_err(dev->dev, "modeset_init failed: %d\n", ret); goto fail; } mdp4_kms->blank_cursor_bo = msm_gem_new(dev, SZ_16K, MSM_BO_WC); if (IS_ERR(mdp4_kms->blank_cursor_bo)) { ret = PTR_ERR(mdp4_kms->blank_cursor_bo); dev_err(dev->dev, "could not allocate blank-cursor bo: %d\n", ret); mdp4_kms->blank_cursor_bo = NULL; goto fail; } ret = msm_gem_get_iova(mdp4_kms->blank_cursor_bo, kms->aspace, &mdp4_kms->blank_cursor_iova); if (ret) { dev_err(dev->dev, "could not pin blank-cursor bo: %d\n", ret); goto fail; } dev->mode_config.min_width = 0; dev->mode_config.min_height = 0; dev->mode_config.max_width = 2048; dev->mode_config.max_height = 2048; return kms; fail: if (kms) mdp4_destroy(kms); return ERR_PTR(ret); }
int msm_edp_ctrl_init(struct msm_edp *edp) { struct edp_ctrl *ctrl = NULL; struct device *dev = &edp->pdev->dev; int ret; if (!edp) { pr_err("%s: edp is NULL!\n", __func__); return -EINVAL; } ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); if (!ctrl) return -ENOMEM; edp->ctrl = ctrl; ctrl->pdev = edp->pdev; ctrl->base = msm_ioremap(ctrl->pdev, "edp", "eDP"); if (IS_ERR(ctrl->base)) return PTR_ERR(ctrl->base); /* Get regulator, clock, gpio, pwm */ ret = edp_regulator_init(ctrl); if (ret) { pr_err("%s:regulator init fail\n", __func__); return ret; } ret = edp_clk_init(ctrl); if (ret) { pr_err("%s:clk init fail\n", __func__); return ret; } ret = edp_gpio_config(ctrl); if (ret) { pr_err("%s:failed to configure GPIOs: %d", __func__, ret); return ret; } /* Init aux and phy */ ctrl->aux = msm_edp_aux_init(dev, ctrl->base, &ctrl->drm_aux); if (!ctrl->aux || !ctrl->drm_aux) { pr_err("%s:failed to init aux\n", __func__); return -ENOMEM; } ctrl->phy = msm_edp_phy_init(dev, ctrl->base); if (!ctrl->phy) { pr_err("%s:failed to init phy\n", __func__); ret = -ENOMEM; goto err_destory_aux; } spin_lock_init(&ctrl->irq_lock); mutex_init(&ctrl->dev_mutex); init_completion(&ctrl->idle_comp); /* setup workqueue */ ctrl->workqueue = alloc_ordered_workqueue("edp_drm_work", 0); INIT_WORK(&ctrl->on_work, edp_ctrl_on_worker); INIT_WORK(&ctrl->off_work, edp_ctrl_off_worker); return 0; err_destory_aux: msm_edp_aux_destroy(dev, ctrl->aux); ctrl->aux = NULL; return ret; }
static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; struct mdp5_kms *mdp5_kms; struct mdp5_cfg *config; u32 major, minor; int ret; mdp5_kms = devm_kzalloc(&pdev->dev, sizeof(*mdp5_kms), GFP_KERNEL); if (!mdp5_kms) { ret = -ENOMEM; goto fail; } platform_set_drvdata(pdev, mdp5_kms); spin_lock_init(&mdp5_kms->resource_lock); mdp5_kms->dev = dev; mdp5_kms->pdev = pdev; drm_modeset_lock_init(&mdp5_kms->state_lock); mdp5_kms->state = kzalloc(sizeof(*mdp5_kms->state), GFP_KERNEL); if (!mdp5_kms->state) { ret = -ENOMEM; goto fail; } mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys", "MDP5"); if (IS_ERR(mdp5_kms->mmio)) { ret = PTR_ERR(mdp5_kms->mmio); goto fail; } /* mandatory clocks: */ ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus", true); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->ahb_clk, "iface", true); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->core_clk, "core", true); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->vsync_clk, "vsync", true); if (ret) goto fail; /* optional clocks: */ get_clk(pdev, &mdp5_kms->lut_clk, "lut", false); /* we need to set a default rate before enabling. Set a safe * rate first, then figure out hw revision, and then set a * more optimal rate: */ clk_set_rate(mdp5_kms->core_clk, 200000000); pm_runtime_enable(&pdev->dev); mdp5_kms->rpm_enabled = true; read_mdp_hw_revision(mdp5_kms, &major, &minor); mdp5_kms->cfg = mdp5_cfg_init(mdp5_kms, major, minor); if (IS_ERR(mdp5_kms->cfg)) { ret = PTR_ERR(mdp5_kms->cfg); mdp5_kms->cfg = NULL; goto fail; } config = mdp5_cfg_get_config(mdp5_kms->cfg); mdp5_kms->caps = config->hw->mdp.caps; /* TODO: compute core clock rate at runtime */ clk_set_rate(mdp5_kms->core_clk, config->hw->max_clk); /* * Some chipsets have a Shared Memory Pool (SMP), while others * have dedicated latency buffering per source pipe instead; * this section initializes the SMP: */ if (mdp5_kms->caps & MDP_CAP_SMP) { mdp5_kms->smp = mdp5_smp_init(mdp5_kms, &config->hw->smp); if (IS_ERR(mdp5_kms->smp)) { ret = PTR_ERR(mdp5_kms->smp); mdp5_kms->smp = NULL; goto fail; } } mdp5_kms->ctlm = mdp5_ctlm_init(dev, mdp5_kms->mmio, mdp5_kms->cfg); if (IS_ERR(mdp5_kms->ctlm)) { ret = PTR_ERR(mdp5_kms->ctlm); mdp5_kms->ctlm = NULL; goto fail; } ret = hwpipe_init(mdp5_kms); if (ret) goto fail; ret = hwmixer_init(mdp5_kms); if (ret) goto fail; ret = interface_init(mdp5_kms); if (ret) goto fail; /* set uninit-ed kms */ priv->kms = &mdp5_kms->base.base; return 0; fail: mdp5_destroy(pdev); return ret; }
/* construct hdmi at bind/probe time, grab all the resources. If * we are to EPROBE_DEFER we want to do it here, rather than later * at modeset_init() time */ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) { struct hdmi_platform_config *config = pdev->dev.platform_data; struct hdmi *hdmi = NULL; struct resource *res; int i, ret; hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); if (!hdmi) { ret = -ENOMEM; goto fail; } hdmi->pdev = pdev; hdmi->config = config; spin_lock_init(&hdmi->reg_lock); hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI"); if (IS_ERR(hdmi->mmio)) { ret = PTR_ERR(hdmi->mmio); goto fail; } /* HDCP needs physical address of hdmi register */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, config->mmio_name); hdmi->mmio_phy_addr = res->start; hdmi->qfprom_mmio = msm_ioremap(pdev, config->qfprom_mmio_name, "HDMI_QFPROM"); if (IS_ERR(hdmi->qfprom_mmio)) { dev_info(&pdev->dev, "can't find qfprom resource\n"); hdmi->qfprom_mmio = NULL; } hdmi->hpd_regs = devm_kzalloc(&pdev->dev, sizeof(hdmi->hpd_regs[0]) * config->hpd_reg_cnt, GFP_KERNEL); if (!hdmi->hpd_regs) { ret = -ENOMEM; goto fail; } for (i = 0; i < config->hpd_reg_cnt; i++) { struct regulator *reg; reg = devm_regulator_get(&pdev->dev, config->hpd_reg_names[i]); if (IS_ERR(reg)) { ret = PTR_ERR(reg); dev_err(&pdev->dev, "failed to get hpd regulator: %s (%d)\n", config->hpd_reg_names[i], ret); goto fail; } hdmi->hpd_regs[i] = reg; } hdmi->pwr_regs = devm_kzalloc(&pdev->dev, sizeof(hdmi->pwr_regs[0]) * config->pwr_reg_cnt, GFP_KERNEL); if (!hdmi->pwr_regs) { ret = -ENOMEM; goto fail; } for (i = 0; i < config->pwr_reg_cnt; i++) { struct regulator *reg; reg = devm_regulator_get(&pdev->dev, config->pwr_reg_names[i]); if (IS_ERR(reg)) { ret = PTR_ERR(reg); dev_err(&pdev->dev, "failed to get pwr regulator: %s (%d)\n", config->pwr_reg_names[i], ret); goto fail; } hdmi->pwr_regs[i] = reg; } hdmi->hpd_clks = devm_kzalloc(&pdev->dev, sizeof(hdmi->hpd_clks[0]) * config->hpd_clk_cnt, GFP_KERNEL); if (!hdmi->hpd_clks) { ret = -ENOMEM; goto fail; } for (i = 0; i < config->hpd_clk_cnt; i++) { struct clk *clk; clk = msm_clk_get(pdev, config->hpd_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "failed to get hpd clk: %s (%d)\n", config->hpd_clk_names[i], ret); goto fail; } hdmi->hpd_clks[i] = clk; } hdmi->pwr_clks = devm_kzalloc(&pdev->dev, sizeof(hdmi->pwr_clks[0]) * config->pwr_clk_cnt, GFP_KERNEL); if (!hdmi->pwr_clks) { ret = -ENOMEM; goto fail; } for (i = 0; i < config->pwr_clk_cnt; i++) { struct clk *clk; clk = msm_clk_get(pdev, config->pwr_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "failed to get pwr clk: %s (%d)\n", config->pwr_clk_names[i], ret); goto fail; } hdmi->pwr_clks[i] = clk; } pm_runtime_enable(&pdev->dev); hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); hdmi->i2c = msm_hdmi_i2c_init(hdmi); if (IS_ERR(hdmi->i2c)) { ret = PTR_ERR(hdmi->i2c); dev_err(&pdev->dev, "failed to get i2c: %d\n", ret); hdmi->i2c = NULL; goto fail; } ret = msm_hdmi_get_phy(hdmi); if (ret) { dev_err(&pdev->dev, "failed to get phy\n"); goto fail; } hdmi->hdcp_ctrl = msm_hdmi_hdcp_init(hdmi); if (IS_ERR(hdmi->hdcp_ctrl)) { dev_warn(&pdev->dev, "failed to init hdcp: disabled\n"); hdmi->hdcp_ctrl = NULL; } return hdmi; fail: if (hdmi) msm_hdmi_destroy(hdmi); return ERR_PTR(ret); }
/* construct hdmi at bind/probe time, grab all the resources. If * we are to EPROBE_DEFER we want to do it here, rather than later * at modeset_init() time */ static struct hdmi *hdmi_init(struct platform_device *pdev) { struct hdmi_platform_config *config = pdev->dev.platform_data; struct hdmi *hdmi = NULL; int i, ret; hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); if (!hdmi) { ret = -ENOMEM; goto fail; } hdmi->pdev = pdev; hdmi->config = config; /* not sure about which phy maps to which msm.. probably I miss some */ if (config->phy_init) hdmi->phy = config->phy_init(hdmi); else hdmi->phy = ERR_PTR(-ENXIO); if (IS_ERR(hdmi->phy)) { ret = PTR_ERR(hdmi->phy); dev_err(&pdev->dev, "failed to load phy: %d\n", ret); hdmi->phy = NULL; goto fail; } hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI"); if (IS_ERR(hdmi->mmio)) { ret = PTR_ERR(hdmi->mmio); goto fail; } BUG_ON(config->hpd_reg_cnt > ARRAY_SIZE(hdmi->hpd_regs)); for (i = 0; i < config->hpd_reg_cnt; i++) { struct regulator *reg; reg = devm_regulator_get(&pdev->dev, config->hpd_reg_names[i]); if (IS_ERR(reg)) { ret = PTR_ERR(reg); dev_err(&pdev->dev, "failed to get hpd regulator: %s (%d)\n", config->hpd_reg_names[i], ret); goto fail; } hdmi->hpd_regs[i] = reg; } BUG_ON(config->pwr_reg_cnt > ARRAY_SIZE(hdmi->pwr_regs)); for (i = 0; i < config->pwr_reg_cnt; i++) { struct regulator *reg; reg = devm_regulator_get(&pdev->dev, config->pwr_reg_names[i]); if (IS_ERR(reg)) { ret = PTR_ERR(reg); dev_err(&pdev->dev, "failed to get pwr regulator: %s (%d)\n", config->pwr_reg_names[i], ret); goto fail; } hdmi->pwr_regs[i] = reg; } BUG_ON(config->hpd_clk_cnt > ARRAY_SIZE(hdmi->hpd_clks)); for (i = 0; i < config->hpd_clk_cnt; i++) { struct clk *clk; clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "failed to get hpd clk: %s (%d)\n", config->hpd_clk_names[i], ret); goto fail; } hdmi->hpd_clks[i] = clk; } BUG_ON(config->pwr_clk_cnt > ARRAY_SIZE(hdmi->pwr_clks)); for (i = 0; i < config->pwr_clk_cnt; i++) { struct clk *clk; clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "failed to get pwr clk: %s (%d)\n", config->pwr_clk_names[i], ret); goto fail; } hdmi->pwr_clks[i] = clk; } hdmi->i2c = hdmi_i2c_init(hdmi); if (IS_ERR(hdmi->i2c)) { ret = PTR_ERR(hdmi->i2c); dev_err(&pdev->dev, "failed to get i2c: %d\n", ret); hdmi->i2c = NULL; goto fail; } return hdmi; fail: if (hdmi) hdmi_destroy(hdmi); return ERR_PTR(ret); }
int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs, const char *name, const char *ioname, const char *irqname, int ringsz) { int i, ret; gpu->dev = drm; gpu->funcs = funcs; gpu->name = name; INIT_LIST_HEAD(&gpu->active_list); INIT_WORK(&gpu->retire_work, retire_worker); INIT_WORK(&gpu->recover_work, recover_worker); setup_timer(&gpu->hangcheck_timer, hangcheck_handler, (unsigned long)gpu); BUG_ON(ARRAY_SIZE(clk_names) != ARRAY_SIZE(gpu->grp_clks)); /* Map registers: */ gpu->mmio = msm_ioremap(pdev, ioname, name); if (IS_ERR(gpu->mmio)) { ret = PTR_ERR(gpu->mmio); goto fail; } /* Get Interrupt: */ gpu->irq = platform_get_irq_byname(pdev, irqname); if (gpu->irq < 0) { ret = gpu->irq; dev_err(drm->dev, "failed to get irq: %d\n", ret); goto fail; } ret = devm_request_irq(&pdev->dev, gpu->irq, irq_handler, IRQF_TRIGGER_HIGH, gpu->name, gpu); if (ret) { dev_err(drm->dev, "failed to request IRQ%u: %d\n", gpu->irq, ret); goto fail; } /* Acquire clocks: */ for (i = 0; i < ARRAY_SIZE(clk_names); i++) { gpu->grp_clks[i] = devm_clk_get(&pdev->dev, clk_names[i]); DBG("grp_clks[%s]: %p", clk_names[i], gpu->grp_clks[i]); if (IS_ERR(gpu->grp_clks[i])) gpu->grp_clks[i] = NULL; } gpu->ebi1_clk = devm_clk_get(&pdev->dev, "bus_clk"); DBG("ebi1_clk: %p", gpu->ebi1_clk); if (IS_ERR(gpu->ebi1_clk)) gpu->ebi1_clk = NULL; /* Acquire regulators: */ gpu->gpu_reg = devm_regulator_get(&pdev->dev, "vdd"); DBG("gpu_reg: %p", gpu->gpu_reg); if (IS_ERR(gpu->gpu_reg)) gpu->gpu_reg = NULL; gpu->gpu_cx = devm_regulator_get(&pdev->dev, "vddcx"); DBG("gpu_cx: %p", gpu->gpu_cx); if (IS_ERR(gpu->gpu_cx)) gpu->gpu_cx = NULL; /* Setup IOMMU.. eventually we will (I think) do this once per context * and have separate page tables per context. For now, to keep things * simple and to get something working, just use a single address space: */ gpu->iommu = iommu_domain_alloc(&platform_bus_type); if (!gpu->iommu) { dev_err(drm->dev, "failed to allocate IOMMU\n"); ret = -ENOMEM; goto fail; } gpu->id = msm_register_iommu(drm, gpu->iommu); /* Create ringbuffer: */ gpu->rb = msm_ringbuffer_new(gpu, ringsz); if (IS_ERR(gpu->rb)) { ret = PTR_ERR(gpu->rb); gpu->rb = NULL; dev_err(drm->dev, "could not create ringbuffer: %d\n", ret); goto fail; } ret = msm_gem_get_iova_locked(gpu->rb->bo, gpu->id, &gpu->rb_iova); if (ret) { gpu->rb_iova = 0; dev_err(drm->dev, "could not map ringbuffer: %d\n", ret); goto fail; } bs_init(gpu, pdev); return 0; fail: return ret; }
struct msm_kms *mdp5_kms_init(struct drm_device *dev) { struct platform_device *pdev = dev->platformdev; struct mdp5_cfg *config; struct mdp5_kms *mdp5_kms; struct msm_kms *kms = NULL; struct msm_mmu *mmu; uint32_t major, minor; int i, ret; mdp5_kms = kzalloc(sizeof(*mdp5_kms), GFP_KERNEL); if (!mdp5_kms) { dev_err(dev->dev, "failed to allocate kms\n"); ret = -ENOMEM; goto fail; } spin_lock_init(&mdp5_kms->resource_lock); mdp_kms_init(&mdp5_kms->base, &kms_funcs); kms = &mdp5_kms->base.base; mdp5_kms->dev = dev; /* mdp5_kms->mmio actually represents the MDSS base address */ mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys", "MDP5"); if (IS_ERR(mdp5_kms->mmio)) { ret = PTR_ERR(mdp5_kms->mmio); goto fail; } mdp5_kms->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); if (IS_ERR(mdp5_kms->vbif)) { ret = PTR_ERR(mdp5_kms->vbif); goto fail; } mdp5_kms->vdd = devm_regulator_get(&pdev->dev, "vdd"); if (IS_ERR(mdp5_kms->vdd)) { ret = PTR_ERR(mdp5_kms->vdd); goto fail; } ret = regulator_enable(mdp5_kms->vdd); if (ret) { dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret); goto fail; } ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus_clk"); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->ahb_clk, "iface_clk"); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->src_clk, "core_clk_src"); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->core_clk, "core_clk"); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->lut_clk, "lut_clk"); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->vsync_clk, "vsync_clk"); if (ret) goto fail; /* we need to set a default rate before enabling. Set a safe * rate first, then figure out hw revision, and then set a * more optimal rate: */ clk_set_rate(mdp5_kms->src_clk, 200000000); read_hw_revision(mdp5_kms, &major, &minor); mdp5_kms->cfg = mdp5_cfg_init(mdp5_kms, major, minor); if (IS_ERR(mdp5_kms->cfg)) { ret = PTR_ERR(mdp5_kms->cfg); mdp5_kms->cfg = NULL; goto fail; } config = mdp5_cfg_get_config(mdp5_kms->cfg); /* TODO: compute core clock rate at runtime */ clk_set_rate(mdp5_kms->src_clk, config->hw->max_clk); mdp5_kms->smp = mdp5_smp_init(mdp5_kms->dev, &config->hw->smp); if (IS_ERR(mdp5_kms->smp)) { ret = PTR_ERR(mdp5_kms->smp); mdp5_kms->smp = NULL; goto fail; } mdp5_kms->ctlm = mdp5_ctlm_init(dev, mdp5_kms->mmio, config->hw); if (IS_ERR(mdp5_kms->ctlm)) { ret = PTR_ERR(mdp5_kms->ctlm); mdp5_kms->ctlm = NULL; goto fail; } /* 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 (!config->hw->intf.base[i] || mdp5_cfg_intf_is_virtual(config->hw->intfs[i])) continue; mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(i), 0); } 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(dev->dev, "failed to init iommu: %d\n", ret); goto fail; } ret = mmu->funcs->attach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports)); if (ret) { dev_err(dev->dev, "failed to attach iommu: %d\n", ret); mmu->funcs->destroy(mmu); goto fail; } } else { dev_info(dev->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(dev->dev, "failed to register mdp5 iommu: %d\n", ret); goto fail; } ret = modeset_init(mdp5_kms); if (ret) { dev_err(dev->dev, "modeset_init failed: %d\n", ret); goto fail; } return kms; fail: if (kms) mdp5_destroy(kms); return ERR_PTR(ret); }
struct msm_kms *mdp5_kms_init(struct drm_device *dev) { struct platform_device *pdev = dev->platformdev; struct mdp5_platform_config *config = mdp5_get_config(pdev); struct mdp5_kms *mdp5_kms; struct msm_kms *kms = NULL; struct msm_mmu *mmu; int ret; mdp5_kms = kzalloc(sizeof(*mdp5_kms), GFP_KERNEL); if (!mdp5_kms) { dev_err(dev->dev, "failed to allocate kms\n"); ret = -ENOMEM; goto fail; } mdp_kms_init(&mdp5_kms->base, &kms_funcs); kms = &mdp5_kms->base.base; mdp5_kms->dev = dev; mdp5_kms->smp_blk_cnt = config->smp_blk_cnt; mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys", "MDP5"); if (IS_ERR(mdp5_kms->mmio)) { ret = PTR_ERR(mdp5_kms->mmio); goto fail; } mdp5_kms->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); if (IS_ERR(mdp5_kms->vbif)) { ret = PTR_ERR(mdp5_kms->vbif); goto fail; } mdp5_kms->vdd = devm_regulator_get(&pdev->dev, "vdd"); if (IS_ERR(mdp5_kms->vdd)) { ret = PTR_ERR(mdp5_kms->vdd); goto fail; } ret = regulator_enable(mdp5_kms->vdd); if (ret) { dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret); goto fail; } ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus_clk"); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->ahb_clk, "iface_clk"); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->src_clk, "core_clk_src"); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->core_clk, "core_clk"); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->lut_clk, "lut_clk"); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->vsync_clk, "vsync_clk"); if (ret) goto fail; ret = clk_set_rate(mdp5_kms->src_clk, config->max_clk); /* 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); mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(0), 0); mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(1), 0); mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(2), 0); mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(3), 0); mdp5_disable(mdp5_kms); mdelay(16); if (config->iommu) { mmu = msm_iommu_new(dev, config->iommu); if (IS_ERR(mmu)) { ret = PTR_ERR(mmu); goto fail; } ret = mmu->funcs->attach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports)); if (ret) goto fail; } else { dev_info(dev->dev, "no iommu, fallback to phys " "contig buffers for scanout\n"); mmu = NULL; } mdp5_kms->id = msm_register_mmu(dev, mmu); if (mdp5_kms->id < 0) { ret = mdp5_kms->id; dev_err(dev->dev, "failed to register mdp5 iommu: %d\n", ret); goto fail; } ret = modeset_init(mdp5_kms); if (ret) { dev_err(dev->dev, "modeset_init failed: %d\n", ret); goto fail; } return kms; fail: if (kms) mdp5_destroy(kms); return ERR_PTR(ret); }
struct msm_kms *mdp4_kms_init(struct drm_device *dev) { struct platform_device *pdev = dev->platformdev; struct mdp4_platform_config *config = mdp4_get_config(pdev); struct mdp4_kms *mdp4_kms; struct msm_kms *kms = NULL; struct msm_mmu *mmu; int ret; mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL); if (!mdp4_kms) { dev_err(dev->dev, "failed to allocate kms\n"); ret = -ENOMEM; goto fail; } mdp_kms_init(&mdp4_kms->base, &kms_funcs); kms = &mdp4_kms->base.base; mdp4_kms->dev = dev; mdp4_kms->mmio = msm_ioremap(pdev, NULL, "MDP4"); if (IS_ERR(mdp4_kms->mmio)) { ret = PTR_ERR(mdp4_kms->mmio); goto fail; } mdp4_kms->dsi_pll_vdda = devm_regulator_get_optional(&pdev->dev, "dsi_pll_vdda"); if (IS_ERR(mdp4_kms->dsi_pll_vdda)) mdp4_kms->dsi_pll_vdda = NULL; mdp4_kms->dsi_pll_vddio = devm_regulator_get_optional(&pdev->dev, "dsi_pll_vddio"); if (IS_ERR(mdp4_kms->dsi_pll_vddio)) mdp4_kms->dsi_pll_vddio = NULL; mdp4_kms->vdd = devm_regulator_get_exclusive(&pdev->dev, "vdd"); if (IS_ERR(mdp4_kms->vdd)) mdp4_kms->vdd = NULL; if (mdp4_kms->vdd) { ret = regulator_enable(mdp4_kms->vdd); if (ret) { dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret); goto fail; } } mdp4_kms->clk = devm_clk_get(&pdev->dev, "core_clk"); if (IS_ERR(mdp4_kms->clk)) { dev_err(dev->dev, "failed to get core_clk\n"); ret = PTR_ERR(mdp4_kms->clk); goto fail; } mdp4_kms->pclk = devm_clk_get(&pdev->dev, "iface_clk"); if (IS_ERR(mdp4_kms->pclk)) mdp4_kms->pclk = NULL; // XXX if (rev >= MDP_REV_42) { ??? mdp4_kms->lut_clk = devm_clk_get(&pdev->dev, "lut_clk"); if (IS_ERR(mdp4_kms->lut_clk)) { dev_err(dev->dev, "failed to get lut_clk\n"); ret = PTR_ERR(mdp4_kms->lut_clk); goto fail; } mdp4_kms->axi_clk = devm_clk_get(&pdev->dev, "mdp_axi_clk"); if (IS_ERR(mdp4_kms->axi_clk)) { dev_err(dev->dev, "failed to get axi_clk\n"); ret = PTR_ERR(mdp4_kms->axi_clk); goto fail; } clk_set_rate(mdp4_kms->clk, config->max_clk); clk_set_rate(mdp4_kms->lut_clk, config->max_clk); /* 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): */ mdp4_enable(mdp4_kms); mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0); mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0); mdp4_write(mdp4_kms, REG_MDP4_DSI_ENABLE, 0); mdp4_disable(mdp4_kms); mdelay(16); if (config->iommu) { mmu = msm_iommu_new(&pdev->dev, config->iommu); if (IS_ERR(mmu)) { ret = PTR_ERR(mmu); goto fail; } ret = mmu->funcs->attach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports)); if (ret) goto fail; } else { dev_info(dev->dev, "no iommu, fallback to phys " "contig buffers for scanout\n"); mmu = NULL; } mdp4_kms->id = msm_register_mmu(dev, mmu); if (mdp4_kms->id < 0) { ret = mdp4_kms->id; dev_err(dev->dev, "failed to register mdp4 iommu: %d\n", ret); goto fail; } ret = modeset_init(mdp4_kms); if (ret) { dev_err(dev->dev, "modeset_init failed: %d\n", ret); goto fail; } mutex_lock(&dev->struct_mutex); mdp4_kms->blank_cursor_bo = msm_gem_new(dev, SZ_16K, MSM_BO_WC); mutex_unlock(&dev->struct_mutex); if (IS_ERR(mdp4_kms->blank_cursor_bo)) { ret = PTR_ERR(mdp4_kms->blank_cursor_bo); dev_err(dev->dev, "could not allocate blank-cursor bo: %d\n", ret); mdp4_kms->blank_cursor_bo = NULL; goto fail; } ret = msm_gem_get_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id, &mdp4_kms->blank_cursor_iova); if (ret) { dev_err(dev->dev, "could not pin blank-cursor bo: %d\n", ret); goto fail; } return kms; fail: if (kms) mdp4_destroy(kms); return ERR_PTR(ret); }
/* initialize connector */ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) { struct hdmi *hdmi = NULL; struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = priv->hdmi_pdev; struct hdmi_platform_config *config; int i, ret; if (!pdev) { dev_err(dev->dev, "no hdmi device\n"); ret = -ENXIO; goto fail; } config = pdev->dev.platform_data; hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL); if (!hdmi) { ret = -ENOMEM; goto fail; } kref_init(&hdmi->refcount); hdmi->dev = dev; hdmi->pdev = pdev; hdmi->config = config; hdmi->encoder = encoder; /* not sure about which phy maps to which msm.. probably I miss some */ if (config->phy_init) hdmi->phy = config->phy_init(hdmi); else hdmi->phy = ERR_PTR(-ENXIO); if (IS_ERR(hdmi->phy)) { ret = PTR_ERR(hdmi->phy); dev_err(dev->dev, "failed to load phy: %d\n", ret); hdmi->phy = NULL; goto fail; } hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI"); if (IS_ERR(hdmi->mmio)) { ret = PTR_ERR(hdmi->mmio); goto fail; } BUG_ON(config->hpd_reg_cnt > ARRAY_SIZE(hdmi->hpd_regs)); for (i = 0; i < config->hpd_reg_cnt; i++) { struct regulator *reg; reg = devm_regulator_get(&pdev->dev, config->hpd_reg_names[i]); if (IS_ERR(reg)) { ret = PTR_ERR(reg); dev_err(dev->dev, "failed to get hpd regulator: %s (%d)\n", config->hpd_reg_names[i], ret); goto fail; } hdmi->hpd_regs[i] = reg; } BUG_ON(config->pwr_reg_cnt > ARRAY_SIZE(hdmi->pwr_regs)); for (i = 0; i < config->pwr_reg_cnt; i++) { struct regulator *reg; reg = devm_regulator_get(&pdev->dev, config->pwr_reg_names[i]); if (IS_ERR(reg)) { ret = PTR_ERR(reg); dev_err(dev->dev, "failed to get pwr regulator: %s (%d)\n", config->pwr_reg_names[i], ret); goto fail; } hdmi->pwr_regs[i] = reg; } BUG_ON(config->hpd_clk_cnt > ARRAY_SIZE(hdmi->hpd_clks)); for (i = 0; i < config->hpd_clk_cnt; i++) { struct clk *clk; clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(dev->dev, "failed to get hpd clk: %s (%d)\n", config->hpd_clk_names[i], ret); goto fail; } hdmi->hpd_clks[i] = clk; } BUG_ON(config->pwr_clk_cnt > ARRAY_SIZE(hdmi->pwr_clks)); for (i = 0; i < config->pwr_clk_cnt; i++) { struct clk *clk; clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(dev->dev, "failed to get pwr clk: %s (%d)\n", config->pwr_clk_names[i], ret); goto fail; } hdmi->pwr_clks[i] = clk; } hdmi->i2c = hdmi_i2c_init(hdmi); if (IS_ERR(hdmi->i2c)) { ret = PTR_ERR(hdmi->i2c); dev_err(dev->dev, "failed to get i2c: %d\n", ret); hdmi->i2c = NULL; goto fail; } hdmi->bridge = hdmi_bridge_init(hdmi); if (IS_ERR(hdmi->bridge)) { ret = PTR_ERR(hdmi->bridge); dev_err(dev->dev, "failed to create HDMI bridge: %d\n", ret); hdmi->bridge = NULL; goto fail; } hdmi->connector = hdmi_connector_init(hdmi); if (IS_ERR(hdmi->connector)) { ret = PTR_ERR(hdmi->connector); dev_err(dev->dev, "failed to create HDMI connector: %d\n", ret); hdmi->connector = NULL; goto fail; } if (!config->shared_irq) { hdmi->irq = platform_get_irq(pdev, 0); if (hdmi->irq < 0) { ret = hdmi->irq; dev_err(dev->dev, "failed to get irq: %d\n", ret); goto fail; } ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq, NULL, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "hdmi_isr", hdmi); if (ret < 0) { dev_err(dev->dev, "failed to request IRQ%u: %d\n", hdmi->irq, ret); goto fail; } } encoder->bridge = hdmi->bridge; priv->bridges[priv->num_bridges++] = hdmi->bridge; priv->connectors[priv->num_connectors++] = hdmi->connector; return hdmi; fail: if (hdmi) { /* bridge/connector are normally destroyed by drm: */ if (hdmi->bridge) hdmi->bridge->funcs->destroy(hdmi->bridge); if (hdmi->connector) hdmi->connector->funcs->destroy(hdmi->connector); hdmi_destroy(&hdmi->refcount); } return ERR_PTR(ret); }
int msm_mdss_init(struct drm_device *dev) { struct platform_device *pdev = to_platform_device(dev->dev); struct msm_drm_private *priv = dev->dev_private; struct msm_mdss *mdss; int ret; DBG(""); if (!of_device_is_compatible(dev->dev->of_node, "qcom,mdss")) return 0; mdss = devm_kzalloc(dev->dev, sizeof(*mdss), GFP_KERNEL); if (!mdss) { ret = -ENOMEM; goto fail; } mdss->dev = dev; mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS"); if (IS_ERR(mdss->mmio)) { ret = PTR_ERR(mdss->mmio); goto fail; } mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); if (IS_ERR(mdss->vbif)) { ret = PTR_ERR(mdss->vbif); goto fail; } /* Regulator to enable GDSCs in downstream kernels */ mdss->vdd = devm_regulator_get(dev->dev, "vdd"); if (IS_ERR(mdss->vdd)) { ret = PTR_ERR(mdss->vdd); goto fail; } ret = regulator_enable(mdss->vdd); if (ret) { dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret); goto fail; } ret = devm_request_irq(dev->dev, platform_get_irq(pdev, 0), mdss_irq, 0, "mdss_isr", mdss); if (ret) { dev_err(dev->dev, "failed to init irq: %d\n", ret); goto fail_irq; } ret = mdss_irq_domain_init(mdss); if (ret) { dev_err(dev->dev, "failed to init sub-block irqs: %d\n", ret); goto fail_irq; } priv->mdss = mdss; pm_runtime_enable(dev->dev); /* * TODO: This is needed as the MDSS GDSC is only tied to MDSS's power * domain. Remove this once runtime PM is adapted for all the devices. */ pm_runtime_get_sync(dev->dev); return 0; fail_irq: regulator_disable(mdss->vdd); fail: return ret; }
struct msm_kms *mdp5_kms_init(struct drm_device *dev) { struct platform_device *pdev = dev->platformdev; struct mdp5_cfg *config; struct mdp5_kms *mdp5_kms; struct msm_kms *kms = NULL; struct msm_mmu *mmu; uint32_t major, minor; int i, ret; mdp5_kms = kzalloc(sizeof(*mdp5_kms), GFP_KERNEL); if (!mdp5_kms) { dev_err(dev->dev, "failed to allocate kms\n"); ret = -ENOMEM; goto fail; } spin_lock_init(&mdp5_kms->resource_lock); mdp_kms_init(&mdp5_kms->base, &kms_funcs); kms = &mdp5_kms->base.base; mdp5_kms->dev = dev; /* mdp5_kms->mmio actually represents the MDSS base address */ mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys", "MDP5"); if (IS_ERR(mdp5_kms->mmio)) { ret = PTR_ERR(mdp5_kms->mmio); goto fail; } mdp5_kms->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); if (IS_ERR(mdp5_kms->vbif)) { ret = PTR_ERR(mdp5_kms->vbif); goto fail; } mdp5_kms->vdd = devm_regulator_get(&pdev->dev, "vdd"); if (IS_ERR(mdp5_kms->vdd)) { ret = PTR_ERR(mdp5_kms->vdd); goto fail; } ret = regulator_enable(mdp5_kms->vdd); if (ret) { dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret); goto fail; } /* mandatory clocks: */ ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus_clk", true); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->ahb_clk, "iface_clk", true); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->src_clk, "core_clk_src", true); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->core_clk, "core_clk", true); if (ret) goto fail; ret = get_clk(pdev, &mdp5_kms->vsync_clk, "vsync_clk", true); if (ret) goto fail; /* optional clocks: */ get_clk(pdev, &mdp5_kms->lut_clk, "lut_clk", false); /* we need to set a default rate before enabling. Set a safe * rate first, then figure out hw revision, and then set a * more optimal rate: */ clk_set_rate(mdp5_kms->src_clk, 200000000); read_hw_revision(mdp5_kms, &major, &minor); mdp5_kms->cfg = mdp5_cfg_init(mdp5_kms, major, minor); if (IS_ERR(mdp5_kms->cfg)) { ret = PTR_ERR(mdp5_kms->cfg); mdp5_kms->cfg = NULL; goto fail; } config = mdp5_cfg_get_config(mdp5_kms->cfg); mdp5_kms->caps = config->hw->mdp.caps; /* TODO: compute core clock rate at runtime */ clk_set_rate(mdp5_kms->src_clk, config->hw->max_clk); /* * Some chipsets have a Shared Memory Pool (SMP), while others * have dedicated latency buffering per source pipe instead; * this section initializes the SMP: */ if (mdp5_kms->caps & MDP_CAP_SMP) { mdp5_kms->smp = mdp5_smp_init(mdp5_kms->dev, &config->hw->smp); if (IS_ERR(mdp5_kms->smp)) { ret = PTR_ERR(mdp5_kms->smp); mdp5_kms->smp = NULL; goto fail; } } mdp5_kms->ctlm = mdp5_ctlm_init(dev, mdp5_kms->mmio, mdp5_kms->cfg); if (IS_ERR(mdp5_kms->ctlm)) { ret = PTR_ERR(mdp5_kms->ctlm); mdp5_kms->ctlm = NULL; goto fail; } /* 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(dev->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(dev->dev, "failed to attach iommu: %d\n", ret); mmu->funcs->destroy(mmu); goto fail; } } else { dev_info(dev->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(dev->dev, "failed to register mdp5 iommu: %d\n", ret); goto fail; } ret = modeset_init(mdp5_kms); if (ret) { dev_err(dev->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_destroy(kms); return ERR_PTR(ret); }