On Sat, Apr 18, 2015 at 1:17 PM, Guenter Roeck <linux@xxxxxxxxxxxx> wrote: > From: Rob Clark <robdclark@xxxxxxxxx> > > commit 060530f1ea6740eb767085008d183f89ccdd289c upstream. > > Signed-off-by: Rob Clark <robdclark@xxxxxxxxx> > [Guenter Roeck: backported to 3.14] > Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx> > --- > Please consider adding this patch to v3.14, to fix a build error > seen with arm:allmodconfig. > > Rob, it would be great if you can have a look to ensure that I did not miss > anything. looks good, thanks BR, -R > Build results: > total: 125 pass: 125 fail: 0 > > Qemu test results: > total: 30 pass: 30 fail: 0 > > > drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 49 ++++++++++----- > drivers/gpu/drm/msm/hdmi/hdmi.c | 42 +++++++++---- > drivers/gpu/drm/msm/msm_drv.c | 112 ++++++++++++++++++++++++++++++++-- > drivers/gpu/drm/msm/msm_drv.h | 4 ++ > 4 files changed, 176 insertions(+), 31 deletions(-) > > diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c > index 461df93e825e..4f32b34f48d4 100644 > --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c > +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c > @@ -35,8 +35,6 @@ > A3XX_INT0_CP_AHB_ERROR_HALT | \ > A3XX_INT0_UCHE_OOB_ACCESS) > > -static struct platform_device *a3xx_pdev; > - > static void a3xx_me_init(struct msm_gpu *gpu) > { > struct msm_ringbuffer *ring = gpu->rb; > @@ -311,7 +309,6 @@ static void a3xx_destroy(struct msm_gpu *gpu) > ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl); > #endif > > - put_device(&a3xx_gpu->pdev->dev); > kfree(a3xx_gpu); > } > > @@ -439,7 +436,8 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) > struct a3xx_gpu *a3xx_gpu = NULL; > struct adreno_gpu *adreno_gpu; > struct msm_gpu *gpu; > - struct platform_device *pdev = a3xx_pdev; > + struct msm_drm_private *priv = dev->dev_private; > + struct platform_device *pdev = priv->gpu_pdev; > struct adreno_platform_config *config; > int ret; > > @@ -460,7 +458,6 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) > adreno_gpu = &a3xx_gpu->base; > gpu = &adreno_gpu->base; > > - get_device(&pdev->dev); > a3xx_gpu->pdev = pdev; > > gpu->fast_rate = config->fast_rate; > @@ -522,17 +519,24 @@ fail: > # include <mach/kgsl.h> > #endif > > -static int a3xx_probe(struct platform_device *pdev) > +static void set_gpu_pdev(struct drm_device *dev, > + struct platform_device *pdev) > +{ > + struct msm_drm_private *priv = dev->dev_private; > + priv->gpu_pdev = pdev; > +} > + > +static int a3xx_bind(struct device *dev, struct device *master, void *data) > { > static struct adreno_platform_config config = {}; > #ifdef CONFIG_OF > - struct device_node *child, *node = pdev->dev.of_node; > + struct device_node *child, *node = dev->of_node; > u32 val; > int ret; > > ret = of_property_read_u32(node, "qcom,chipid", &val); > if (ret) { > - dev_err(&pdev->dev, "could not find chipid: %d\n", ret); > + dev_err(dev, "could not find chipid: %d\n", ret); > return ret; > } > > @@ -548,7 +552,7 @@ static int a3xx_probe(struct platform_device *pdev) > for_each_child_of_node(child, pwrlvl) { > ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val); > if (ret) { > - dev_err(&pdev->dev, "could not find gpu-freq: %d\n", ret); > + dev_err(dev, "could not find gpu-freq: %d\n", ret); > return ret; > } > config.fast_rate = max(config.fast_rate, val); > @@ -558,12 +562,12 @@ static int a3xx_probe(struct platform_device *pdev) > } > > if (!config.fast_rate) { > - dev_err(&pdev->dev, "could not find clk rates\n"); > + dev_err(dev, "could not find clk rates\n"); > return -ENXIO; > } > > #else > - struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; > + struct kgsl_device_platform_data *pdata = dev->platform_data; > uint32_t version = socinfo_get_version(); > if (cpu_is_apq8064ab()) { > config.fast_rate = 450000000; > @@ -609,14 +613,30 @@ static int a3xx_probe(struct platform_device *pdev) > config.bus_scale_table = pdata->bus_scale_table; > # endif > #endif > - pdev->dev.platform_data = &config; > - a3xx_pdev = pdev; > + dev->platform_data = &config; > + set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev)); > return 0; > } > > +static void a3xx_unbind(struct device *dev, struct device *master, > + void *data) > +{ > + set_gpu_pdev(dev_get_drvdata(master), NULL); > +} > + > +static const struct component_ops a3xx_ops = { > + .bind = a3xx_bind, > + .unbind = a3xx_unbind, > +}; > + > +static int a3xx_probe(struct platform_device *pdev) > +{ > + return component_add(&pdev->dev, &a3xx_ops); > +} > + > static int a3xx_remove(struct platform_device *pdev) > { > - a3xx_pdev = NULL; > + component_del(&pdev->dev, &a3xx_ops); > return 0; > } > > @@ -624,7 +644,6 @@ static const struct of_device_id dt_match[] = { > { .compatible = "qcom,kgsl-3d0" }, > {} > }; > -MODULE_DEVICE_TABLE(of, dt_match); > > static struct platform_driver a3xx_driver = { > .probe = a3xx_probe, > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c > index 6f1588aa9071..8a04a1d206cd 100644 > --- a/drivers/gpu/drm/msm/hdmi/hdmi.c > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c > @@ -17,8 +17,6 @@ > > #include "hdmi.h" > > -static struct platform_device *hdmi_pdev; > - > void hdmi_set_mode(struct hdmi *hdmi, bool power_on) > { > uint32_t ctrl = 0; > @@ -75,7 +73,7 @@ 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 = hdmi_pdev; > + struct platform_device *pdev = priv->hdmi_pdev; > struct hdmi_platform_config *config; > int i, ret; > > @@ -95,8 +93,6 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) > > kref_init(&hdmi->refcount); > > - get_device(&pdev->dev); > - > hdmi->dev = dev; > hdmi->pdev = pdev; > hdmi->config = config; > @@ -249,17 +245,24 @@ fail: > > #include <linux/of_gpio.h> > > -static int hdmi_dev_probe(struct platform_device *pdev) > +static void set_hdmi_pdev(struct drm_device *dev, > + struct platform_device *pdev) > +{ > + struct msm_drm_private *priv = dev->dev_private; > + priv->hdmi_pdev = pdev; > +} > + > +static int hdmi_bind(struct device *dev, struct device *master, void *data) > { > static struct hdmi_platform_config config = {}; > #ifdef CONFIG_OF > - struct device_node *of_node = pdev->dev.of_node; > + struct device_node *of_node = dev->of_node; > > int get_gpio(const char *name) > { > int gpio = of_get_named_gpio(of_node, name, 0); > if (gpio < 0) { > - dev_err(&pdev->dev, "failed to get gpio: %s (%d)\n", > + dev_err(dev, "failed to get gpio: %s (%d)\n", > name, gpio); > gpio = -1; > } > @@ -336,14 +339,30 @@ static int hdmi_dev_probe(struct platform_device *pdev) > config.mux_sel_gpio = -1; > } > #endif > - pdev->dev.platform_data = &config; > - hdmi_pdev = pdev; > + dev->platform_data = &config; > + set_hdmi_pdev(dev_get_drvdata(master), to_platform_device(dev)); > return 0; > } > > +static void hdmi_unbind(struct device *dev, struct device *master, > + void *data) > +{ > + set_hdmi_pdev(dev_get_drvdata(master), NULL); > +} > + > +static const struct component_ops hdmi_ops = { > + .bind = hdmi_bind, > + .unbind = hdmi_unbind, > +}; > + > +static int hdmi_dev_probe(struct platform_device *pdev) > +{ > + return component_add(&pdev->dev, &hdmi_ops); > +} > + > static int hdmi_dev_remove(struct platform_device *pdev) > { > - hdmi_pdev = NULL; > + component_del(&pdev->dev, &hdmi_ops); > return 0; > } > > @@ -351,7 +370,6 @@ static const struct of_device_id dt_match[] = { > { .compatible = "qcom,hdmi-tx" }, > {} > }; > -MODULE_DEVICE_TABLE(of, dt_match); > > static struct platform_driver hdmi_driver = { > .probe = hdmi_dev_probe, > diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c > index e6adafc7eff3..e79cfd0b2b04 100644 > --- a/drivers/gpu/drm/msm/msm_drv.c > +++ b/drivers/gpu/drm/msm/msm_drv.c > @@ -56,6 +56,10 @@ static char *vram; > MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU"); > module_param(vram, charp, 0); > > +/* > + * Util/helpers: > + */ > + > void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, > const char *dbgname) > { > @@ -143,6 +147,8 @@ static int msm_unload(struct drm_device *dev) > priv->vram.paddr, &attrs); > } > > + component_unbind_all(dev->dev, dev); > + > dev->dev_private = NULL; > > kfree(priv); > @@ -175,6 +181,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags) > struct msm_kms *kms; > int ret; > > + > priv = kzalloc(sizeof(*priv), GFP_KERNEL); > if (!priv) { > dev_err(dev->dev, "failed to allocate private data\n"); > @@ -226,6 +233,13 @@ static int msm_load(struct drm_device *dev, unsigned long flags) > (uint32_t)(priv->vram.paddr + size)); > } > > + platform_set_drvdata(pdev, dev); > + > + /* Bind all our sub-components: */ > + ret = component_bind_all(dev->dev, dev); > + if (ret) > + return ret; > + > switch (get_mdp_ver(pdev)) { > case 4: > kms = mdp4_kms_init(dev); > @@ -281,8 +295,6 @@ static int msm_load(struct drm_device *dev, unsigned long flags) > goto fail; > } > > - platform_set_drvdata(pdev, dev); > - > #ifdef CONFIG_DRM_MSM_FBDEV > priv->fbdev = msm_fbdev_init(dev); > #endif > @@ -819,18 +831,110 @@ static const struct dev_pm_ops msm_pm_ops = { > }; > > /* > + * Componentized driver support: > + */ > + > +#ifdef CONFIG_OF > +/* NOTE: the CONFIG_OF case duplicates the same code as exynos or imx > + * (or probably any other).. so probably some room for some helpers > + */ > +static int compare_of(struct device *dev, void *data) > +{ > + return dev->of_node == data; > +} > + > +static int msm_drm_add_components(struct device *master, struct master *m) > +{ > + struct device_node *np = master->of_node; > + unsigned i; > + int ret; > + > + for (i = 0; ; i++) { > + struct device_node *node; > + > + node = of_parse_phandle(np, "connectors", i); > + if (!node) > + break; > + > + ret = component_master_add_child(m, compare_of, node); > + of_node_put(node); > + > + if (ret) > + return ret; > + } > + return 0; > +} > +#else > +static int compare_dev(struct device *dev, void *data) > +{ > + return dev == data; > +} > + > +static int msm_drm_add_components(struct device *master, struct master *m) > +{ > + /* For non-DT case, it kinda sucks. We don't actually have a way > + * to know whether or not we are waiting for certain devices (or if > + * they are simply not present). But for non-DT we only need to > + * care about apq8064/apq8060/etc (all mdp4/a3xx): > + */ > + static const char *devnames[] = { > + "hdmi_msm.0", "kgsl-3d0.0", > + }; > + int i; > + > + DBG("Adding components.."); > + > + for (i = 0; i < ARRAY_SIZE(devnames); i++) { > + struct device *dev; > + int ret; > + > + dev = bus_find_device_by_name(&platform_bus_type, > + NULL, devnames[i]); > + if (!dev) { > + dev_info(master, "still waiting for %s\n", devnames[i]); > + return -EPROBE_DEFER; > + } > + > + ret = component_master_add_child(m, compare_dev, dev); > + if (ret) { > + DBG("could not add child: %d", ret); > + return ret; > + } > + } > + > + return 0; > +} > +#endif > + > +static int msm_drm_bind(struct device *dev) > +{ > + return drm_platform_init(&msm_driver, to_platform_device(dev)); > +} > + > +static void msm_drm_unbind(struct device *dev) > +{ > + drm_put_dev(platform_get_drvdata(to_platform_device(dev))); > +} > + > +static const struct component_master_ops msm_drm_ops = { > + .add_components = msm_drm_add_components, > + .bind = msm_drm_bind, > + .unbind = msm_drm_unbind, > +}; > + > +/* > * Platform driver: > */ > > 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); > + return component_master_add(&pdev->dev, &msm_drm_ops); > } > > static int msm_pdev_remove(struct platform_device *pdev) > { > - drm_put_dev(platform_get_drvdata(pdev)); > + component_master_del(&pdev->dev, &msm_drm_ops); > > return 0; > } > diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h > index 3d63269c5b29..9d10ee0b5aac 100644 > --- a/drivers/gpu/drm/msm/msm_drv.h > +++ b/drivers/gpu/drm/msm/msm_drv.h > @@ -22,6 +22,7 @@ > #include <linux/clk.h> > #include <linux/cpufreq.h> > #include <linux/module.h> > +#include <linux/component.h> > #include <linux/platform_device.h> > #include <linux/pm.h> > #include <linux/pm_runtime.h> > @@ -69,6 +70,9 @@ struct msm_drm_private { > > struct msm_kms *kms; > > + /* subordinate devices, if present: */ > + struct platform_device *hdmi_pdev, *gpu_pdev; > + > /* when we have more than one 'msm_gpu' these need to be an array: */ > struct msm_gpu *gpu; > struct msm_file_private *lastctx; > -- > 2.1.0 > -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html