Message ID | 20180709173200.238457-10-seanpaul@chromium.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Monday 09 July 2018 11:01 PM, Sean Paul wrote: > From: Rajesh Yadav <ryadav@codeaurora.org> > > SoCs having mdp5 or dpu have identical tree like > device hierarchy where MDSS top level wrapper manages > common power resources for all child devices. > > Subclass msm_mdss so that msm_mdss includes common defines > and mdp5/dpu mdss derivations to include any extensions. > > Add mdss helper interface (msm_mdss_funcs) to msm_mdss > base for mdp5/dpu mdss specific implementation calls. > > This change subclasses msm_mdss for mdp5, dpu specific > changes will be done separately. Reviewed-by: Archit Taneja <architt@codeaurora.org> > > Changes in v3: > - none > > Changes in v2: > - fixed indentation for irq_domain_add_linear call (Sean Paul) > > Signed-off-by: Rajesh Yadav <ryadav@codeaurora.org> > Reviewed-by: Sean Paul <seanpaul@chromium.org> > [seanpaul rebased on msm-next and resolved conflicts] > Signed-off-by: Sean Paul <seanpaul@chromium.org> > --- > drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c | 154 ++++++++++++---------- > drivers/gpu/drm/msm/msm_drv.c | 22 +++- > drivers/gpu/drm/msm/msm_kms.h | 17 ++- > 3 files changed, 109 insertions(+), 84 deletions(-) > > diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c > index f2a0db7a8a03..1cc4e57f0226 100644 > --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c > +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c > @@ -20,12 +20,10 @@ > #include "msm_drv.h" > #include "mdp5_kms.h" > > -/* > - * If needed, this can become more specific: something like struct mdp5_mdss, > - * which contains a 'struct msm_mdss base' member. > - */ > -struct msm_mdss { > - struct drm_device *dev; > +#define to_mdp5_mdss(x) container_of(x, struct mdp5_mdss, base) > + > +struct mdp5_mdss { > + struct msm_mdss base; > > void __iomem *mmio, *vbif; > > @@ -41,22 +39,22 @@ struct msm_mdss { > } irqcontroller; > }; > > -static inline void mdss_write(struct msm_mdss *mdss, u32 reg, u32 data) > +static inline void mdss_write(struct mdp5_mdss *mdp5_mdss, u32 reg, u32 data) > { > - msm_writel(data, mdss->mmio + reg); > + msm_writel(data, mdp5_mdss->mmio + reg); > } > > -static inline u32 mdss_read(struct msm_mdss *mdss, u32 reg) > +static inline u32 mdss_read(struct mdp5_mdss *mdp5_mdss, u32 reg) > { > - return msm_readl(mdss->mmio + reg); > + return msm_readl(mdp5_mdss->mmio + reg); > } > > static irqreturn_t mdss_irq(int irq, void *arg) > { > - struct msm_mdss *mdss = arg; > + struct mdp5_mdss *mdp5_mdss = arg; > u32 intr; > > - intr = mdss_read(mdss, REG_MDSS_HW_INTR_STATUS); > + intr = mdss_read(mdp5_mdss, REG_MDSS_HW_INTR_STATUS); > > VERB("intr=%08x", intr); > > @@ -64,7 +62,7 @@ static irqreturn_t mdss_irq(int irq, void *arg) > irq_hw_number_t hwirq = fls(intr) - 1; > > generic_handle_irq(irq_find_mapping( > - mdss->irqcontroller.domain, hwirq)); > + mdp5_mdss->irqcontroller.domain, hwirq)); > intr &= ~(1 << hwirq); > } > > @@ -84,19 +82,19 @@ static irqreturn_t mdss_irq(int irq, void *arg) > > static void mdss_hw_mask_irq(struct irq_data *irqd) > { > - struct msm_mdss *mdss = irq_data_get_irq_chip_data(irqd); > + struct mdp5_mdss *mdp5_mdss = irq_data_get_irq_chip_data(irqd); > > smp_mb__before_atomic(); > - clear_bit(irqd->hwirq, &mdss->irqcontroller.enabled_mask); > + clear_bit(irqd->hwirq, &mdp5_mdss->irqcontroller.enabled_mask); > smp_mb__after_atomic(); > } > > static void mdss_hw_unmask_irq(struct irq_data *irqd) > { > - struct msm_mdss *mdss = irq_data_get_irq_chip_data(irqd); > + struct mdp5_mdss *mdp5_mdss = irq_data_get_irq_chip_data(irqd); > > smp_mb__before_atomic(); > - set_bit(irqd->hwirq, &mdss->irqcontroller.enabled_mask); > + set_bit(irqd->hwirq, &mdp5_mdss->irqcontroller.enabled_mask); > smp_mb__after_atomic(); > } > > @@ -109,13 +107,13 @@ static struct irq_chip mdss_hw_irq_chip = { > static int mdss_hw_irqdomain_map(struct irq_domain *d, unsigned int irq, > irq_hw_number_t hwirq) > { > - struct msm_mdss *mdss = d->host_data; > + struct mdp5_mdss *mdp5_mdss = d->host_data; > > if (!(VALID_IRQS & (1 << hwirq))) > return -EPERM; > > irq_set_chip_and_handler(irq, &mdss_hw_irq_chip, handle_level_irq); > - irq_set_chip_data(irq, mdss); > + irq_set_chip_data(irq, mdp5_mdss); > > return 0; > } > @@ -126,90 +124,99 @@ static const struct irq_domain_ops mdss_hw_irqdomain_ops = { > }; > > > -static int mdss_irq_domain_init(struct msm_mdss *mdss) > +static int mdss_irq_domain_init(struct mdp5_mdss *mdp5_mdss) > { > - struct device *dev = mdss->dev->dev; > + struct device *dev = mdp5_mdss->base.dev->dev; > struct irq_domain *d; > > d = irq_domain_add_linear(dev->of_node, 32, &mdss_hw_irqdomain_ops, > - mdss); > + mdp5_mdss); > if (!d) { > dev_err(dev, "mdss irq domain add failed\n"); > return -ENXIO; > } > > - mdss->irqcontroller.enabled_mask = 0; > - mdss->irqcontroller.domain = d; > + mdp5_mdss->irqcontroller.enabled_mask = 0; > + mdp5_mdss->irqcontroller.domain = d; > > return 0; > } > > -int msm_mdss_enable(struct msm_mdss *mdss) > +static int mdp5_mdss_enable(struct msm_mdss *mdss) > { > + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(mdss); > DBG(""); > > - clk_prepare_enable(mdss->ahb_clk); > - if (mdss->axi_clk) > - clk_prepare_enable(mdss->axi_clk); > - if (mdss->vsync_clk) > - clk_prepare_enable(mdss->vsync_clk); > + clk_prepare_enable(mdp5_mdss->ahb_clk); > + if (mdp5_mdss->axi_clk) > + clk_prepare_enable(mdp5_mdss->axi_clk); > + if (mdp5_mdss->vsync_clk) > + clk_prepare_enable(mdp5_mdss->vsync_clk); > > return 0; > } > > -int msm_mdss_disable(struct msm_mdss *mdss) > +static int mdp5_mdss_disable(struct msm_mdss *mdss) > { > + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(mdss); > DBG(""); > > - if (mdss->vsync_clk) > - clk_disable_unprepare(mdss->vsync_clk); > - if (mdss->axi_clk) > - clk_disable_unprepare(mdss->axi_clk); > - clk_disable_unprepare(mdss->ahb_clk); > + if (mdp5_mdss->vsync_clk) > + clk_disable_unprepare(mdp5_mdss->vsync_clk); > + if (mdp5_mdss->axi_clk) > + clk_disable_unprepare(mdp5_mdss->axi_clk); > + clk_disable_unprepare(mdp5_mdss->ahb_clk); > > return 0; > } > > -static int msm_mdss_get_clocks(struct msm_mdss *mdss) > +static int msm_mdss_get_clocks(struct mdp5_mdss *mdp5_mdss) > { > - struct platform_device *pdev = to_platform_device(mdss->dev->dev); > + struct platform_device *pdev = > + to_platform_device(mdp5_mdss->base.dev->dev); > > - mdss->ahb_clk = msm_clk_get(pdev, "iface"); > - if (IS_ERR(mdss->ahb_clk)) > - mdss->ahb_clk = NULL; > + mdp5_mdss->ahb_clk = msm_clk_get(pdev, "iface"); > + if (IS_ERR(mdp5_mdss->ahb_clk)) > + mdp5_mdss->ahb_clk = NULL; > > - mdss->axi_clk = msm_clk_get(pdev, "bus"); > - if (IS_ERR(mdss->axi_clk)) > - mdss->axi_clk = NULL; > + mdp5_mdss->axi_clk = msm_clk_get(pdev, "bus"); > + if (IS_ERR(mdp5_mdss->axi_clk)) > + mdp5_mdss->axi_clk = NULL; > > - mdss->vsync_clk = msm_clk_get(pdev, "vsync"); > - if (IS_ERR(mdss->vsync_clk)) > - mdss->vsync_clk = NULL; > + mdp5_mdss->vsync_clk = msm_clk_get(pdev, "vsync"); > + if (IS_ERR(mdp5_mdss->vsync_clk)) > + mdp5_mdss->vsync_clk = NULL; > > return 0; > } > > -void msm_mdss_destroy(struct drm_device *dev) > +static void mdp5_mdss_destroy(struct drm_device *dev) > { > struct msm_drm_private *priv = dev->dev_private; > - struct msm_mdss *mdss = priv->mdss; > + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(priv->mdss); > > - if (!mdss) > + if (!mdp5_mdss) > return; > > - irq_domain_remove(mdss->irqcontroller.domain); > - mdss->irqcontroller.domain = NULL; > + irq_domain_remove(mdp5_mdss->irqcontroller.domain); > + mdp5_mdss->irqcontroller.domain = NULL; > > - regulator_disable(mdss->vdd); > + regulator_disable(mdp5_mdss->vdd); > > pm_runtime_disable(dev->dev); > } > > -int msm_mdss_init(struct drm_device *dev) > +static const struct msm_mdss_funcs mdss_funcs = { > + .enable = mdp5_mdss_enable, > + .disable = mdp5_mdss_disable, > + .destroy = mdp5_mdss_destroy, > +}; > + > +int mdp5_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; > + struct mdp5_mdss *mdp5_mdss; > int ret; > > DBG(""); > @@ -217,40 +224,40 @@ int msm_mdss_init(struct drm_device *dev) > if (!of_device_is_compatible(dev->dev->of_node, "qcom,mdss")) > return 0; > > - mdss = devm_kzalloc(dev->dev, sizeof(*mdss), GFP_KERNEL); > - if (!mdss) { > + mdp5_mdss = devm_kzalloc(dev->dev, sizeof(*mdp5_mdss), GFP_KERNEL); > + if (!mdp5_mdss) { > ret = -ENOMEM; > goto fail; > } > > - mdss->dev = dev; > + mdp5_mdss->base.dev = dev; > > - mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS"); > - if (IS_ERR(mdss->mmio)) { > - ret = PTR_ERR(mdss->mmio); > + mdp5_mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS"); > + if (IS_ERR(mdp5_mdss->mmio)) { > + ret = PTR_ERR(mdp5_mdss->mmio); > goto fail; > } > > - mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); > - if (IS_ERR(mdss->vbif)) { > - ret = PTR_ERR(mdss->vbif); > + mdp5_mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); > + if (IS_ERR(mdp5_mdss->vbif)) { > + ret = PTR_ERR(mdp5_mdss->vbif); > goto fail; > } > > - ret = msm_mdss_get_clocks(mdss); > + ret = msm_mdss_get_clocks(mdp5_mdss); > if (ret) { > dev_err(dev->dev, "failed to get clocks: %d\n", ret); > 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); > + mdp5_mdss->vdd = devm_regulator_get(dev->dev, "vdd"); > + if (IS_ERR(mdp5_mdss->vdd)) { > + ret = PTR_ERR(mdp5_mdss->vdd); > goto fail; > } > > - ret = regulator_enable(mdss->vdd); > + ret = regulator_enable(mdp5_mdss->vdd); > if (ret) { > dev_err(dev->dev, "failed to enable regulator vdd: %d\n", > ret); > @@ -258,25 +265,26 @@ int msm_mdss_init(struct drm_device *dev) > } > > ret = devm_request_irq(dev->dev, platform_get_irq(pdev, 0), > - mdss_irq, 0, "mdss_isr", mdss); > + mdss_irq, 0, "mdss_isr", mdp5_mdss); > if (ret) { > dev_err(dev->dev, "failed to init irq: %d\n", ret); > goto fail_irq; > } > > - ret = mdss_irq_domain_init(mdss); > + ret = mdss_irq_domain_init(mdp5_mdss); > if (ret) { > dev_err(dev->dev, "failed to init sub-block irqs: %d\n", ret); > goto fail_irq; > } > > - priv->mdss = mdss; > + mdp5_mdss->base.funcs = &mdss_funcs; > + priv->mdss = &mdp5_mdss->base; > > pm_runtime_enable(dev->dev); > > return 0; > fail_irq: > - regulator_disable(mdss->vdd); > + regulator_disable(mdp5_mdss->vdd); > fail: > return ret; > } > diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c > index 7f7321eb5312..2608d3f77956 100644 > --- a/drivers/gpu/drm/msm/msm_drv.c > +++ b/drivers/gpu/drm/msm/msm_drv.c > @@ -208,6 +208,7 @@ static int msm_drm_uninit(struct device *dev) > struct drm_device *ddev = platform_get_drvdata(pdev); > struct msm_drm_private *priv = ddev->dev_private; > struct msm_kms *kms = priv->kms; > + struct msm_mdss *mdss = priv->mdss; > struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl; > struct vblank_event *vbl_ev, *tmp; > > @@ -258,7 +259,8 @@ static int msm_drm_uninit(struct device *dev) > > component_unbind_all(dev, ddev); > > - msm_mdss_destroy(ddev); > + if (mdss && mdss->funcs) > + mdss->funcs->destroy(ddev); > > ddev->dev_private = NULL; > drm_dev_unref(ddev); > @@ -357,6 +359,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) > struct drm_device *ddev; > struct msm_drm_private *priv; > struct msm_kms *kms; > + struct msm_mdss *mdss; > int ret; > > ddev = drm_dev_alloc(drv, dev); > @@ -376,13 +379,15 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) > ddev->dev_private = priv; > priv->dev = ddev; > > - ret = msm_mdss_init(ddev); > + ret = mdp5_mdss_init(ddev); > if (ret) { > kfree(priv); > drm_dev_unref(ddev); > return ret; > } > > + mdss = priv->mdss; > + > priv->wq = alloc_ordered_workqueue("msm", 0); > priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0); > > @@ -396,7 +401,8 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) > /* Bind all our sub-components: */ > ret = component_bind_all(dev, ddev); > if (ret) { > - msm_mdss_destroy(ddev); > + if (mdss && mdss->funcs) > + mdss->funcs->destroy(ddev); > kfree(priv); > drm_dev_unref(ddev); > return ret; > @@ -924,11 +930,12 @@ static int msm_runtime_suspend(struct device *dev) > { > struct drm_device *ddev = dev_get_drvdata(dev); > struct msm_drm_private *priv = ddev->dev_private; > + struct msm_mdss *mdss = priv->mdss; > > DBG(""); > > - if (priv->mdss) > - return msm_mdss_disable(priv->mdss); > + if (mdss && mdss->funcs) > + return mdss->funcs->disable(mdss); > > return 0; > } > @@ -937,11 +944,12 @@ static int msm_runtime_resume(struct device *dev) > { > struct drm_device *ddev = dev_get_drvdata(dev); > struct msm_drm_private *priv = ddev->dev_private; > + struct msm_mdss *mdss = priv->mdss; > > DBG(""); > > - if (priv->mdss) > - return msm_mdss_enable(priv->mdss); > + if (mdss && mdss->funcs) > + return mdss->funcs->enable(mdss); > > return 0; > } > diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h > index dfd92947de2c..76c14221ffdf 100644 > --- a/drivers/gpu/drm/msm/msm_kms.h > +++ b/drivers/gpu/drm/msm/msm_kms.h > @@ -86,9 +86,18 @@ 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); > -int msm_mdss_init(struct drm_device *dev); > -void msm_mdss_destroy(struct drm_device *dev); > -int msm_mdss_enable(struct msm_mdss *mdss); > -int msm_mdss_disable(struct msm_mdss *mdss); > + > +struct msm_mdss_funcs { > + int (*enable)(struct msm_mdss *mdss); > + int (*disable)(struct msm_mdss *mdss); > + void (*destroy)(struct drm_device *dev); > +}; > + > +struct msm_mdss { > + struct drm_device *dev; > + const struct msm_mdss_funcs *funcs; > +}; > + > +int mdp5_mdss_init(struct drm_device *dev); > > #endif /* __MSM_KMS_H__ */ >
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c index f2a0db7a8a03..1cc4e57f0226 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c @@ -20,12 +20,10 @@ #include "msm_drv.h" #include "mdp5_kms.h" -/* - * If needed, this can become more specific: something like struct mdp5_mdss, - * which contains a 'struct msm_mdss base' member. - */ -struct msm_mdss { - struct drm_device *dev; +#define to_mdp5_mdss(x) container_of(x, struct mdp5_mdss, base) + +struct mdp5_mdss { + struct msm_mdss base; void __iomem *mmio, *vbif; @@ -41,22 +39,22 @@ struct msm_mdss { } irqcontroller; }; -static inline void mdss_write(struct msm_mdss *mdss, u32 reg, u32 data) +static inline void mdss_write(struct mdp5_mdss *mdp5_mdss, u32 reg, u32 data) { - msm_writel(data, mdss->mmio + reg); + msm_writel(data, mdp5_mdss->mmio + reg); } -static inline u32 mdss_read(struct msm_mdss *mdss, u32 reg) +static inline u32 mdss_read(struct mdp5_mdss *mdp5_mdss, u32 reg) { - return msm_readl(mdss->mmio + reg); + return msm_readl(mdp5_mdss->mmio + reg); } static irqreturn_t mdss_irq(int irq, void *arg) { - struct msm_mdss *mdss = arg; + struct mdp5_mdss *mdp5_mdss = arg; u32 intr; - intr = mdss_read(mdss, REG_MDSS_HW_INTR_STATUS); + intr = mdss_read(mdp5_mdss, REG_MDSS_HW_INTR_STATUS); VERB("intr=%08x", intr); @@ -64,7 +62,7 @@ static irqreturn_t mdss_irq(int irq, void *arg) irq_hw_number_t hwirq = fls(intr) - 1; generic_handle_irq(irq_find_mapping( - mdss->irqcontroller.domain, hwirq)); + mdp5_mdss->irqcontroller.domain, hwirq)); intr &= ~(1 << hwirq); } @@ -84,19 +82,19 @@ static irqreturn_t mdss_irq(int irq, void *arg) static void mdss_hw_mask_irq(struct irq_data *irqd) { - struct msm_mdss *mdss = irq_data_get_irq_chip_data(irqd); + struct mdp5_mdss *mdp5_mdss = irq_data_get_irq_chip_data(irqd); smp_mb__before_atomic(); - clear_bit(irqd->hwirq, &mdss->irqcontroller.enabled_mask); + clear_bit(irqd->hwirq, &mdp5_mdss->irqcontroller.enabled_mask); smp_mb__after_atomic(); } static void mdss_hw_unmask_irq(struct irq_data *irqd) { - struct msm_mdss *mdss = irq_data_get_irq_chip_data(irqd); + struct mdp5_mdss *mdp5_mdss = irq_data_get_irq_chip_data(irqd); smp_mb__before_atomic(); - set_bit(irqd->hwirq, &mdss->irqcontroller.enabled_mask); + set_bit(irqd->hwirq, &mdp5_mdss->irqcontroller.enabled_mask); smp_mb__after_atomic(); } @@ -109,13 +107,13 @@ static struct irq_chip mdss_hw_irq_chip = { static int mdss_hw_irqdomain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) { - struct msm_mdss *mdss = d->host_data; + struct mdp5_mdss *mdp5_mdss = d->host_data; if (!(VALID_IRQS & (1 << hwirq))) return -EPERM; irq_set_chip_and_handler(irq, &mdss_hw_irq_chip, handle_level_irq); - irq_set_chip_data(irq, mdss); + irq_set_chip_data(irq, mdp5_mdss); return 0; } @@ -126,90 +124,99 @@ static const struct irq_domain_ops mdss_hw_irqdomain_ops = { }; -static int mdss_irq_domain_init(struct msm_mdss *mdss) +static int mdss_irq_domain_init(struct mdp5_mdss *mdp5_mdss) { - struct device *dev = mdss->dev->dev; + struct device *dev = mdp5_mdss->base.dev->dev; struct irq_domain *d; d = irq_domain_add_linear(dev->of_node, 32, &mdss_hw_irqdomain_ops, - mdss); + mdp5_mdss); if (!d) { dev_err(dev, "mdss irq domain add failed\n"); return -ENXIO; } - mdss->irqcontroller.enabled_mask = 0; - mdss->irqcontroller.domain = d; + mdp5_mdss->irqcontroller.enabled_mask = 0; + mdp5_mdss->irqcontroller.domain = d; return 0; } -int msm_mdss_enable(struct msm_mdss *mdss) +static int mdp5_mdss_enable(struct msm_mdss *mdss) { + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(mdss); DBG(""); - clk_prepare_enable(mdss->ahb_clk); - if (mdss->axi_clk) - clk_prepare_enable(mdss->axi_clk); - if (mdss->vsync_clk) - clk_prepare_enable(mdss->vsync_clk); + clk_prepare_enable(mdp5_mdss->ahb_clk); + if (mdp5_mdss->axi_clk) + clk_prepare_enable(mdp5_mdss->axi_clk); + if (mdp5_mdss->vsync_clk) + clk_prepare_enable(mdp5_mdss->vsync_clk); return 0; } -int msm_mdss_disable(struct msm_mdss *mdss) +static int mdp5_mdss_disable(struct msm_mdss *mdss) { + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(mdss); DBG(""); - if (mdss->vsync_clk) - clk_disable_unprepare(mdss->vsync_clk); - if (mdss->axi_clk) - clk_disable_unprepare(mdss->axi_clk); - clk_disable_unprepare(mdss->ahb_clk); + if (mdp5_mdss->vsync_clk) + clk_disable_unprepare(mdp5_mdss->vsync_clk); + if (mdp5_mdss->axi_clk) + clk_disable_unprepare(mdp5_mdss->axi_clk); + clk_disable_unprepare(mdp5_mdss->ahb_clk); return 0; } -static int msm_mdss_get_clocks(struct msm_mdss *mdss) +static int msm_mdss_get_clocks(struct mdp5_mdss *mdp5_mdss) { - struct platform_device *pdev = to_platform_device(mdss->dev->dev); + struct platform_device *pdev = + to_platform_device(mdp5_mdss->base.dev->dev); - mdss->ahb_clk = msm_clk_get(pdev, "iface"); - if (IS_ERR(mdss->ahb_clk)) - mdss->ahb_clk = NULL; + mdp5_mdss->ahb_clk = msm_clk_get(pdev, "iface"); + if (IS_ERR(mdp5_mdss->ahb_clk)) + mdp5_mdss->ahb_clk = NULL; - mdss->axi_clk = msm_clk_get(pdev, "bus"); - if (IS_ERR(mdss->axi_clk)) - mdss->axi_clk = NULL; + mdp5_mdss->axi_clk = msm_clk_get(pdev, "bus"); + if (IS_ERR(mdp5_mdss->axi_clk)) + mdp5_mdss->axi_clk = NULL; - mdss->vsync_clk = msm_clk_get(pdev, "vsync"); - if (IS_ERR(mdss->vsync_clk)) - mdss->vsync_clk = NULL; + mdp5_mdss->vsync_clk = msm_clk_get(pdev, "vsync"); + if (IS_ERR(mdp5_mdss->vsync_clk)) + mdp5_mdss->vsync_clk = NULL; return 0; } -void msm_mdss_destroy(struct drm_device *dev) +static void mdp5_mdss_destroy(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; - struct msm_mdss *mdss = priv->mdss; + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(priv->mdss); - if (!mdss) + if (!mdp5_mdss) return; - irq_domain_remove(mdss->irqcontroller.domain); - mdss->irqcontroller.domain = NULL; + irq_domain_remove(mdp5_mdss->irqcontroller.domain); + mdp5_mdss->irqcontroller.domain = NULL; - regulator_disable(mdss->vdd); + regulator_disable(mdp5_mdss->vdd); pm_runtime_disable(dev->dev); } -int msm_mdss_init(struct drm_device *dev) +static const struct msm_mdss_funcs mdss_funcs = { + .enable = mdp5_mdss_enable, + .disable = mdp5_mdss_disable, + .destroy = mdp5_mdss_destroy, +}; + +int mdp5_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; + struct mdp5_mdss *mdp5_mdss; int ret; DBG(""); @@ -217,40 +224,40 @@ int msm_mdss_init(struct drm_device *dev) if (!of_device_is_compatible(dev->dev->of_node, "qcom,mdss")) return 0; - mdss = devm_kzalloc(dev->dev, sizeof(*mdss), GFP_KERNEL); - if (!mdss) { + mdp5_mdss = devm_kzalloc(dev->dev, sizeof(*mdp5_mdss), GFP_KERNEL); + if (!mdp5_mdss) { ret = -ENOMEM; goto fail; } - mdss->dev = dev; + mdp5_mdss->base.dev = dev; - mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS"); - if (IS_ERR(mdss->mmio)) { - ret = PTR_ERR(mdss->mmio); + mdp5_mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS"); + if (IS_ERR(mdp5_mdss->mmio)) { + ret = PTR_ERR(mdp5_mdss->mmio); goto fail; } - mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); - if (IS_ERR(mdss->vbif)) { - ret = PTR_ERR(mdss->vbif); + mdp5_mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); + if (IS_ERR(mdp5_mdss->vbif)) { + ret = PTR_ERR(mdp5_mdss->vbif); goto fail; } - ret = msm_mdss_get_clocks(mdss); + ret = msm_mdss_get_clocks(mdp5_mdss); if (ret) { dev_err(dev->dev, "failed to get clocks: %d\n", ret); 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); + mdp5_mdss->vdd = devm_regulator_get(dev->dev, "vdd"); + if (IS_ERR(mdp5_mdss->vdd)) { + ret = PTR_ERR(mdp5_mdss->vdd); goto fail; } - ret = regulator_enable(mdss->vdd); + ret = regulator_enable(mdp5_mdss->vdd); if (ret) { dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret); @@ -258,25 +265,26 @@ int msm_mdss_init(struct drm_device *dev) } ret = devm_request_irq(dev->dev, platform_get_irq(pdev, 0), - mdss_irq, 0, "mdss_isr", mdss); + mdss_irq, 0, "mdss_isr", mdp5_mdss); if (ret) { dev_err(dev->dev, "failed to init irq: %d\n", ret); goto fail_irq; } - ret = mdss_irq_domain_init(mdss); + ret = mdss_irq_domain_init(mdp5_mdss); if (ret) { dev_err(dev->dev, "failed to init sub-block irqs: %d\n", ret); goto fail_irq; } - priv->mdss = mdss; + mdp5_mdss->base.funcs = &mdss_funcs; + priv->mdss = &mdp5_mdss->base; pm_runtime_enable(dev->dev); return 0; fail_irq: - regulator_disable(mdss->vdd); + regulator_disable(mdp5_mdss->vdd); fail: return ret; } diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 7f7321eb5312..2608d3f77956 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -208,6 +208,7 @@ static int msm_drm_uninit(struct device *dev) struct drm_device *ddev = platform_get_drvdata(pdev); struct msm_drm_private *priv = ddev->dev_private; struct msm_kms *kms = priv->kms; + struct msm_mdss *mdss = priv->mdss; struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl; struct vblank_event *vbl_ev, *tmp; @@ -258,7 +259,8 @@ static int msm_drm_uninit(struct device *dev) component_unbind_all(dev, ddev); - msm_mdss_destroy(ddev); + if (mdss && mdss->funcs) + mdss->funcs->destroy(ddev); ddev->dev_private = NULL; drm_dev_unref(ddev); @@ -357,6 +359,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) struct drm_device *ddev; struct msm_drm_private *priv; struct msm_kms *kms; + struct msm_mdss *mdss; int ret; ddev = drm_dev_alloc(drv, dev); @@ -376,13 +379,15 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) ddev->dev_private = priv; priv->dev = ddev; - ret = msm_mdss_init(ddev); + ret = mdp5_mdss_init(ddev); if (ret) { kfree(priv); drm_dev_unref(ddev); return ret; } + mdss = priv->mdss; + priv->wq = alloc_ordered_workqueue("msm", 0); priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0); @@ -396,7 +401,8 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) /* Bind all our sub-components: */ ret = component_bind_all(dev, ddev); if (ret) { - msm_mdss_destroy(ddev); + if (mdss && mdss->funcs) + mdss->funcs->destroy(ddev); kfree(priv); drm_dev_unref(ddev); return ret; @@ -924,11 +930,12 @@ static int msm_runtime_suspend(struct device *dev) { struct drm_device *ddev = dev_get_drvdata(dev); struct msm_drm_private *priv = ddev->dev_private; + struct msm_mdss *mdss = priv->mdss; DBG(""); - if (priv->mdss) - return msm_mdss_disable(priv->mdss); + if (mdss && mdss->funcs) + return mdss->funcs->disable(mdss); return 0; } @@ -937,11 +944,12 @@ static int msm_runtime_resume(struct device *dev) { struct drm_device *ddev = dev_get_drvdata(dev); struct msm_drm_private *priv = ddev->dev_private; + struct msm_mdss *mdss = priv->mdss; DBG(""); - if (priv->mdss) - return msm_mdss_enable(priv->mdss); + if (mdss && mdss->funcs) + return mdss->funcs->enable(mdss); return 0; } diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index dfd92947de2c..76c14221ffdf 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -86,9 +86,18 @@ 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); -int msm_mdss_init(struct drm_device *dev); -void msm_mdss_destroy(struct drm_device *dev); -int msm_mdss_enable(struct msm_mdss *mdss); -int msm_mdss_disable(struct msm_mdss *mdss); + +struct msm_mdss_funcs { + int (*enable)(struct msm_mdss *mdss); + int (*disable)(struct msm_mdss *mdss); + void (*destroy)(struct drm_device *dev); +}; + +struct msm_mdss { + struct drm_device *dev; + const struct msm_mdss_funcs *funcs; +}; + +int mdp5_mdss_init(struct drm_device *dev); #endif /* __MSM_KMS_H__ */