* Re: [PATCH] video: exynos_dp: Add device tree support to DP driver
From: Leela Krishna Amudala @ 2012-09-18 9:28 UTC (permalink / raw)
To: Ajay Kumar
Cc: linux-samsung-soc, linux-fbdev, jg1.han, thomas.ab,
FlorianSchandinat
In-Reply-To: <1347561592-29400-1-git-send-email-ajaykumar.rs@samsung.com>
Hello,
Please post the documentation for the bindings.
Thanks,
Leela Krishna Amudala.
On Fri, Sep 14, 2012 at 12:09 AM, Ajay Kumar <ajaykumar.rs@samsung.com> wrote:
>
> This patch enables device tree based discovery support for DP driver.
> The driver is modified to handle platform data in both the cases:
> with DT and non-DT.
>
> DP-PHY should be regarded as a seperate device node while
> being passed from device tree list, and device node for
> DP should contain DP-PHY as child node with property name "dp-phy"
> associated with it.
>
> Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
> ---
> drivers/video/exynos/exynos_dp_core.c | 156 +++++++++++++++++++++++++++++++--
> drivers/video/exynos/exynos_dp_core.h | 2 +
> 2 files changed, 151 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
> index f57c915..15887bd 100644
> --- a/drivers/video/exynos/exynos_dp_core.c
> +++ b/drivers/video/exynos/exynos_dp_core.c
> @@ -18,6 +18,7 @@
> #include <linux/io.h>
> #include <linux/interrupt.h>
> #include <linux/delay.h>
> +#include <linux/of.h>
>
> #include <video/exynos_dp.h>
>
> @@ -856,20 +857,117 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
> return IRQ_HANDLED;
> }
>
> +#ifdef CONFIG_OF
> +struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
> +{
> + struct device_node *dp_node = dev->of_node;
> + struct exynos_dp_platdata *pd;
> + struct video_info *dp_video_config;
> +
> + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
> + if (!pd) {
> + dev_err(dev, "memory allocation for pdata failed\n");
> + return ERR_PTR(-ENOMEM);
> + }
> + dp_video_config = devm_kzalloc(dev,
> + sizeof(*dp_video_config), GFP_KERNEL);
> +
> + if (!dp_video_config) {
> + dev_err(dev, "memory allocation for video config failed\n");
> + return ERR_PTR(-ENOMEM);
> + }
> + pd->video_info = dp_video_config;
> +
> + if (of_get_property(dp_node, "samsung,h-sync-polarity", NULL))
> + dp_video_config->h_sync_polarity = 1;
> +
> + if (of_get_property(dp_node, "samsung,v-sync-polarity", NULL))
> + dp_video_config->v_sync_polarity = 1;
> +
> + if (of_get_property(dp_node, "samsung,interlaced", NULL))
> + dp_video_config->interlaced = 1;
> +
> + of_property_read_u32(dp_node, "samsung,color_space",
> + &dp_video_config->color_space);
> +
> + of_property_read_u32(dp_node, "samsung,dynamic_range",
> + &dp_video_config->dynamic_range);
> +
> + of_property_read_u32(dp_node, "samsung,ycbcr_coeff",
> + &dp_video_config->ycbcr_coeff);
> +
> + of_property_read_u32(dp_node, "samsung,color_depth",
> + &dp_video_config->color_depth);
> +
> + of_property_read_u32(dp_node, "samsung,link_rate",
> + &dp_video_config->link_rate);
> +
> + of_property_read_u32(dp_node, "samsung,lane_count",
> + &dp_video_config->lane_count);
> + return pd;
> +}
> +
> +void exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
> +{
> + struct device_node *dp_phy_node;
> +
> + const __be32 *parp;
> +
> + u32 phy_base;
> +
> + void *virt_phy_base;
> +
> + parp = of_get_property(dp->dev->of_node, "dp_phy", NULL);
> + if (!parp) {
> + dp->dp_phy_addr = NULL;
> + return;
> + }
> +
> + dp_phy_node = of_find_node_by_phandle(be32_to_cpup(parp));
> + if (!dp_phy_node) {
> + dp->dp_phy_addr = NULL;
> + return;
> + }
> +
> + of_property_read_u32(dp_phy_node, "samsung,dptx_phy_reg", &phy_base);
> + of_property_read_u32(dp_phy_node, "samsung,enable_bit",
> + &dp->enable_bit);
> + virt_phy_base = ioremap(phy_base, SZ_4);
> + if (!virt_phy_base) {
> + dev_err(dp->dev, "failed to ioremap dp-phy\n");
> + dp->dp_phy_addr = NULL;
> + return;
> + }
> + dp->dp_phy_addr = virt_phy_base;
> +}
> +
> +void dp_phy_init(struct exynos_dp_device *dp)
> +{
> + u32 reg;
> +
> + reg = __raw_readl(dp->dp_phy_addr);
> + reg |= dp->enable_bit;
> + __raw_writel(reg, dp->dp_phy_addr);
> +}
> +
> +void dp_phy_exit(struct exynos_dp_device *dp)
> +{
> + u32 reg;
> +
> + reg = __raw_readl(dp->dp_phy_addr);
> + reg &= ~(dp->enable_bit);
> + __raw_writel(reg, dp->dp_phy_addr);
> +}
> +#endif /* CONFIG_OF */
> +
> static int __devinit exynos_dp_probe(struct platform_device *pdev)
> {
> struct resource *res;
> struct exynos_dp_device *dp;
> - struct exynos_dp_platdata *pdata;
> + struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
>
> int ret = 0;
>
> - pdata = pdev->dev.platform_data;
> - if (!pdata) {
> - dev_err(&pdev->dev, "no platform data\n");
> - return -EINVAL;
> - }
> -
> dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
> GFP_KERNEL);
> if (!dp) {
> @@ -879,6 +982,19 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
>
> dp->dev = &pdev->dev;
>
> + if (pdev->dev.of_node) {
> + pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
> + if (IS_ERR(pdata))
> + return PTR_ERR(pdata);
> +
> + exynos_dp_dt_parse_phydata(dp);
> + }
> +
> + if (!pdata) {
> + dev_err(&pdev->dev, "no platform data\n");
> + return -EINVAL;
> + }
> +
> dp->clock = devm_clk_get(&pdev->dev, "dp");
> if (IS_ERR(dp->clock)) {
> dev_err(&pdev->dev, "failed to get clock\n");
> @@ -909,9 +1025,13 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
> }
>
> dp->video_info = pdata->video_info;
> if (pdata->phy_init)
> pdata->phy_init();
>
> + if (pdev->dev.of_node)
> + if (dp->dp_phy_addr)
> + dp_phy_init(dp);
> +
> exynos_dp_init_dp(dp);
>
> ret = exynos_dp_detect_hpd(dp);
> @@ -956,6 +1077,10 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
> if (pdata && pdata->phy_exit)
> pdata->phy_exit();
>
> + if (pdev->dev.of_node)
> + if (dp->dp_phy_addr)
> + dp_phy_exit(dp);
> +
> clk_disable(dp->clock);
>
> return 0;
> @@ -971,6 +1096,10 @@ static int exynos_dp_suspend(struct device *dev)
> if (pdata && pdata->phy_exit)
> pdata->phy_exit();
>
> + if (dev->of_node)
> + if (dp->dp_phy_addr)
> + dp_phy_exit(dp);
> +
> clk_disable(dp->clock);
>
> return 0;
> @@ -985,6 +1114,10 @@ static int exynos_dp_resume(struct device *dev)
> if (pdata && pdata->phy_init)
> pdata->phy_init();
>
> + if (dev->of_node)
> + if (dp->dp_phy_addr)
> + dp_phy_init(dp);
> +
> clk_enable(dp->clock);
>
> exynos_dp_init_dp(dp);
> @@ -1013,6 +1146,14 @@ static const struct dev_pm_ops exynos_dp_pm_ops = {
> SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
> };
>
> +#ifdef CONFIG_OF
> +static const struct of_device_id exynos_dp_match[] = {
> + { .compatible = "samsung,exynos5-dp" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, exynos_dp_match);
> +#endif
> +
> static struct platform_driver exynos_dp_driver = {
> .probe = exynos_dp_probe,
> .remove = __devexit_p(exynos_dp_remove),
> @@ -1020,6 +1161,7 @@ static struct platform_driver exynos_dp_driver = {
> .name = "exynos-dp",
> .owner = THIS_MODULE,
> .pm = &exynos_dp_pm_ops,
> + .of_match_table = of_match_ptr(exynos_dp_match),
> },
> };
>
> diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
> index 57b8a65..49b30cb 100644
> --- a/drivers/video/exynos/exynos_dp_core.h
> +++ b/drivers/video/exynos/exynos_dp_core.h
> @@ -29,6 +29,8 @@ struct exynos_dp_device {
> struct clk *clock;
> unsigned int irq;
> void __iomem *reg_base;
> + void __iomem *dp_phy_addr;
> + int enable_bit;
>
> struct video_info *video_info;
> struct link_train link_train;
> --
> 1.7.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 1/2] video: exynos_mipi_dsi: Remove unused code
From: Sachin Kamat @ 2012-09-18 11:49 UTC (permalink / raw)
To: linux-fbdev
This code is never executed and hence removed.
Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
---
drivers/video/exynos/exynos_mipi_dsi_common.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c
index 47b533a..7cc4113 100644
--- a/drivers/video/exynos/exynos_mipi_dsi_common.c
+++ b/drivers/video/exynos/exynos_mipi_dsi_common.c
@@ -288,9 +288,6 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
mutex_unlock(&dsim->lock);
return -EINVAL;
}
-
- mutex_unlock(&dsim->lock);
- return 0;
}
static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device *dsim,
--
1.7.4.1
^ permalink raw reply related
* [PATCH 2/2] video: exynos_mipi_dsi: Fix potential NULL pointer dereference
From: Sachin Kamat @ 2012-09-18 11:50 UTC (permalink / raw)
To: linux-fbdev
The error message printed when dsim is NULL references its member.
This will cause NULL pointer derefernce error. Hence change dev_err
to pr_err to avoid it.
Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
---
drivers/video/exynos/exynos_mipi_dsi_common.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c
index 7cc4113..4fc64c4 100644
--- a/drivers/video/exynos/exynos_mipi_dsi_common.c
+++ b/drivers/video/exynos/exynos_mipi_dsi_common.c
@@ -80,7 +80,7 @@ irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id)
unsigned int intsrc, intmsk;
if (dsim = NULL) {
- dev_err(dsim->dev, "%s: wrong parameter\n", __func__);
+ pr_err("%s: wrong parameter\n", __func__);
return IRQ_NONE;
}
--
1.7.4.1
^ permalink raw reply related
* [PATCH 01/10] drivers/video/mb862xx/mb862xxfbdrv.c: fix error return code
From: Peter Senna Tschudin @ 2012-09-18 12:07 UTC (permalink / raw)
To: FlorianSchandinat
Cc: paul.gortmaker, hsweeten, agust, davidb, linux-fbdev,
linux-kernel, kernel-janitors, Peter Senna Tschudin
From: Peter Senna Tschudin <peter.senna@gmail.com>
Convert a nonnegative error return code to a negative one, as returned
elsewhere in the function.
A simplified version of the semantic match that finds this problem is as
follows: (http://coccinelle.lip6.fr/)
// <smpl>
(
if@p1 (\(ret < 0\|ret != 0\))
{ ... return ret; }
|
ret@p1 = 0
)
... when != ret = e1
when != &ret
*if(...)
{
... when != ret = e2
when forall
return ret;
}
// </smpl>
Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>
---
drivers/video/mb862xx/mb862xxfbdrv.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c
index 57d940b..d68e332 100644
--- a/drivers/video/mb862xx/mb862xxfbdrv.c
+++ b/drivers/video/mb862xx/mb862xxfbdrv.c
@@ -1052,12 +1052,14 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
break;
default:
/* should never occur */
+ ret = -EIO;
goto rel_reg;
}
par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);
if (par->fb_base = NULL) {
dev_err(dev, "Cannot map framebuffer\n");
+ ret = -EIO;
goto rel_reg;
}
@@ -1073,11 +1075,13 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n",
(unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len);
- if (mb862xx_pci_gdc_init(par))
+ ret = mb862xx_pci_gdc_init(par);
+ if (ret)
goto io_unmap;
- if (request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
- DRV_NAME, (void *)par)) {
+ ret = request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
+ DRV_NAME, (void *)par);
+ if (ret) {
dev_err(dev, "Cannot request irq\n");
goto io_unmap;
}
--
1.7.11.4
^ permalink raw reply related
* [PATCH 02/10] drivers/video/sunxvr1000.c: fix error return code
From: Peter Senna Tschudin @ 2012-09-18 12:07 UTC (permalink / raw)
To: FlorianSchandinat
Cc: linux-fbdev, linux-kernel, kernel-janitors, Peter Senna Tschudin
In-Reply-To: <1347970080-25175-1-git-send-email-peter.senna@gmail.com>
From: Peter Senna Tschudin <peter.senna@gmail.com>
Convert a nonnegative error return code to a negative one, as returned
elsewhere in the function.
A simplified version of the semantic match that finds this problem is as
follows: (http://coccinelle.lip6.fr/)
// <smpl>
(
if@p1 (\(ret < 0\|ret != 0\))
{ ... return ret; }
|
ret@p1 = 0
)
... when != ret = e1
when != &ret
*if(...)
{
... when != ret = e2
when forall
return ret;
}
// </smpl>
Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>
---
drivers/video/sunxvr1000.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c
index b7f27ac..729a507 100644
--- a/drivers/video/sunxvr1000.c
+++ b/drivers/video/sunxvr1000.c
@@ -141,8 +141,10 @@ static int __devinit gfb_probe(struct platform_device *op)
gp->fb_base = of_ioremap(&op->resource[6], 0,
gp->fb_size, "gfb fb");
- if (!gp->fb_base)
+ if (!gp->fb_base) {
+ err = -ENOMEM;
goto err_release_fb;
+ }
err = gfb_set_fbinfo(gp);
if (err)
--
1.7.11.4
^ permalink raw reply related
* [PATCH 03/10] drivers/video/cg3.c: fix error return code
From: Peter Senna Tschudin @ 2012-09-18 12:07 UTC (permalink / raw)
To: FlorianSchandinat
Cc: linux-fbdev, linux-kernel, kernel-janitors, Peter Senna Tschudin
In-Reply-To: <1347970080-25175-1-git-send-email-peter.senna@gmail.com>
From: Peter Senna Tschudin <peter.senna@gmail.com>
Convert a nonnegative error return code to a negative one, as returned
elsewhere in the function.
A simplified version of the semantic match that finds this problem is as
follows: (http://coccinelle.lip6.fr/)
// <smpl>
(
if@p1 (\(ret < 0\|ret != 0\))
{ ... return ret; }
|
ret@p1 = 0
)
... when != ret = e1
when != &ret
*if(...)
{
... when != ret = e2
when forall
return ret;
}
// </smpl>
Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>
---
drivers/video/cg3.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index f927a7b..c5e7612 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -398,7 +398,8 @@ static int __devinit cg3_probe(struct platform_device *op)
goto out_unmap_screen;
}
- if (fb_alloc_cmap(&info->cmap, 256, 0))
+ err = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (err)
goto out_unmap_screen;
fb_set_cmap(&info->cmap, info);
--
1.7.11.4
^ permalink raw reply related
* [PATCH 04/10] drivers/video/sunxvr500.c: fix error return code
From: Peter Senna Tschudin @ 2012-09-18 12:07 UTC (permalink / raw)
To: FlorianSchandinat
Cc: linux-fbdev, linux-kernel, kernel-janitors, Peter Senna Tschudin
In-Reply-To: <1347970080-25175-1-git-send-email-peter.senna@gmail.com>
From: Peter Senna Tschudin <peter.senna@gmail.com>
Convert a nonnegative error return code to a negative one, as returned
elsewhere in the function.
A simplified version of the semantic match that finds this problem is as
follows: (http://coccinelle.lip6.fr/)
// <smpl>
(
if@p1 (\(ret < 0\|ret != 0\))
{ ... return ret; }
|
ret@p1 = 0
)
... when != ret = e1
when != &ret
*if(...)
{
... when != ret = e2
when forall
return ret;
}
// </smpl>
Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>
---
drivers/video/sunxvr500.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/video/sunxvr500.c b/drivers/video/sunxvr500.c
index eb931b8..6c71b1b 100644
--- a/drivers/video/sunxvr500.c
+++ b/drivers/video/sunxvr500.c
@@ -298,8 +298,10 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev,
goto err_release_fb;
}
ep->ramdac = ioremap(ep->regs_base_phys + 0x8000, 0x1000);
- if (!ep->ramdac)
+ if (!ep->ramdac) {
+ err = -ENOMEM;
goto err_release_pci1;
+ }
ep->fb8_0_off = readl(ep->ramdac + RAMDAC_VID_8FB_0);
ep->fb8_0_off -= ep->fb_base_reg;
@@ -343,8 +345,10 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev,
ep->fb_size = info->fix.line_length * ep->height;
ep->fb_base = ioremap(ep->fb_base_phys, ep->fb_size);
- if (!ep->fb_base)
+ if (!ep->fb_base) {
+ err = -ENOMEM;
goto err_release_pci0;
+ }
err = e3d_set_fbinfo(ep);
if (err)
--
1.7.11.4
^ permalink raw reply related
* [PATCH 05/10] drivers/video/atmel_lcdfb.c: fix error return code
From: Peter Senna Tschudin @ 2012-09-18 12:07 UTC (permalink / raw)
To: nicolas.ferre
Cc: FlorianSchandinat, linux-fbdev, linux-kernel, kernel-janitors,
Peter Senna Tschudin
In-Reply-To: <1347970080-25175-1-git-send-email-peter.senna@gmail.com>
From: Peter Senna Tschudin <peter.senna@gmail.com>
Convert a nonnegative error return code to a negative one, as returned
elsewhere in the function.
A simplified version of the semantic match that finds this problem is as
follows: (http://coccinelle.lip6.fr/)
// <smpl>
(
if@p1 (\(ret < 0\|ret != 0\))
{ ... return ret; }
|
ret@p1 = 0
)
... when != ret = e1
when != &ret
*if(...)
{
... when != ret = e2
when forall
return ret;
}
// </smpl>
Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>
---
drivers/video/atmel_lcdfb.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 1505539..94cac9f 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -931,8 +931,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
}
info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
- if (!info->screen_base)
+ if (!info->screen_base) {
+ ret = -ENOMEM;
goto release_intmem;
+ }
/*
* Don't clear the framebuffer -- someone may have set
@@ -960,6 +962,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);
if (!sinfo->mmio) {
dev_err(dev, "cannot map LCDC registers\n");
+ ret = -ENOMEM;
goto release_mem;
}
--
1.7.11.4
^ permalink raw reply related
* [PATCH 06/10] drivers/video/imxfb.c: fix error return code
From: Peter Senna Tschudin @ 2012-09-18 12:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1347970080-25175-1-git-send-email-peter.senna@gmail.com>
From: Peter Senna Tschudin <peter.senna@gmail.com>
Convert a nonnegative error return code to a negative one, as returned
elsewhere in the function.
A simplified version of the semantic match that finds this problem is as
follows: (http://coccinelle.lip6.fr/)
// <smpl>
(
if@p1 (\(ret < 0\|ret != 0\))
{ ... return ret; }
|
ret@p1 = 0
)
... when != ret = e1
when != &ret
*if(...)
{
... when != ret = e2
when forall
return ret;
}
// </smpl>
Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>
---
drivers/video/imxfb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index caad368..469b07c 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -803,6 +803,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
fbi->regs = ioremap(res->start, resource_size(res));
if (fbi->regs = NULL) {
dev_err(&pdev->dev, "Cannot map frame buffer registers\n");
+ ret = -ENOMEM;
goto failed_ioremap;
}
--
1.7.11.4
^ permalink raw reply related
* [PATCH 07/10] drivers/video/bw2.c: fix error return code
From: Peter Senna Tschudin @ 2012-09-18 12:07 UTC (permalink / raw)
To: FlorianSchandinat
Cc: linux-fbdev, linux-kernel, kernel-janitors, Peter Senna Tschudin
In-Reply-To: <1347970080-25175-1-git-send-email-peter.senna@gmail.com>
From: Peter Senna Tschudin <peter.senna@gmail.com>
Convert a nonnegative error return code to a negative one, as returned
elsewhere in the function.
A simplified version of the semantic match that finds this problem is as
follows: (http://coccinelle.lip6.fr/)
// <smpl>
(
if@p1 (\(ret < 0\|ret != 0\))
{ ... return ret; }
|
ret@p1 = 0
)
... when != ret = e1
when != &ret
*if(...)
{
... when != ret = e2
when forall
return ret;
}
// </smpl>
Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>
---
drivers/video/bw2.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 7ba74cd..6bea9a9 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -319,8 +319,10 @@ static int __devinit bw2_probe(struct platform_device *op)
info->screen_base = of_ioremap(&op->resource[0], 0,
info->fix.smem_len, "bw2 ram");
- if (!info->screen_base)
+ if (!info->screen_base) {
+ err = -ENOMEM;
goto out_unmap_regs;
+ }
bw2_blank(FB_BLANK_UNBLANK, info);
--
1.7.11.4
^ permalink raw reply related
* [PATCH 08/10] drivers/video/cyber2000fb.c: fix error return code
From: Peter Senna Tschudin @ 2012-09-18 12:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1347970080-25175-1-git-send-email-peter.senna@gmail.com>
From: Peter Senna Tschudin <peter.senna@gmail.com>
Convert a nonnegative error return code to a negative one, as returned
elsewhere in the function.
A simplified version of the semantic match that finds this problem is as
follows: (http://coccinelle.lip6.fr/)
// <smpl>
(
if@p1 (\(ret < 0\|ret != 0\))
{ ... return ret; }
|
ret@p1 = 0
)
... when != ret = e1
when != &ret
*if(...)
{
... when != ret = e2
when forall
return ret;
}
// </smpl>
Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>
---
drivers/video/cyber2000fb.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index c1527f5..e40125c 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1804,8 +1804,10 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
cfb->irq = dev->irq;
cfb->region = pci_ioremap_bar(dev, 0);
- if (!cfb->region)
+ if (!cfb->region) {
+ err = -ENOMEM;
goto failed_ioremap;
+ }
cfb->regs = cfb->region + MMIO_OFFSET;
cfb->fb.device = &dev->dev;
--
1.7.11.4
^ permalink raw reply related
* [PATCH 09/10] drivers/video/ps3fb.c: fix error return code
From: Peter Senna Tschudin @ 2012-09-18 12:07 UTC (permalink / raw)
To: geoff
Cc: cbe-oss-dev, linux-fbdev, FlorianSchandinat, Peter Senna Tschudin,
kernel-janitors, linux-kernel, linuxppc-dev
In-Reply-To: <1347970080-25175-1-git-send-email-peter.senna@gmail.com>
From: Peter Senna Tschudin <peter.senna@gmail.com>
Convert a nonnegative error return code to a negative one, as returned
elsewhere in the function.
A simplified version of the semantic match that finds this problem is as
follows: (http://coccinelle.lip6.fr/)
// <smpl>
(
if@p1 (\(ret < 0\|ret != 0\))
{ ... return ret; }
|
ret@p1 = 0
)
... when != ret = e1
when != &ret
*if(...)
{
... when != ret = e2
when forall
return ret;
}
// </smpl>
Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>
---
drivers/video/ps3fb.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 4e292f2..0b340d6 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -1034,6 +1034,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
if (status) {
dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",
__func__, status);
+ retval = -ENOMEM;
goto err_close_device;
}
dev_dbg(&dev->core, "ddr:lpar:0x%llx\n", ddr_lpar);
@@ -1046,6 +1047,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
dev_err(&dev->core,
"%s: lv1_gpu_context_allocate failed: %d\n", __func__,
status);
+ retval = -ENOMEM;
goto err_gpu_memory_free;
}
@@ -1053,6 +1055,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024);
if (!dinfo) {
dev_err(&dev->core, "%s: ioremap failed\n", __func__);
+ retval = -ENOMEM;
goto err_gpu_context_free;
}
@@ -1121,8 +1124,10 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
}
info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
- if (!info)
+ if (!info) {
+ retval = -ENOMEM;
goto err_context_fb_close;
+ }
par = info->par;
par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */
--
1.7.11.4
^ permalink raw reply related
* [PATCH 10/10] drivers/video/arcfb.c: fix error return code
From: Peter Senna Tschudin @ 2012-09-18 12:08 UTC (permalink / raw)
To: jayalk
Cc: FlorianSchandinat, linux-fbdev, linux-kernel, kernel-janitors,
Peter Senna Tschudin
In-Reply-To: <1347970080-25175-1-git-send-email-peter.senna@gmail.com>
From: Peter Senna Tschudin <peter.senna@gmail.com>
Convert a nonnegative error return code to a negative one, as returned
elsewhere in the function.
A simplified version of the semantic match that finds this problem is as
follows: (http://coccinelle.lip6.fr/)
// <smpl>
(
if@p1 (\(ret < 0\|ret != 0\))
{ ... return ret; }
|
ret@p1 = 0
)
... when != ret = e1
when != &ret
*if(...)
{
... when != ret = e2
when forall
return ret;
}
// </smpl>
Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>
---
drivers/video/arcfb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index a1d58e9..4659d5d 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -552,6 +552,7 @@ static int __devinit arcfb_probe(struct platform_device *dev)
"arcfb", info)) {
printk(KERN_INFO
"arcfb: Failed req IRQ %d\n", par->irq);
+ retval = -EBUSY;
goto err1;
}
}
--
1.7.11.4
^ permalink raw reply related
* [PATCH v2 02/13] video: Versatile Express display output driver
From: Pawel Moll @ 2012-09-18 14:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1347977875-16855-1-git-send-email-pawel.moll@arm.com>
Versatile Express' DVI video output can be connected to one the three
sources - motherboard's CLCD controller or a video signal generated
by one of the daughterboards.
This driver configures the muxer FPGA so the output displays
content of one of the framebuffers in the system (0 by default,
can be changed by user writing to "fb" attribute of the muxfpga
device). The decision is based on an educated guess in case of
DT-less system or on the "arm,vexpress,site" property of the
display controller's DT node.
It will also set up the display formatter mode and keep it up
to date with mode changes requested by the user (eg. with fbset
tool).
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
drivers/video/Makefile | 3 +
drivers/video/vexpress-dvi.c | 208 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 211 insertions(+)
create mode 100644 drivers/video/vexpress-dvi.c
Hi Florian,
Assuming it's not totally crap ;-) what would be you preference about
merging this patch? Would you take it through your tree?
Regards
Pawel
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index ee8dafb..01d28d5 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -170,3 +170,6 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o
#video output switch sysfs driver
obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
+
+# platform specific output drivers
+obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-dvi.o
diff --git a/drivers/video/vexpress-dvi.c b/drivers/video/vexpress-dvi.c
new file mode 100644
index 0000000..fc50fc6
--- /dev/null
+++ b/drivers/video/vexpress-dvi.c
@@ -0,0 +1,208 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define pr_fmt(fmt) "vexpress-dvi: " fmt
+
+#include <linux/fb.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/vexpress.h>
+
+
+static struct vexpress_config_func *vexpress_dvimode_func;
+
+static struct {
+ u32 xres, yres, mode;
+} vexpress_dvi_dvimodes[] = {
+ { 640, 480, 0 }, /* VGA */
+ { 800, 600, 1 }, /* SVGA */
+ { 1024, 768, 2 }, /* XGA */
+ { 1280, 1024, 3 }, /* SXGA */
+ { 1600, 1200, 4 }, /* UXGA */
+ { 1920, 1080, 5 }, /* HD1080 */
+};
+
+static void vexpress_dvi_mode_set(struct fb_info *info, u32 xres, u32 yres)
+{
+ int err = -ENOENT;
+ int i;
+
+ if (!vexpress_dvimode_func)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(vexpress_dvi_dvimodes); i++) {
+ if (vexpress_dvi_dvimodes[i].xres == xres &&
+ vexpress_dvi_dvimodes[i].yres == yres) {
+ pr_debug("mode: %ux%u = %d\n", xres, yres,
+ vexpress_dvi_dvimodes[i].mode);
+ err = vexpress_config_write(vexpress_dvimode_func, 0,
+ vexpress_dvi_dvimodes[i].mode);
+ break;
+ }
+ }
+
+ if (err)
+ pr_warn("Failed to set %ux%u mode! (%d)\n", xres, yres, err);
+}
+
+
+static struct vexpress_config_func *vexpress_muxfpga_func;
+static int vexpress_dvi_fb = -1;
+
+static int vexpress_dvi_mux_set(struct fb_info *info)
+{
+ u32 site = vexpress_get_site_by_dev(info->device);
+ int err = vexpress_config_write(vexpress_muxfpga_func, 0, site);
+
+ if (!err) {
+ pr_debug("Selected MUXFPGA input %d (fb%d)\n", site,
+ info->node);
+ vexpress_dvi_fb = info->node;
+ vexpress_dvi_mode_set(info, info->var.xres,
+ info->var.yres);
+ } else {
+ pr_warn("Failed to select MUXFPGA input %d (fb%d)! (%d)\n",
+ site, info->node, err);
+ }
+
+ return err;
+}
+
+static int vexpress_dvi_fb_select(int fb)
+{
+ int err;
+ struct fb_info *info = registered_fb[fb];
+
+ if (!info || !lock_fb_info(info))
+ return -ENODEV;
+
+ err = vexpress_dvi_mux_set(info);
+
+ unlock_fb_info(info);
+
+ return err;
+}
+
+static ssize_t vexpress_dvi_fb_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", vexpress_dvi_fb);
+}
+
+static ssize_t vexpress_dvi_fb_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ long value;
+ int err = kstrtol(buf, 0, &value);
+
+ if (!err)
+ err = vexpress_dvi_fb_select(value);
+
+ return err ? err : count;
+}
+
+DEVICE_ATTR(fb, S_IRUGO | S_IWUSR, vexpress_dvi_fb_show,
+ vexpress_dvi_fb_store);
+
+
+static int vexpress_dvi_fb_event_notify(struct notifier_block *self,
+ unsigned long action, void *data)
+{
+ struct fb_event *event = data;
+ struct fb_info *info = event->info;
+ struct fb_videomode *mode = event->data;
+
+ switch (action) {
+ case FB_EVENT_FB_REGISTERED:
+ if (vexpress_dvi_fb < 0)
+ vexpress_dvi_mux_set(info);
+ break;
+ case FB_EVENT_MODE_CHANGE:
+ case FB_EVENT_MODE_CHANGE_ALL:
+ if (info->node == vexpress_dvi_fb)
+ vexpress_dvi_mode_set(info, mode->xres, mode->yres);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block vexpress_dvi_fb_notifier = {
+ .notifier_call = vexpress_dvi_fb_event_notify,
+};
+
+
+enum vexpress_dvi_func { FUNC_MUXFPGA, FUNC_DVIMODE };
+
+static struct of_device_id vexpress_dvi_of_match[] = {
+ {
+ .compatible = "arm,vexpress-muxfpga",
+ .data = (void *)FUNC_MUXFPGA,
+ }, {
+ .compatible = "arm,vexpress-dvimode",
+ .data = (void *)FUNC_DVIMODE,
+ },
+ {}
+};
+
+static int vexpress_dvi_probe(struct platform_device *pdev)
+{
+ enum vexpress_dvi_func func;
+ const struct of_device_id *match =
+ of_match_device(vexpress_dvi_of_match, &pdev->dev);
+
+ if (match)
+ func = (enum vexpress_dvi_func)match->data;
+ else
+ func = pdev->id_entry->driver_data;
+
+ switch (func) {
+ case FUNC_MUXFPGA:
+ vexpress_muxfpga_func =
+ vexpress_config_func_get_by_dev(&pdev->dev);
+ device_create_file(&pdev->dev, &dev_attr_fb);
+ break;
+ case FUNC_DVIMODE:
+ vexpress_dvimode_func =
+ vexpress_config_func_get_by_dev(&pdev->dev);
+ break;
+ }
+
+ if (vexpress_muxfpga_func && vexpress_dvimode_func) {
+ fb_register_client(&vexpress_dvi_fb_notifier);
+ vexpress_dvi_fb_select(0);
+ }
+
+ return 0;
+}
+
+static const struct platform_device_id vexpress_dvi_id_table[] = {
+ { .name = "vexpress-muxfpga", .driver_data = FUNC_MUXFPGA, },
+ { .name = "vexpress-dvimode", .driver_data = FUNC_DVIMODE, },
+ {}
+};
+
+static struct platform_driver vexpress_dvi_driver = {
+ .probe = vexpress_dvi_probe,
+ .driver = {
+ .name = "vexpress-dvi",
+ .of_match_table = vexpress_dvi_of_match,
+ },
+ .id_table = vexpress_dvi_id_table,
+};
+
+static int __init vexpress_dvi_init(void)
+{
+ return platform_driver_register(&vexpress_dvi_driver);
+}
+device_initcall(vexpress_dvi_init);
--
1.7.9.5
^ permalink raw reply related
* RE: [PATCH 1/2] video: exynos_mipi_dsi: Remove unused code
From: Inki Dae @ 2012-09-19 2:24 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1347968280-22343-1-git-send-email-sachin.kamat@linaro.org>
Acked-by: Inki Dae <inki.dae@samsung.com>
> -----Original Message-----
> From: Sachin Kamat [mailto:sachin.kamat@linaro.org]
> Sent: Tuesday, September 18, 2012 8:38 PM
> To: linux-fbdev@vger.kernel.org
> Cc: inki.dae@samsung.com; dh09.lee@samsung.com; FlorianSchandinat@gmx.de;
> sachin.kamat@linaro.org; patches@linaro.org
> Subject: [PATCH 1/2] video: exynos_mipi_dsi: Remove unused code
>
> This code is never executed and hence removed.
>
> Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
> ---
> drivers/video/exynos/exynos_mipi_dsi_common.c | 3 ---
> 1 files changed, 0 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c
> b/drivers/video/exynos/exynos_mipi_dsi_common.c
> index 47b533a..7cc4113 100644
> --- a/drivers/video/exynos/exynos_mipi_dsi_common.c
> +++ b/drivers/video/exynos/exynos_mipi_dsi_common.c
> @@ -288,9 +288,6 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device
> *dsim, unsigned int data_id,
> mutex_unlock(&dsim->lock);
> return -EINVAL;
> }
> -
> - mutex_unlock(&dsim->lock);
> - return 0;
> }
>
> static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device
> *dsim,
> --
> 1.7.4.1
^ permalink raw reply
* RE: [PATCH 2/2] video: exynos_mipi_dsi: Fix potential NULL pointer dereference
From: Inki Dae @ 2012-09-19 2:28 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1347968280-22343-2-git-send-email-sachin.kamat@linaro.org>
> -----Original Message-----
> From: Sachin Kamat [mailto:sachin.kamat@linaro.org]
> Sent: Tuesday, September 18, 2012 8:38 PM
> To: linux-fbdev@vger.kernel.org
> Cc: inki.dae@samsung.com; dh09.lee@samsung.com; FlorianSchandinat@gmx.de;
> sachin.kamat@linaro.org; patches@linaro.org
> Subject: [PATCH 2/2] video: exynos_mipi_dsi: Fix potential NULL pointer
> dereference
>
> The error message printed when dsim is NULL references its member.
> This will cause NULL pointer derefernce error. Hence change dev_err
> to pr_err to avoid it.
>
> Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
> ---
> drivers/video/exynos/exynos_mipi_dsi_common.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c
> b/drivers/video/exynos/exynos_mipi_dsi_common.c
> index 7cc4113..4fc64c4 100644
> --- a/drivers/video/exynos/exynos_mipi_dsi_common.c
> +++ b/drivers/video/exynos/exynos_mipi_dsi_common.c
> @@ -80,7 +80,7 @@ irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq,
> void *dev_id)
> unsigned int intsrc, intmsk;
>
> if (dsim = NULL) {
> - dev_err(dsim->dev, "%s: wrong parameter\n", __func__);
> + pr_err("%s: wrong parameter\n", __func__);
> return IRQ_NONE;
> }
Please, just remove above exception codes. dsim was allocated and already
checked by probe so this exception isn't needed.
Thanks,
Inki Dae
>
> --
> 1.7.4.1
^ permalink raw reply
* Re: [PATCH 2/2] video: exynos_mipi_dsi: Fix potential NULL pointer dereference
From: Sachin Kamat @ 2012-09-19 2:49 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1347968280-22343-2-git-send-email-sachin.kamat@linaro.org>
On 19 September 2012 07:58, Inki Dae <inki.dae@samsung.com> wrote:
>
>
>> -----Original Message-----
>> From: Sachin Kamat [mailto:sachin.kamat@linaro.org]
>> Sent: Tuesday, September 18, 2012 8:38 PM
>> To: linux-fbdev@vger.kernel.org
>> Cc: inki.dae@samsung.com; dh09.lee@samsung.com; FlorianSchandinat@gmx.de;
>> sachin.kamat@linaro.org; patches@linaro.org
>> Subject: [PATCH 2/2] video: exynos_mipi_dsi: Fix potential NULL pointer
>> dereference
>>
>> The error message printed when dsim is NULL references its member.
>> This will cause NULL pointer derefernce error. Hence change dev_err
>> to pr_err to avoid it.
>>
>> Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
>> ---
>> drivers/video/exynos/exynos_mipi_dsi_common.c | 2 +-
>> 1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c
>> b/drivers/video/exynos/exynos_mipi_dsi_common.c
>> index 7cc4113..4fc64c4 100644
>> --- a/drivers/video/exynos/exynos_mipi_dsi_common.c
>> +++ b/drivers/video/exynos/exynos_mipi_dsi_common.c
>> @@ -80,7 +80,7 @@ irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq,
>> void *dev_id)
>> unsigned int intsrc, intmsk;
>>
>> if (dsim = NULL) {
>> - dev_err(dsim->dev, "%s: wrong parameter\n", __func__);
>> + pr_err("%s: wrong parameter\n", __func__);
>> return IRQ_NONE;
>> }
>
> Please, just remove above exception codes. dsim was allocated and already
> checked by probe so this exception isn't needed.
Yes, that looks better if it is already ensured to be non-NULL. I had
not checked that.
Will remove this check and re-send.
Thanks.
>
> Thanks,
> Inki Dae
>
>
>>
>> --
>> 1.7.4.1
>
--
With warm regards,
Sachin
^ permalink raw reply
* Re: [PATCH v6 0/4] Runtime Interpreted Power Sequences
From: Mark Brown @ 2012-09-19 3:01 UTC (permalink / raw)
To: Stephen Warren
Cc: Alex Courbot, linux-fbdev@vger.kernel.org, Stephen Warren,
linux-pm@vger.kernel.org, Leela Krishna Amudala,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
Rob Herring, Anton Vorontsov, Tomi Valkeinen,
linux-tegra@vger.kernel.org, David Woodhouse,
devicetree-discuss@lists.ozlabs.org
In-Reply-To: <5051FAC5.40501@wwwdotorg.org>
On Thu, Sep 13, 2012 at 09:24:53AM -0600, Stephen Warren wrote:
> On 09/13/2012 01:29 AM, Mark Brown wrote:
> > The driver knows the power sequence. Having to type the same sequence
> > into the DT or platform data for each board using the device wouuld be
> > retarded so we need the drivers to be able to give the sequence to the
> > library if they're going to be able to reuse it (which is a lot of what
> > Tomi is talking about).
> I believe that's trivial to implement. The relevant function is:
Right, that's what I'm saying - the code is mostly there now.
> It's up to the driver whether pseq comes from platform data or is
> hard-coded into the driver (or not provided at all, for the DT case).
> So, the only change needed to convert a "hard-coded" driver to this API
> is to convert the current custom data structure (or code) that describes
> the sequence into a struct platform_power_seq_set.
The framework could still help by providing ways to avoid having to copy
the structure and fill in the blanks for GPIO numbers (and anything else
that is numbered rather than named) by hand.
^ permalink raw reply
* [PATCH v4] of: Add videomode helper
From: Steffen Trumtrar @ 2012-09-19 8:20 UTC (permalink / raw)
To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, Sascha Hauer,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Laurent Pinchart,
kernel-bIcnvbaLZ9MEGnE8C9+IrQ, Steffen Trumtrar
This patch adds a helper function for parsing videomodes from the devicetree.
The videomode can be either converted to a struct drm_display_mode or a
struct fb_videomode.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
Hi!
changes since v3:
- print error messages
- free alloced memory
- general cleanup
Regards
Steffen
.../devicetree/bindings/video/displaymode | 74 +++++
drivers/of/Kconfig | 5 +
drivers/of/Makefile | 1 +
drivers/of/of_videomode.c | 283 ++++++++++++++++++++
include/linux/of_videomode.h | 56 ++++
5 files changed, 419 insertions(+)
create mode 100644 Documentation/devicetree/bindings/video/displaymode
create mode 100644 drivers/of/of_videomode.c
create mode 100644 include/linux/of_videomode.h
diff --git a/Documentation/devicetree/bindings/video/displaymode b/Documentation/devicetree/bindings/video/displaymode
new file mode 100644
index 0000000..990ca52
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/displaymode
@@ -0,0 +1,74 @@
+videomode bindings
+=========
+
+Required properties:
+ - hactive, vactive: Display resolution
+ - hfront-porch, hback-porch, hsync-len: Horizontal Display timing parameters
+ in pixels
+ vfront-porch, vback-porch, vsync-len: Vertical display timing parameters in
+ lines
+ - clock: displayclock in Hz
+
+Optional properties:
+ - width-mm, height-mm: Display dimensions in mm
+ - hsync-active-high (bool): Hsync pulse is active high
+ - vsync-active-high (bool): Vsync pulse is active high
+ - interlaced (bool): This is an interlaced mode
+ - doublescan (bool): This is a doublescan mode
+
+There are different ways of describing a display mode. The devicetree representation
+corresponds to the one commonly found in datasheets for displays.
+The description of the display and its mode is split in two parts: first the display
+properties like size in mm and (optionally) multiple subnodes with the supported modes.
+
+Example:
+
+ display@0 {
+ width-mm = <800>;
+ height-mm = <480>;
+ modes {
+ mode0: mode@0 {
+ /* 1920x1080p24 */
+ clock = <52000000>;
+ hactive = <1920>;
+ vactive = <1080>;
+ hfront-porch = <25>;
+ hback-porch = <25>;
+ hsync-len = <25>;
+ vback-porch = <2>;
+ vfront-porch = <2>;
+ vsync-len = <2>;
+ hsync-active-high;
+ };
+ };
+ };
+
+Every property also supports the use of ranges, so the commonly used datasheet
+description with <min typ max>-tuples can be used.
+
+Example:
+
+ mode1: mode@1 {
+ /* 1920x1080p24 */
+ clock = <148500000>;
+ hactive = <1920>;
+ vactive = <1080>;
+ hsync-len = <0 44 60>;
+ hfront-porch = <80 88 95>;
+ hback-porch = <100 148 160>;
+ vfront-porch = <0 4 6>;
+ vback-porch = <0 36 50>;
+ vsync-len = <0 5 6>;
+ };
+
+The videomode can be linked to a connector via phandles. The connector has to
+support the display- and default-mode-property to link to and select a mode.
+
+Example:
+
+ hdmi@00120000 {
+ status = "okay";
+ display = <&benq>;
+ default-mode = <&mode1>;
+ };
+
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index dfba3e6..a3acaa3 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -83,4 +83,9 @@ config OF_MTD
depends on MTD
def_bool y
+config OF_VIDEOMODE
+ def_bool y
+ help
+ helper to parse videomodes from the devicetree
+
endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index e027f44..80e6db3 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_OF_MDIO) += of_mdio.o
obj-$(CONFIG_OF_PCI) += of_pci.o
obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
obj-$(CONFIG_OF_MTD) += of_mtd.o
+obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o
diff --git a/drivers/of/of_videomode.c b/drivers/of/of_videomode.c
new file mode 100644
index 0000000..52bfc74
--- /dev/null
+++ b/drivers/of/of_videomode.c
@@ -0,0 +1,283 @@
+/*
+ * OF helpers for parsing display modes
+ *
+ * Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * This file is released under the GPLv2
+ */
+#include <linux/of.h>
+#include <linux/fb.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <linux/of_videomode.h>
+
+static u32 of_video_get_value(struct mode_property *prop)
+{
+ return (prop->min >= prop->typ) ? prop->min : prop->typ;
+}
+
+/* read property into new mode_property */
+static int of_video_parse_property(struct device_node *np, char *name,
+ struct mode_property *result)
+{
+ struct property *prop;
+ int length;
+ int cells;
+ int ret;
+
+ prop = of_find_property(np, name, &length);
+ if (!prop) {
+ pr_err("%s: could not find property %s\n", __func__,
+ name);
+ return -EINVAL;
+ }
+
+ cells = length / sizeof(u32);
+
+ memset(result, 0, sizeof(*result));
+
+ ret = of_property_read_u32_array(np, name, &result->min, cells);
+
+ return ret;
+}
+
+static int of_video_free(struct display *disp)
+{
+ int i;
+
+ for (i=0; i<disp->num_modes; i++)
+ kfree(disp->modes[i]);
+ kfree(disp->modes);
+
+ return 0;
+}
+
+int videomode_to_display_mode(struct display *disp, struct drm_display_mode *dmode, int index)
+{
+ struct videomode *vm;
+
+ memset(dmode, 0, sizeof(*dmode));
+
+ if (index > disp->num_modes) {
+ pr_err("%s: wrong index: %d from %d\n", __func__, index, disp->num_modes);
+ return -EINVAL;
+ }
+
+ vm = disp->modes[index];
+
+ dmode->hdisplay = of_video_get_value(&vm->hactive);
+ dmode->hsync_start = of_video_get_value(&vm->hactive) + of_video_get_value(&vm->hfront_porch);
+ dmode->hsync_end = of_video_get_value(&vm->hactive) + of_video_get_value(&vm->hfront_porch)
+ + of_video_get_value(&vm->hsync_len);
+ dmode->htotal = of_video_get_value(&vm->hactive) + of_video_get_value(&vm->hfront_porch)
+ + of_video_get_value(&vm->hsync_len) + of_video_get_value(&vm->hback_porch);
+
+ dmode->vdisplay = of_video_get_value(&vm->vactive);
+ dmode->vsync_start = of_video_get_value(&vm->vactive) + of_video_get_value(&vm->vfront_porch);
+ dmode->vsync_end = of_video_get_value(&vm->vactive) + of_video_get_value(&vm->vfront_porch)
+ + of_video_get_value(&vm->vsync_len);
+ dmode->vtotal = of_video_get_value(&vm->vactive) + of_video_get_value(&vm->vfront_porch) +
+ of_video_get_value(&vm->vsync_len) + of_video_get_value(&vm->vback_porch);
+
+ dmode->width_mm = disp->width_mm;
+ dmode->height_mm = disp->height_mm;
+
+ dmode->clock = of_video_get_value(&vm->clock) / 1000;
+
+ if (vm->hah)
+ dmode->flags |= DRM_MODE_FLAG_PHSYNC;
+ else
+ dmode->flags |= DRM_MODE_FLAG_NHSYNC;
+ if (vm->vah)
+ dmode->flags |= DRM_MODE_FLAG_PVSYNC;
+ else
+ dmode->flags |= DRM_MODE_FLAG_NVSYNC;
+ if (vm->interlaced)
+ dmode->flags |= DRM_MODE_FLAG_INTERLACE;
+ if (vm->doublescan)
+ dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
+
+ drm_mode_set_name(dmode);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(videomode_to_display_mode);
+
+int videomode_to_fb_mode(struct display *disp, struct fb_videomode *fbmode, int index)
+{
+ struct videomode *vm;
+
+ memset(fbmode, 0, sizeof(*fbmode));
+
+ if (index > disp->num_modes) {
+ pr_err("%s: wrong index: %d from %d\n", __func__, index, disp->num_modes);
+ return -EINVAL;
+ }
+
+ vm = disp->modes[index];
+
+ fbmode->xres = of_video_get_value(&vm->hactive);
+ fbmode->left_margin = of_video_get_value(&vm->hback_porch);
+ fbmode->right_margin = of_video_get_value(&vm->hfront_porch);
+ fbmode->hsync_len = of_video_get_value(&vm->hsync_len);
+
+ fbmode->yres = of_video_get_value(&vm->vactive);
+ fbmode->upper_margin = of_video_get_value(&vm->vback_porch);
+ fbmode->lower_margin = of_video_get_value(&vm->vfront_porch);
+ fbmode->vsync_len = of_video_get_value(&vm->vsync_len);
+
+ fbmode->pixclock = KHZ2PICOS(of_video_get_value(&vm->clock) / 1000);
+
+ if (vm->hah)
+ fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (vm->vah)
+ fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
+ if (vm->interlaced)
+ fbmode->vmode |= FB_VMODE_INTERLACED;
+ if (vm->doublescan)
+ fbmode->vmode |= FB_VMODE_DOUBLE;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(videomode_to_fb_mode);
+
+int of_get_video_modes(struct device_node *np, struct display *disp)
+{
+ struct device_node *display_np;
+ struct device_node *mode_np;
+ struct device_node *modes_np;
+ char *default_mode;
+
+ int ret = 0;
+
+ memset(disp, 0, sizeof(*disp));
+ disp->modes = kmalloc(sizeof(struct videomode*), GFP_KERNEL);
+
+ if (!np) {
+ pr_err("%s: no node provided\n", __func__);
+ return -EINVAL;
+ }
+
+ display_np = of_parse_phandle(np, "display", 0);
+
+ if (!display_np) {
+ pr_err("%s: could not find display node\n", __func__);
+ return -EINVAL;
+ }
+
+ of_property_read_u32(display_np, "width-mm", &disp->width_mm);
+ of_property_read_u32(display_np, "height-mm", &disp->height_mm);
+
+ mode_np = of_parse_phandle(np, "default-mode", 0);
+
+ if (!mode_np) {
+ pr_info("%s: no default-mode specified.\n", __func__);
+ mode_np = of_find_node_by_name(np, "mode");
+ }
+
+ if (!mode_np) {
+ pr_err("%s: could not find any mode specification\n", __func__);
+ return -EINVAL;
+ }
+
+ default_mode = (char *)mode_np->full_name;
+
+ modes_np = of_find_node_by_name(np, "modes");
+ for_each_child_of_node(modes_np, mode_np) {
+ struct videomode *vm;
+
+ vm = kmalloc(sizeof(struct videomode*), GFP_KERNEL);
+ disp->modes[disp->num_modes] = kmalloc(sizeof(struct videomode*), GFP_KERNEL);
+
+ ret |= of_video_parse_property(mode_np, "hback-porch", &vm->hback_porch);
+ ret |= of_video_parse_property(mode_np, "hfront-porch", &vm->hfront_porch);
+ ret |= of_video_parse_property(mode_np, "hactive", &vm->hactive);
+ ret |= of_video_parse_property(mode_np, "hsync-len", &vm->hsync_len);
+ ret |= of_video_parse_property(mode_np, "vback-porch", &vm->vback_porch);
+ ret |= of_video_parse_property(mode_np, "vfront-porch", &vm->vfront_porch);
+ ret |= of_video_parse_property(mode_np, "vactive", &vm->vactive);
+ ret |= of_video_parse_property(mode_np, "vsync-len", &vm->vsync_len);
+ ret |= of_video_parse_property(mode_np, "clock", &vm->clock);
+
+ if (ret)
+ return -EINVAL;
+
+ vm->hah = of_property_read_bool(mode_np, "hsync-active-high");
+ vm->vah = of_property_read_bool(mode_np, "vsync-active-high");
+ vm->interlaced = of_property_read_bool(mode_np, "interlaced");
+ vm->doublescan = of_property_read_bool(mode_np, "doublescan");
+
+ if (strcmp(default_mode,mode_np->full_name) = 0)
+ disp->default_mode = disp->num_modes;
+
+ disp->modes[disp->num_modes] = vm;
+ disp->num_modes++;
+ }
+ of_node_put(display_np);
+
+ pr_info("%s: found %d modelines. Using #%d as default\n", __func__,
+ disp->num_modes, disp->default_mode + 1);
+
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_video_modes);
+
+int of_video_mode_exists(struct device_node *np)
+{
+ struct device_node *display_np;
+ struct device_node *mode_np;
+
+ if (!np)
+ return -EINVAL;
+
+ display_np = of_parse_phandle(np, "display", 0);
+
+ if (!display_np)
+ return -EINVAL;
+
+ mode_np = of_parse_phandle(np, "default-mode", 0);
+
+ if (mode_np)
+ return 0;
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(of_video_mode_exists);
+
+int of_get_display_mode(struct device_node *np, struct drm_display_mode *dmode, int index)
+{
+ struct display disp;
+
+ of_get_video_modes(np, &disp);
+
+ if (index = OF_MODE_SELECTION)
+ index = disp.default_mode;
+ if (dmode)
+ videomode_to_display_mode(&disp, dmode, index);
+
+ of_video_free(&disp);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_display_mode);
+
+int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fbmode, int index)
+{
+ struct display disp;
+
+ of_get_video_modes(np, &disp);
+
+ if (index = OF_MODE_SELECTION)
+ index = disp.default_mode;
+ if (fbmode)
+ videomode_to_fb_mode(&disp, fbmode, index);
+
+ of_video_free(&disp);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_fb_videomode);
diff --git a/include/linux/of_videomode.h b/include/linux/of_videomode.h
new file mode 100644
index 0000000..5571ce3
--- /dev/null
+++ b/include/linux/of_videomode.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012 Sascha Hauer <s.hauer@pengutronix.de>
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * OF helpers for videomodes.
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_OF_VIDEOMODE_H
+#define __LINUX_OF_VIDEOMODE_H
+
+#define OF_MODE_SELECTION -1
+
+struct mode_property {
+ u32 min;
+ u32 typ;
+ u32 max;
+};
+
+struct display {
+ u32 width_mm;
+ u32 height_mm;
+ struct videomode **modes;
+ int default_mode;
+ int num_modes;
+};
+
+/* describe videomode in terms of hardware parameters */
+struct videomode {
+ struct mode_property hback_porch;
+ struct mode_property hfront_porch;
+ struct mode_property hactive;
+ struct mode_property hsync_len;
+
+ struct mode_property vback_porch;
+ struct mode_property vfront_porch;
+ struct mode_property vactive;
+ struct mode_property vsync_len;
+
+ struct mode_property clock;
+
+ bool hah;
+ bool vah;
+ bool interlaced;
+ bool doublescan;
+};
+
+int of_video_mode_exists(struct device_node *np);
+int videomode_to_display_mode(struct display *disp, struct drm_display_mode *dmode, int index);
+int videomode_to_fb_mode(struct display *disp, struct fb_videomode *fbmode, int index);
+int of_get_video_modes(struct device_node *np, struct display *disp);
+int of_video_mode_exists(struct device_node *np);
+int of_get_display_mode(struct device_node *np, struct drm_display_mode *dmode, int index);
+int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fbmode, int index);
+#endif /* __LINUX_OF_VIDEOMODE_H */
--
1.7.10.4
^ permalink raw reply related
* [PATCH 0/8] OMAPDSS: dss device model changes
From: Tomi Valkeinen @ 2012-09-19 8:30 UTC (permalink / raw)
To: archit, linux-omap, linux-fbdev
Cc: Tomi Valkeinen, Steve Sakoman, Lajos Molnar, Jassi Brar,
Grazvydas Ignotas, Vaibhav Hiremath
Hi,
This series contains patches that change how omapdss's panel devices
(omap_dss_device) are initialized and registered. There are two patches that
change behaviour, the rest should be just cleanups:
The patch "omap_dss_register_device() doesn't take display index" affects the
number for the "displayX" sysfs files. This hopefully doesn't affect the
userspace, as the number has never been a clear indication of what the
particular display is.
The patch "register only one display device per output" affects how panel
devices are created. Currently we support multiple panels per output, i.e. you
could have DVI and an LCD displays using the same DPI output, as long as the
DVI and LCD are not used at the same time.
This patch changes the omapdss driver to only register one display device per
output. If there are multiple displays for the output, either the first one is
picked or, if def_display has been defined in kernel parameters and the
def_display is one of the displays for this output, the def_display is picked.
See the patch for more information.
My belief is that neither patch should break things, but there's the
possibility. So I've tried to cc people who might have an opinion about this,
or perhaps test their setup with these patches.
The series is based on the latest omapdss master branch, and is available at:
git://gitorious.org/linux-omap-dss2/linux.git work/devtree-base
Tomi
Tomi Valkeinen (8):
OMAPDSS: omap_dss_register_device() doesn't take display index
OMAPDSS: Add dss_get_default_display_name()
OMAPDSS: register only one display device per output
OMAPDSS: explicitely initialize dssdev->channel for new displays
OMAPDSS: handle errors in dss_init_device
OMAPDSS: cleanup dss_recheck_connections
OMAPDSS: cleanup dss_recheck_connections further
OMAPDSS: alloc dssdevs dynamically
drivers/video/omap2/dss/core.c | 91 +++++++++++++++++++------------------
drivers/video/omap2/dss/display.c | 85 +++++++++++++++++++++++++++++++---
drivers/video/omap2/dss/dpi.c | 58 ++++++++++++++++++-----
drivers/video/omap2/dss/dsi.c | 62 +++++++++++++++++++------
drivers/video/omap2/dss/dss.h | 15 +++---
drivers/video/omap2/dss/hdmi.c | 70 ++++++++++++++++++++++------
drivers/video/omap2/dss/overlay.c | 69 ----------------------------
drivers/video/omap2/dss/rfbi.c | 58 ++++++++++++++++++-----
drivers/video/omap2/dss/sdi.c | 58 ++++++++++++++++++-----
drivers/video/omap2/dss/venc.c | 60 +++++++++++++++++++-----
10 files changed, 428 insertions(+), 198 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCH 1/8] OMAPDSS: omap_dss_register_device() doesn't take display index
From: Tomi Valkeinen @ 2012-09-19 8:30 UTC (permalink / raw)
To: archit, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1348043438-2624-1-git-send-email-tomi.valkeinen@ti.com>
We used to have all the displays of the board in one list, and we made a
"displayX" directory in the sysfs, where X was the index of the display
in the list.
This doesn't work anymore with device tree, as there's no single list to
get the number from, and it doesn't work very well even with non-DT as
we need to do some tricks to get the index nowadays.
This patch changes omap_dss_register_device() so that it doesn't take
disp_num as a parameter anymore, but uses a private increasing counter
for the display number.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/core.c | 9 +++++----
drivers/video/omap2/dss/dpi.c | 2 +-
drivers/video/omap2/dss/dsi.c | 2 +-
drivers/video/omap2/dss/dss.h | 2 +-
drivers/video/omap2/dss/hdmi.c | 2 +-
drivers/video/omap2/dss/rfbi.c | 2 +-
drivers/video/omap2/dss/sdi.c | 2 +-
drivers/video/omap2/dss/venc.c | 2 +-
8 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 58bd9c2..20c8bc8 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -450,16 +450,17 @@ static void omap_dss_dev_release(struct device *dev)
reset_device(dev, 0);
}
+static int disp_num_counter;
+
int omap_dss_register_device(struct omap_dss_device *dssdev,
- struct device *parent, int disp_num)
+ struct device *parent)
{
- WARN_ON(!dssdev->driver_name);
-
reset_device(&dssdev->dev, 1);
+
dssdev->dev.bus = &dss_bus_type;
dssdev->dev.parent = parent;
dssdev->dev.release = omap_dss_dev_release;
- dev_set_name(&dssdev->dev, "display%d", disp_num);
+ dev_set_name(&dssdev->dev, "display%d", disp_num_counter++);
return device_register(&dssdev->dev);
}
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 5ccce9b..703fc1d 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -388,7 +388,7 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)
continue;
}
- r = omap_dss_register_device(dssdev, &pdev->dev, i);
+ r = omap_dss_register_device(dssdev, &pdev->dev);
if (r)
DSSERR("device %s register failed: %d\n",
dssdev->name, r);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 8d815e3..f7078fc 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -5027,7 +5027,7 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
continue;
}
- r = omap_dss_register_device(dssdev, &dsidev->dev, i);
+ r = omap_dss_register_device(dssdev, &dsidev->dev);
if (r)
DSSERR("device %s register failed: %d\n",
dssdev->name, r);
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 5e9fd769..7bac8ee 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -185,7 +185,7 @@ int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
int omap_dss_register_device(struct omap_dss_device *dssdev,
- struct device *parent, int disp_num);
+ struct device *parent);
void omap_dss_unregister_device(struct omap_dss_device *dssdev);
void omap_dss_unregister_child_devices(struct device *parent);
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 83f1845..bb07143 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -923,7 +923,7 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
continue;
}
- r = omap_dss_register_device(dssdev, &pdev->dev, i);
+ r = omap_dss_register_device(dssdev, &pdev->dev);
if (r)
DSSERR("device %s register failed: %d\n",
dssdev->name, r);
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 2e520d3..845b4e7 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -959,7 +959,7 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev)
continue;
}
- r = omap_dss_register_device(dssdev, &pdev->dev, i);
+ r = omap_dss_register_device(dssdev, &pdev->dev);
if (r)
DSSERR("device %s register failed: %d\n",
dssdev->name, r);
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 66c8de4..c9a9045 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -212,7 +212,7 @@ static void __init sdi_probe_pdata(struct platform_device *pdev)
continue;
}
- r = omap_dss_register_device(dssdev, &pdev->dev, i);
+ r = omap_dss_register_device(dssdev, &pdev->dev);
if (r)
DSSERR("device %s register failed: %d\n",
dssdev->name, r);
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 17b3102..60bfc58 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -752,7 +752,7 @@ static void __init venc_probe_pdata(struct platform_device *pdev)
continue;
}
- r = omap_dss_register_device(dssdev, &pdev->dev, i);
+ r = omap_dss_register_device(dssdev, &pdev->dev);
if (r)
DSSERR("device %s register failed: %d\n",
dssdev->name, r);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/8] OMAPDSS: Add dss_get_default_display_name()
From: Tomi Valkeinen @ 2012-09-19 8:30 UTC (permalink / raw)
To: archit, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1348043438-2624-1-git-send-email-tomi.valkeinen@ti.com>
Add function dss_get_default_display_name() which returns the name of
the default display, given from the board file or via module parameters.
The default display name can be used by output drivers to decide which
display is the wanted one.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/core.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 20c8bc8..315f557 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -57,6 +57,11 @@ bool dss_debug;
module_param_named(debug, dss_debug, bool, 0644);
#endif
+const char *dss_get_default_display_name(void)
+{
+ return core.default_display_name;
+}
+
/* REGULATORS */
struct regulator *dss_get_vdds_dsi(void)
--
1.7.9.5
^ permalink raw reply related
* [PATCH 3/8] OMAPDSS: register only one display device per output
From: Tomi Valkeinen @ 2012-09-19 8:30 UTC (permalink / raw)
To: archit, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1348043438-2624-1-git-send-email-tomi.valkeinen@ti.com>
We have boards with multiple panel devices connected to the same
physical output, of which only one panel can be enabled at one time.
Examples of these are Overo, where you can use different daughter boards
that have different LCDs, and 3430SDP which has an LCD and a DVI output
and a physical switch to select the active display.
These are supported by omapdss so that we add all the possible display
devices at probe, but the displays are inactive until somebody enables
one. At this point the panel driver starts using the DSS, thus reserving
the physcal resource and excluding the other panels.
This is problematic:
- Panel drivers can't allocate their resources properly at probe(),
because the resources can be shared with other panels. Thus they can
be only reserved at enable time.
- Managing this in omapdss is confusing. It's not natural to have
child devices, which may not even exist (for example, a daughterboard
that is not connected).
Only some boards have multiple displays per output, and of those, only
very few have possibility of switching the display during runtime.
Because of the above points:
- We don't want to make omapdss and all the panel drivers more complex
just because some boards have complex setups.
- Only few boards support runtime switching, and afaik even then it's
not required. So we don't need to support runtime switching.
Thus we'll change to a model where we will have only one display device
per output and this cannot be (currently) changed at runtime. We'll
still have the possibility to select the display from multiple options
during boot with the default display option.
This patch accomplishes the above by changing how the output drivers
register the display device. Instead of registering all the devices
given from the board file, we'll only register one. If the default
display option is set, the output driver selects that display from its
displays. If the default display is not set, or the default display is
not one of the output's displays, the output driver selects the first
display.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dpi.c | 47 ++++++++++++++++++++++++++-------
drivers/video/omap2/dss/dsi.c | 51 ++++++++++++++++++++++++++---------
drivers/video/omap2/dss/dss.h | 1 +
drivers/video/omap2/dss/hdmi.c | 57 ++++++++++++++++++++++++++++++----------
drivers/video/omap2/dss/rfbi.c | 47 ++++++++++++++++++++++++++-------
drivers/video/omap2/dss/sdi.c | 47 ++++++++++++++++++++++++++-------
drivers/video/omap2/dss/venc.c | 47 ++++++++++++++++++++++++++-------
7 files changed, 231 insertions(+), 66 deletions(-)
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 703fc1d..6f9a199 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -371,10 +371,14 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
return 0;
}
-static void __init dpi_probe_pdata(struct platform_device *pdev)
+static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- int i, r;
+ const char *def_disp_name = dss_get_default_display_name();
+ struct omap_dss_device *def_dssdev;
+ int i;
+
+ def_dssdev = NULL;
for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i];
@@ -382,16 +386,39 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)
if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)
continue;
- r = dpi_init_display(dssdev);
- if (r) {
- DSSERR("device %s init failed: %d\n", dssdev->name, r);
- continue;
+ if (def_dssdev = NULL)
+ def_dssdev = dssdev;
+
+ if (def_disp_name != NULL &&
+ strcmp(dssdev->name, def_disp_name) = 0) {
+ def_dssdev = dssdev;
+ break;
}
+ }
- r = omap_dss_register_device(dssdev, &pdev->dev);
- if (r)
- DSSERR("device %s register failed: %d\n",
- dssdev->name, r);
+ return def_dssdev;
+}
+
+static void __init dpi_probe_pdata(struct platform_device *pdev)
+{
+ struct omap_dss_device *dssdev;
+ int r;
+
+ dssdev = dpi_find_dssdev(pdev);
+
+ if (!dssdev)
+ return;
+
+ r = dpi_init_display(dssdev);
+ if (r) {
+ DSSERR("device %s init failed: %d\n", dssdev->name, r);
+ return;
+ }
+
+ r = omap_dss_register_device(dssdev, &pdev->dev);
+ if (r) {
+ DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ return;
}
}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index f7078fc..ee9ae52 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -5006,11 +5006,15 @@ static void dsi_put_clocks(struct platform_device *dsidev)
clk_put(dsi->sys_clk);
}
-static void __init dsi_probe_pdata(struct platform_device *dsidev)
+static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev)
{
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- struct omap_dss_board_info *pdata = dsidev->dev.platform_data;
- int i, r;
+ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
+ struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
+ const char *def_disp_name = dss_get_default_display_name();
+ struct omap_dss_device *def_dssdev;
+ int i;
+
+ def_dssdev = NULL;
for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i];
@@ -5021,16 +5025,39 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
if (dssdev->phy.dsi.module != dsi->module_id)
continue;
- r = dsi_init_display(dssdev);
- if (r) {
- DSSERR("device %s init failed: %d\n", dssdev->name, r);
- continue;
+ if (def_dssdev = NULL)
+ def_dssdev = dssdev;
+
+ if (def_disp_name != NULL &&
+ strcmp(dssdev->name, def_disp_name) = 0) {
+ def_dssdev = dssdev;
+ break;
}
+ }
- r = omap_dss_register_device(dssdev, &dsidev->dev);
- if (r)
- DSSERR("device %s register failed: %d\n",
- dssdev->name, r);
+ return def_dssdev;
+}
+
+static void __init dsi_probe_pdata(struct platform_device *dsidev)
+{
+ struct omap_dss_device *dssdev;
+ int r;
+
+ dssdev = dsi_find_dssdev(dsidev);
+
+ if (!dssdev)
+ return;
+
+ r = dsi_init_display(dssdev);
+ if (r) {
+ DSSERR("device %s init failed: %d\n", dssdev->name, r);
+ return;
+ }
+
+ r = omap_dss_register_device(dssdev, &dsidev->dev);
+ if (r) {
+ DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ return;
}
}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 7bac8ee..a977826 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -175,6 +175,7 @@ struct seq_file;
struct platform_device;
/* core */
+const char *dss_get_default_display_name(void);
struct bus_type *dss_get_bus(void);
struct regulator *dss_get_vdds_dsi(void);
struct regulator *dss_get_vdds_sdi(void);
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index bb07143..76d100b 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -901,32 +901,61 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
#endif
-static void __init hdmi_probe_pdata(struct platform_device *pdev)
+static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- int r, i;
+ const char *def_disp_name = dss_get_default_display_name();
+ struct omap_dss_device *def_dssdev;
+ int i;
+
+ def_dssdev = NULL;
for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i];
- struct omap_dss_hdmi_data *priv = dssdev->data;
if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
continue;
- hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
- hdmi.ls_oe_gpio = priv->ls_oe_gpio;
- hdmi.hpd_gpio = priv->hpd_gpio;
+ if (def_dssdev = NULL)
+ def_dssdev = dssdev;
- r = hdmi_init_display(dssdev);
- if (r) {
- DSSERR("device %s init failed: %d\n", dssdev->name, r);
- continue;
+ if (def_disp_name != NULL &&
+ strcmp(dssdev->name, def_disp_name) = 0) {
+ def_dssdev = dssdev;
+ break;
}
+ }
+
+ return def_dssdev;
+}
+
+static void __init hdmi_probe_pdata(struct platform_device *pdev)
+{
+ struct omap_dss_device *dssdev;
+ struct omap_dss_hdmi_data *priv;
+ int r;
- r = omap_dss_register_device(dssdev, &pdev->dev);
- if (r)
- DSSERR("device %s register failed: %d\n",
- dssdev->name, r);
+ dssdev = hdmi_find_dssdev(pdev);
+
+ if (!dssdev)
+ return;
+
+ priv = dssdev->data;
+
+ hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
+ hdmi.ls_oe_gpio = priv->ls_oe_gpio;
+ hdmi.hpd_gpio = priv->hpd_gpio;
+
+ r = hdmi_init_display(dssdev);
+ if (r) {
+ DSSERR("device %s init failed: %d\n", dssdev->name, r);
+ return;
+ }
+
+ r = omap_dss_register_device(dssdev, &pdev->dev);
+ if (r) {
+ DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ return;
}
}
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 845b4e7..1127037 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -942,10 +942,14 @@ static int __init rfbi_init_display(struct omap_dss_device *dssdev)
return 0;
}
-static void __init rfbi_probe_pdata(struct platform_device *pdev)
+static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- int i, r;
+ const char *def_disp_name = dss_get_default_display_name();
+ struct omap_dss_device *def_dssdev;
+ int i;
+
+ def_dssdev = NULL;
for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i];
@@ -953,16 +957,39 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev)
if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
continue;
- r = rfbi_init_display(dssdev);
- if (r) {
- DSSERR("device %s init failed: %d\n", dssdev->name, r);
- continue;
+ if (def_dssdev = NULL)
+ def_dssdev = dssdev;
+
+ if (def_disp_name != NULL &&
+ strcmp(dssdev->name, def_disp_name) = 0) {
+ def_dssdev = dssdev;
+ break;
}
+ }
+
+ return def_dssdev;
+}
+
+static void __init rfbi_probe_pdata(struct platform_device *pdev)
+{
+ struct omap_dss_device *dssdev;
+ int r;
+
+ dssdev = rfbi_find_dssdev(pdev);
- r = omap_dss_register_device(dssdev, &pdev->dev);
- if (r)
- DSSERR("device %s register failed: %d\n",
- dssdev->name, r);
+ if (!dssdev)
+ return;
+
+ r = rfbi_init_display(dssdev);
+ if (r) {
+ DSSERR("device %s init failed: %d\n", dssdev->name, r);
+ return;
+ }
+
+ r = omap_dss_register_device(dssdev, &pdev->dev);
+ if (r) {
+ DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ return;
}
}
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index c9a9045..0aaa7f3 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -195,10 +195,14 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
return 0;
}
-static void __init sdi_probe_pdata(struct platform_device *pdev)
+static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- int i, r;
+ const char *def_disp_name = dss_get_default_display_name();
+ struct omap_dss_device *def_dssdev;
+ int i;
+
+ def_dssdev = NULL;
for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i];
@@ -206,16 +210,39 @@ static void __init sdi_probe_pdata(struct platform_device *pdev)
if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)
continue;
- r = sdi_init_display(dssdev);
- if (r) {
- DSSERR("device %s init failed: %d\n", dssdev->name, r);
- continue;
+ if (def_dssdev = NULL)
+ def_dssdev = dssdev;
+
+ if (def_disp_name != NULL &&
+ strcmp(dssdev->name, def_disp_name) = 0) {
+ def_dssdev = dssdev;
+ break;
}
+ }
- r = omap_dss_register_device(dssdev, &pdev->dev);
- if (r)
- DSSERR("device %s register failed: %d\n",
- dssdev->name, r);
+ return def_dssdev;
+}
+
+static void __init sdi_probe_pdata(struct platform_device *pdev)
+{
+ struct omap_dss_device *dssdev;
+ int r;
+
+ dssdev = sdi_find_dssdev(pdev);
+
+ if (!dssdev)
+ return;
+
+ r = sdi_init_display(dssdev);
+ if (r) {
+ DSSERR("device %s init failed: %d\n", dssdev->name, r);
+ return;
+ }
+
+ r = omap_dss_register_device(dssdev, &pdev->dev);
+ if (r) {
+ DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ return;
}
}
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 60bfc58..b9c0a8f 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -735,10 +735,14 @@ static void venc_put_clocks(void)
clk_put(venc.tv_dac_clk);
}
-static void __init venc_probe_pdata(struct platform_device *pdev)
+static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- int r, i;
+ const char *def_disp_name = dss_get_default_display_name();
+ struct omap_dss_device *def_dssdev;
+ int i;
+
+ def_dssdev = NULL;
for (i = 0; i < pdata->num_devices; ++i) {
struct omap_dss_device *dssdev = pdata->devices[i];
@@ -746,16 +750,39 @@ static void __init venc_probe_pdata(struct platform_device *pdev)
if (dssdev->type != OMAP_DISPLAY_TYPE_VENC)
continue;
- r = venc_init_display(dssdev);
- if (r) {
- DSSERR("device %s init failed: %d\n", dssdev->name, r);
- continue;
+ if (def_dssdev = NULL)
+ def_dssdev = dssdev;
+
+ if (def_disp_name != NULL &&
+ strcmp(dssdev->name, def_disp_name) = 0) {
+ def_dssdev = dssdev;
+ break;
}
+ }
+
+ return def_dssdev;
+}
+
+static void __init venc_probe_pdata(struct platform_device *pdev)
+{
+ struct omap_dss_device *dssdev;
+ int r;
+
+ dssdev = venc_find_dssdev(pdev);
+
+ if (!dssdev)
+ return;
+
+ r = venc_init_display(dssdev);
+ if (r) {
+ DSSERR("device %s init failed: %d\n", dssdev->name, r);
+ return;
+ }
- r = omap_dss_register_device(dssdev, &pdev->dev);
- if (r)
- DSSERR("device %s register failed: %d\n",
- dssdev->name, r);
+ r = omap_dss_register_device(dssdev, &pdev->dev);
+ if (r) {
+ DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ return;
}
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH 4/8] OMAPDSS: explicitely initialize dssdev->channel for new displays
From: Tomi Valkeinen @ 2012-09-19 8:30 UTC (permalink / raw)
To: archit, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1348043438-2624-1-git-send-email-tomi.valkeinen@ti.com>
HDMI and VENC outputs always use the DIGIT output from DISPC. The dssdev
struct contains "channel" field which is used to specify the DISPC
output for the display, but this was not used for HDMI and VENC.
This patch fills the channel field explicitely for HDMI and VENC
displays so that we can always rely on the channel field.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/hdmi.c | 2 ++
drivers/video/omap2/dss/venc.c | 2 ++
2 files changed, 4 insertions(+)
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 76d100b..3b10e18 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -946,6 +946,8 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
hdmi.ls_oe_gpio = priv->ls_oe_gpio;
hdmi.hpd_gpio = priv->hpd_gpio;
+ dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
+
r = hdmi_init_display(dssdev);
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index b9c0a8f..88fa6ea 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -773,6 +773,8 @@ static void __init venc_probe_pdata(struct platform_device *pdev)
if (!dssdev)
return;
+ dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
+
r = venc_init_display(dssdev);
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 5/8] OMAPDSS: handle errors in dss_init_device
From: Tomi Valkeinen @ 2012-09-19 8:30 UTC (permalink / raw)
To: archit, linux-omap, linux-fbdev; +Cc: Tomi Valkeinen
In-Reply-To: <1348043438-2624-1-git-send-email-tomi.valkeinen@ti.com>
Add error handling to dss_init_device(), which has, for some reason,
been missing.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/core.c | 4 +++-
drivers/video/omap2/dss/display.c | 23 ++++++++++++++++++-----
drivers/video/omap2/dss/dss.h | 2 +-
3 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 315f557..9315ece 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -358,7 +358,9 @@ static int dss_driver_probe(struct device *dev)
dev_name(dev), dssdev->driver_name,
dssdrv->driver.name);
- dss_init_device(core.pdev, dssdev);
+ r = dss_init_device(core.pdev, dssdev);
+ if (r)
+ return r;
force = core.default_display_name &&
strcmp(core.default_display_name, dssdev->name) = 0;
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 5f09d503..f719010 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -320,26 +320,39 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
}
EXPORT_SYMBOL(omapdss_default_get_timings);
-void dss_init_device(struct platform_device *pdev,
+int dss_init_device(struct platform_device *pdev,
struct omap_dss_device *dssdev)
{
struct device_attribute *attr;
- int i;
- int r;
+ int i, r;
/* create device sysfs files */
i = 0;
while ((attr = display_sysfs_attrs[i++]) != NULL) {
r = device_create_file(&dssdev->dev, attr);
- if (r)
+ if (r) {
+ for (i = i - 2; i >= 0; i--) {
+ attr = display_sysfs_attrs[i];
+ device_remove_file(&dssdev->dev, attr);
+ }
+
DSSERR("failed to create sysfs file\n");
+ return r;
+ }
}
/* create display? sysfs links */
r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
dev_name(&dssdev->dev));
- if (r)
+ if (r) {
+ while ((attr = display_sysfs_attrs[i++]) != NULL)
+ device_remove_file(&dssdev->dev, attr);
+
DSSERR("failed to create sysfs display link\n");
+ return r;
+ }
+
+ return 0;
}
void dss_uninit_device(struct platform_device *pdev,
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index a977826..98e8273 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -228,7 +228,7 @@ int dss_suspend_all_devices(void);
int dss_resume_all_devices(void);
void dss_disable_all_devices(void);
-void dss_init_device(struct platform_device *pdev,
+int dss_init_device(struct platform_device *pdev,
struct omap_dss_device *dssdev);
void dss_uninit_device(struct platform_device *pdev,
struct omap_dss_device *dssdev);
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox