* Re: [PATCH V5 1/2] video: exynos_dp: Add device tree support to DP driver
From: Sylwester Nawrocki @ 2012-10-12 21:44 UTC (permalink / raw)
To: Ajay Kumar
Cc: linux-samsung-soc, linux-fbdev, jg1.han, devicetree-discuss,
FlorianSchandinat, sylvester.nawrocki, tomasz.figa, thomas.ab
In-Reply-To: <1350074859-23226-1-git-send-email-ajaykumar.rs@samsung.com>
On 10/12/2012 10:47 PM, Ajay Kumar 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.
>
> Signed-off-by: Ajay Kumar<ajaykumar.rs@samsung.com>
> Acked-by: Jingoo Han<jg1.han@samsung.com>
> ---
> drivers/video/exynos/exynos_dp_core.c | 161 ++++++++++++++++++++++++++++++---
> drivers/video/exynos/exynos_dp_core.h | 2 +
> 2 files changed, 149 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
> index d55470e..62932ba 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,6 +857,99 @@ 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, "hsync-active-high", NULL))
> + dp_video_config->h_sync_polarity = 1;
> +
> + if (of_get_property(dp_node, "vsync-active-high", NULL))
> + dp_video_config->v_sync_polarity = 1;
> +
> + if (of_get_property(dp_node, "interlaced", NULL))
> + dp_video_config->interlaced = 1;
of_property_read_bool() could also be used here.
> +
> + 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);
Shouldn't it be checked whether all these required properties are present ?
If someone forgets to specify any one the driver will silently ignore it,
not giving a clue what's wrong.
> + return pd;
> +}
> +
> +void exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
> +{
> + struct device_node *dp_phy_node;
> + u32 phy_base;
> + void *virt_phy_base;
> +
> + dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy");
> + if (!dp_phy_node) {
> + dp->dp_phy_addr = NULL;
Is this required ? You've allocated dp with kzalloc().
> + return;
> + }
> +
> + of_property_read_u32(dp_phy_node, "reg",&phy_base);
> + of_property_read_u32(dp_phy_node, "samsung,enable-mask",
> + &dp->enable_mask);
I think you should check the return values, these are required properties.
Some error logs might be useful here.
> + virt_phy_base = ioremap(phy_base, SZ_4);
How about assigning to dp->dp_phy_addr directly and gettting rid of
virt_phy_base ?
> + 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 exynos_dp_phy_init(struct exynos_dp_device *dp)
> +{
> + u32 reg;
> +
> + reg = __raw_readl(dp->dp_phy_addr);
> + reg |= dp->enable_mask;
> + __raw_writel(reg, dp->dp_phy_addr);
> +}
> +
> +void exynos_dp_phy_exit(struct exynos_dp_device *dp)
> +{
> + u32 reg;
> +
> + reg = __raw_readl(dp->dp_phy_addr);
> + reg&= ~(dp->enable_mask);
> + __raw_writel(reg, dp->dp_phy_addr);
> +}
> +#endif /* CONFIG_OF */
> +
> static int __devinit exynos_dp_probe(struct platform_device *pdev)
> {
> struct resource *res;
> @@ -864,12 +958,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
>
> 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 +967,21 @@ 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);
> + } else {
> + pdata = pdev->dev.platform_data;
> + }
> +
> + if (!pdata) {
> + dev_err(&pdev->dev, "no platform data\n");
> + return -EINVAL;
> + }
> +
This check is only reqired for non-dt case, might be worth to move
it under else statement above.
> dp->clock = devm_clk_get(&pdev->dev, "dp");
> if (IS_ERR(dp->clock)) {
> dev_err(&pdev->dev, "failed to get clock\n");
> @@ -909,8 +1012,14 @@ 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)
> + exynos_dp_phy_init(dp);
> + } else {
> + if (pdata->phy_init)
> + pdata->phy_init();
> + }
>
> exynos_dp_init_dp(dp);
>
> @@ -953,8 +1062,13 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
> struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> struct exynos_dp_device *dp = platform_get_drvdata(pdev);
This doesn't belong to your patch, but the above 2 lines could be written as:
struct exynos_dp_device *dp = dev_get_drvdata(&pdev->dev);
Same in functions exynos_dp_suspend() and exynos_dp_resume().
>
> - if (pdata&& pdata->phy_exit)
> - pdata->phy_exit();
> + if (pdev->dev.of_node) {
> + if (dp->dp_phy_addr)
> + exynos_dp_phy_exit(dp);
> + } else {
> + if (pdata&& pdata->phy_exit)
> + pdata->phy_exit();
> + }
It is not possible to have valid dp->dp_phy_addr pointer without
valid pdev->dev.of_node, is it ?
Can't this (and all similar occurrences) be simplified to:
if (dp->dp_phy_addr)
exynos_dp_phy_exit(dp);
else if (pdata->phy_exit)
pdata->phy_exit();
?
It just requires dp->dp_phy_addr being NULL for non-dt case.
pdata is never NULL, otherwise probe() would have already failed.
> clk_disable_unprepare(dp->clock);
>
> @@ -968,8 +1082,13 @@ static int exynos_dp_suspend(struct device *dev)
> struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> struct exynos_dp_device *dp = platform_get_drvdata(pdev);
>
> - if (pdata&& pdata->phy_exit)
> - pdata->phy_exit();
> + if (dev->of_node) {
> + if (dp->dp_phy_addr)
> + exynos_dp_phy_exit(dp);
> + } else {
> + if (pdata&& pdata->phy_exit)
> + pdata->phy_exit();
> + }
>
> clk_disable_unprepare(dp->clock);
>
> @@ -982,8 +1101,13 @@ static int exynos_dp_resume(struct device *dev)
> struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> struct exynos_dp_device *dp = platform_get_drvdata(pdev);
>
> - if (pdata&& pdata->phy_init)
> - pdata->phy_init();
> + if (dev->of_node) {
> + if (dp->dp_phy_addr)
> + exynos_dp_phy_init(dp);
> + } else {
> + if (pdata&& pdata->phy_init)
> + pdata->phy_init();
> + }
>
> clk_prepare_enable(dp->clock);
>
> @@ -1013,6 +1137,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
> +
How about just dropping this #ifdef, since you're using of_match_ptr() ?
> static struct platform_driver exynos_dp_driver = {
> .probe = exynos_dp_probe,
> .remove = __devexit_p(exynos_dp_remove),
> @@ -1020,6 +1152,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..569858b 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;
Nit: "dp" is already within the structure name. How about just
naming it phy_addr ? dp->phy_addr might look better than
dp->dp_phy_addr ;)
> + unsigned int enable_mask;
>
> struct video_info *video_info;
> struct link_train link_train;
^ permalink raw reply
* Re: [PATCH V5 1/2] video: exynos_dp: Add device tree support to DP driver
From: Tomasz Figa @ 2012-10-12 21:54 UTC (permalink / raw)
To: Sylwester Nawrocki
Cc: Ajay Kumar, linux-samsung-soc, linux-fbdev, jg1.han,
devicetree-discuss, FlorianSchandinat, thomas.ab
In-Reply-To: <50788F25.2040003@gmail.com>
Dnia piątek, 12 października 2012 23:44:05 Sylwester Nawrocki pisze:
> On 10/12/2012 10:47 PM, Ajay Kumar 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.
> >
> > Signed-off-by: Ajay Kumar<ajaykumar.rs@samsung.com>
> > Acked-by: Jingoo Han<jg1.han@samsung.com>
> > ---
> >
> > drivers/video/exynos/exynos_dp_core.c | 161
> > ++++++++++++++++++++++++++++++---
> > drivers/video/exynos/exynos_dp_core.h | 2 +
> > 2 files changed, 149 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/video/exynos/exynos_dp_core.c
> > b/drivers/video/exynos/exynos_dp_core.c index d55470e..62932ba 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,6 +857,99 @@ 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, "hsync-active-high", NULL))
> > + dp_video_config->h_sync_polarity = 1;
> > +
> > + if (of_get_property(dp_node, "vsync-active-high", NULL))
> > + dp_video_config->v_sync_polarity = 1;
> > +
> > + if (of_get_property(dp_node, "interlaced", NULL))
> > + dp_video_config->interlaced = 1;
>
> of_property_read_bool() could also be used here.
Wouldn't it make the property mandatory?
I would just use of_find_property here, instead of of_get_property.
Best regards,
Tomasz Figa
^ permalink raw reply
* Re: [PATCH V5 1/2] video: exynos_dp: Add device tree support to DP driver
From: Sylwester Nawrocki @ 2012-10-12 22:14 UTC (permalink / raw)
To: Tomasz Figa
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
FlorianSchandinat-Mmb7MZpHnFY,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
jg1.han-Sze3O3UU22JBDgjK7y7TUQ, thomas.ab-Sze3O3UU22JBDgjK7y7TUQ,
Sylwester Nawrocki, Ajay Kumar
In-Reply-To: <1909932.BXc5ALaqMM@flatron>
On 10/12/2012 11:54 PM, Tomasz Figa wrote:
>>> + if (of_get_property(dp_node, "interlaced", NULL))
>>> + dp_video_config->interlaced = 1;
>>
>> of_property_read_bool() could also be used here.
>
> Wouldn't it make the property mandatory?
No, it wouldn't. of_property_read_bool() uses of_find_property()
internally. It just returns true if property is found or false
otherwise. Anyway, it appears of_get_property(..., NULL) pattern
is commonly used for boolean properties.
> I would just use of_find_property here, instead of of_get_property.
>
> Best regards,
> Tomasz Figa
^ permalink raw reply
* Re: [PATCH V5 1/2] video: exynos_dp: Add device tree support to DP driver
From: Tomasz Figa @ 2012-10-12 22:22 UTC (permalink / raw)
To: Sylwester Nawrocki
Cc: Ajay Kumar, linux-samsung-soc, linux-fbdev, jg1.han,
devicetree-discuss, FlorianSchandinat, thomas.ab
In-Reply-To: <5078964F.4000902@gmail.com>
On Saturday 13 of October 2012 00:14:39 Sylwester Nawrocki wrote:
> On 10/12/2012 11:54 PM, Tomasz Figa wrote:
> >>> + if (of_get_property(dp_node, "interlaced", NULL))
> >>> + dp_video_config->interlaced = 1;
> >>
> >> of_property_read_bool() could also be used here.
> >
> > Wouldn't it make the property mandatory?
>
> No, it wouldn't. of_property_read_bool() uses of_find_property()
> internally. It just returns true if property is found or false
> otherwise.
Right, sorry. I thought that all of_property_read_* return error in case
of missing property.
> Anyway, it appears of_get_property(..., NULL) pattern
> is commonly used for boolean properties.
I guess all three of them should be fine in this case, but since there is
a dedicated function for bool, it might be the best solution here indeed.
Best regards,
Tomasz Figa
^ permalink raw reply
* enquiry
From: Royaldoc International Globe @ 2012-10-12 23:37 UTC (permalink / raw)
To: linux-fbdev
Royaldoc International Globe,
103, Park son road,
Carlifonia,USA.
63-1-3522 2501
royaldoc@inbox.org.tw
We are interested in purchasing your products and I would like to
make an inquiry. can you inform me of your minimum order quantity? and
also your maximum order quantity, if there is any available sample do
let me know.
Sincerely,
Purchase Manager
Alan Smith
^ permalink raw reply
* Re: [PATCH RESEND] video/udlfb: fix line counting in fb_write
From: Alexander Holler @ 2012-10-13 11:44 UTC (permalink / raw)
To: Florian Tobias Schandinat; +Cc: linux-kernel, Bernie Thompson, linux-fbdev
In-Reply-To: <50756A21.1020700@gmx.de>
Am 10.10.2012 14:29, schrieb Florian Tobias Schandinat:
> On 08/14/2012 07:11 AM, Alexander Holler wrote:
>> Line 0 and 1 were both written to line 0 (on the display) and all
>> subsequent
>> lines had an offset of -1. The result was that the last line on the display
>> was never overwritten by writes to /dev/fbN.
>>
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Alexander Holler <holler@ahsoftware.de>
>
> As Bernie agreed but didn't send me a pull request, I applied this one.
Thanks a lot.
> Though the formatting was screwed up and I had to fix it...
Sorry, must have happened because I've used "Edit as new" in Thunderbird
to resend the patch while just adding the RESEND to the subject.
Good to know.
Thanks,
Alexander
^ permalink raw reply
* (no subject)
From: Alexey Dobriyan @ 2012-10-14 10:03 UTC (permalink / raw)
To: linux-fbdev
http://www.art-e-choke.com/blog/wp-content/plugins/zcoawuuqveq/bbc.html
^ permalink raw reply
* Re: [PATCH V5 2/2] video: exynos_dp: device tree documentation
From: Jingoo Han @ 2012-10-15 6:13 UTC (permalink / raw)
To: 'Ajay Kumar'
Cc: linux-samsung-soc, linux-fbdev, devicetree-discuss,
FlorianSchandinat, sylvester.nawrocki, tomasz.figa, thomas.ab,
'Jingoo Han'
In-Reply-To: <1350074859-23226-2-git-send-email-ajaykumar.rs@samsung.com>
On Saturday, October 13, 2012 5:48 AM Ajay kumar wrote
>
> Add documentation for the DT bindings in exynos display port driver.
>
> Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
> ---
> .../devicetree/bindings/video/exynos_dp.txt | 80 ++++++++++++++++++++
> 1 files changed, 80 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/video/exynos_dp.txt
>
> diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt
> b/Documentation/devicetree/bindings/video/exynos_dp.txt
> new file mode 100644
> index 0000000..e19594b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt
> @@ -0,0 +1,80 @@
> +The Exynos display port interface should be configured based on the
> +based on the type of panel connected to it.
'based on' is duplicated. So, please fix it as bellows:
+The Exynos display port interface should be configured based on
+the type of panel connected to it.
> +
> +We use two nodes:
> + -display-port-controller node
> + -dptx-phy node(defined inside display-port-controller node)
> +
> +For the DP-PHY initialization, we use the dptx-phy node.
> +Required properties for dptx-phy:
> + -reg:
> + Base address of DP PHY register.
> + -samsung,enable-mask:
> + The bit-mask used to enable/disable DP PHY.
> +
> +For the Panel initialization, we read data from display-port-controller node.
> +Required properties for display-port-controller:
> + -compatible:
> + should be "samsung,exynos5-dp".
> + -reg:
> + physical base address of the controller and length
> + of memory mapped region.
> + -interrupts:
> + interrupt combiner values.
> + -interrupt-parent:
> + phandle to Interrupt combiner node.
> + -samsung,color-space:
> + input video data format.
> + COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
> + -samsung,dynamic-range:
> + dynamic range for input video data.
> + VESA = 0, CEA = 1
> + -samsung,ycbcr-coeff:
> + YCbCr co-efficients for input video.
> + COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
> + -samsung,color-depth:
> + number of bits per colour component.
> + COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
> + -samsung,link-rate:
> + link rate supported by the panel.
> + LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
> + -samsung,lane-count:
> + number of lanes supported by the panel.
> + LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
> +
> +Optional properties for display-port-controller:
> + -interlaced:
> + interlace scan mode.
> + Progressive if defined, Interlaced if not defined
> + -vsync-active-high:
> + VSYNC polarity configuration.
> + High if defined, Low if not defined
> + -hsync-active-high:
> + HSYNC polarity configuration.
> + High if defined, Low if not defined
> +
> +Example:
> +
> +SOC specific portion:
> + display-port-controller {
> + compatible = "samsung,exynos5-dp";
> + reg = <0x145b0000 0x10000>;
> + interrupts = <10 3>;
> + interrupt-parent = <&combiner>;
> +
> + dptx-phy {
> + reg = <0x10040720>;
> + samsung,enable-mask = <1>;
> + };
> +
> + };
> +
> +Board Specific portion:
> + display-port-controller {
> + samsung,color-space = <0>;
> + samsung,dynamic-range = <0>;
> + samsung,ycbcr-coeff = <0>;
> + samsung,color-depth = <1>;
> + samsung,link-rate = <0x0a>;
> + samsung,lane-count = <2>;
> + };
> --
> 1.7.0.4
^ permalink raw reply
* Re: [PATCH V5 1/2] video: exynos_dp: Add device tree support to DP driver
From: Jingoo Han @ 2012-10-15 8:14 UTC (permalink / raw)
To: 'Sylwester Nawrocki', 'Ajay Kumar'
Cc: linux-samsung-soc, linux-fbdev, devicetree-discuss,
FlorianSchandinat, tomasz.figa, thomas.ab, 'Jingoo Han'
In-Reply-To: <50788F25.2040003@gmail.com>
On Saturday, October 13, 2012 6:44 AM Sylwester Nawrocki wrote
>
> On 10/12/2012 10:47 PM, Ajay Kumar 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.
> >
> > Signed-off-by: Ajay Kumar<ajaykumar.rs@samsung.com>
> > Acked-by: Jingoo Han<jg1.han@samsung.com>
> > ---
> > drivers/video/exynos/exynos_dp_core.c | 161 ++++++++++++++++++++++++++++++---
> > drivers/video/exynos/exynos_dp_core.h | 2 +
> > 2 files changed, 149 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
> > index d55470e..62932ba 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,6 +857,99 @@ 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, "hsync-active-high", NULL))
> > + dp_video_config->h_sync_polarity = 1;
> > +
> > + if (of_get_property(dp_node, "vsync-active-high", NULL))
> > + dp_video_config->v_sync_polarity = 1;
> > +
> > + if (of_get_property(dp_node, "interlaced", NULL))
> > + dp_video_config->interlaced = 1;
>
> of_property_read_bool() could also be used here.
OK, right.
of_property_read_bool() would be better.
>
> > +
> > + 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);
>
> Shouldn't it be checked whether all these required properties are present ?
> If someone forgets to specify any one the driver will silently ignore it,
> not giving a clue what's wrong.
OK, right.
>
> > + return pd;
> > +}
> > +
> > +void exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
> > +{
> > + struct device_node *dp_phy_node;
> > + u32 phy_base;
> > + void *virt_phy_base;
> > +
> > + dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy");
> > + if (!dp_phy_node) {
> > + dp->dp_phy_addr = NULL;
>
> Is this required ? You've allocated dp with kzalloc().
OK, right.
>
> > + return;
> > + }
> > +
> > + of_property_read_u32(dp_phy_node, "reg",&phy_base);
> > + of_property_read_u32(dp_phy_node, "samsung,enable-mask",
> > + &dp->enable_mask);
>
> I think you should check the return values, these are required properties.
> Some error logs might be useful here.
OK, right.
>
> > + virt_phy_base = ioremap(phy_base, SZ_4);
>
> How about assigning to dp->dp_phy_addr directly and gettting rid of
> virt_phy_base ?
OK, right.
There is no reason, virt_phy_base should be removed.
>
> > + 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 exynos_dp_phy_init(struct exynos_dp_device *dp)
> > +{
> > + u32 reg;
> > +
> > + reg = __raw_readl(dp->dp_phy_addr);
> > + reg |= dp->enable_mask;
> > + __raw_writel(reg, dp->dp_phy_addr);
> > +}
> > +
> > +void exynos_dp_phy_exit(struct exynos_dp_device *dp)
> > +{
> > + u32 reg;
> > +
> > + reg = __raw_readl(dp->dp_phy_addr);
> > + reg&= ~(dp->enable_mask);
> > + __raw_writel(reg, dp->dp_phy_addr);
> > +}
> > +#endif /* CONFIG_OF */
> > +
> > static int __devinit exynos_dp_probe(struct platform_device *pdev)
> > {
> > struct resource *res;
> > @@ -864,12 +958,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
> >
> > 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 +967,21 @@ 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);
> > + } else {
> > + pdata = pdev->dev.platform_data;
> > + }
> > +
> > + if (!pdata) {
> > + dev_err(&pdev->dev, "no platform data\n");
> > + return -EINVAL;
> > + }
> > +
>
> This check is only reqired for non-dt case, might be worth to move
> it under else statement above.
OK, right.
>
> > dp->clock = devm_clk_get(&pdev->dev, "dp");
> > if (IS_ERR(dp->clock)) {
> > dev_err(&pdev->dev, "failed to get clock\n");
> > @@ -909,8 +1012,14 @@ 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)
> > + exynos_dp_phy_init(dp);
> > + } else {
> > + if (pdata->phy_init)
> > + pdata->phy_init();
> > + }
> >
> > exynos_dp_init_dp(dp);
> >
> > @@ -953,8 +1062,13 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
> > struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> > struct exynos_dp_device *dp = platform_get_drvdata(pdev);
>
> This doesn't belong to your patch, but the above 2 lines could be written as:
>
> struct exynos_dp_device *dp = dev_get_drvdata(&pdev->dev);
>
> Same in functions exynos_dp_suspend() and exynos_dp_resume().
No, above 2 lines cannot be reduced to 1 line, as you mentioned.
This is because it makes build error.
>
> >
> > - if (pdata&& pdata->phy_exit)
> > - pdata->phy_exit();
> > + if (pdev->dev.of_node) {
> > + if (dp->dp_phy_addr)
> > + exynos_dp_phy_exit(dp);
> > + } else {
> > + if (pdata&& pdata->phy_exit)
> > + pdata->phy_exit();
> > + }
>
> It is not possible to have valid dp->dp_phy_addr pointer without
> valid pdev->dev.of_node, is it ?
Right, however, I prefer coding style as bellow:
if (pdev->dev.of_node)
DT
else
non-DT
>
> Can't this (and all similar occurrences) be simplified to:
>
> if (dp->dp_phy_addr)
> exynos_dp_phy_exit(dp);
> else if (pdata->phy_exit)
> pdata->phy_exit();
> ?
>
> It just requires dp->dp_phy_addr being NULL for non-dt case.
> pdata is never NULL, otherwise probe() would have already failed.
OK, right.
pdata can be removed.
>
> > clk_disable_unprepare(dp->clock);
> >
> > @@ -968,8 +1082,13 @@ static int exynos_dp_suspend(struct device *dev)
> > struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> > struct exynos_dp_device *dp = platform_get_drvdata(pdev);
> >
> > - if (pdata&& pdata->phy_exit)
> > - pdata->phy_exit();
> > + if (dev->of_node) {
> > + if (dp->dp_phy_addr)
> > + exynos_dp_phy_exit(dp);
> > + } else {
> > + if (pdata&& pdata->phy_exit)
> > + pdata->phy_exit();
> > + }
> >
> > clk_disable_unprepare(dp->clock);
> >
> > @@ -982,8 +1101,13 @@ static int exynos_dp_resume(struct device *dev)
> > struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> > struct exynos_dp_device *dp = platform_get_drvdata(pdev);
> >
> > - if (pdata&& pdata->phy_init)
> > - pdata->phy_init();
> > + if (dev->of_node) {
> > + if (dp->dp_phy_addr)
> > + exynos_dp_phy_init(dp);
> > + } else {
> > + if (pdata&& pdata->phy_init)
> > + pdata->phy_init();
> > + }
> >
> > clk_prepare_enable(dp->clock);
> >
> > @@ -1013,6 +1137,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
> > +
>
> How about just dropping this #ifdef, since you're using of_match_ptr() ?
OK, right.
>
> > static struct platform_driver exynos_dp_driver = {
> > .probe = exynos_dp_probe,
> > .remove = __devexit_p(exynos_dp_remove),
> > @@ -1020,6 +1152,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..569858b 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;
>
> Nit: "dp" is already within the structure name. How about just
> naming it phy_addr ? dp->phy_addr might look better than
> dp->dp_phy_addr ;)
OK, right.
>
> > + unsigned int enable_mask;
> >
> > struct video_info *video_info;
> > struct link_train link_train;
Ajay,
When CONFIG_OF is not enabled, it makes build errors.
In addition, exynos_dp_dt_parse_phydata needs return value,
instead of returning void.
Best regards,
Jingoo Han
> --
> 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 V6 1/2] video: exynos_dp: Add device tree support to DP driver
From: Jingoo Han @ 2012-10-15 9:12 UTC (permalink / raw)
To: 'Florian Tobias Schandinat'
Cc: linux-fbdev, linux-samsung-soc, devicetree-discuss,
'Ajay Kumar', 'Sylwester Nawrocki',
'Tomasz Figa', 'Thomas Abraham',
'Jingoo Han'
From: Ajay Kumar <ajaykumar.rs@samsung.com>
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.
Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
This patch is tested with Exynos5250.
Changes since v6:
- Check return values of required properties
- Replace dp_phy_addr with phy_addr
- Remove unnecessary NULL deference checking for 'pdata'
- Remove unncessary 'virt_phy_base' variable
- Make functions static
- Fix build errors when CONFIG_OF option is diabled
- Add return values to exynos_dp_dt_parse_phydata()
drivers/video/exynos/exynos_dp_core.c | 206 ++++++++++++++++++++++++++++++---
drivers/video/exynos/exynos_dp_core.h | 2 +
2 files changed, 194 insertions(+), 14 deletions(-)
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index d55470e..0d9c0ee 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,6 +857,145 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
return IRQ_HANDLED;
}
+#ifdef CONFIG_OF
+static 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;
+
+ dp_video_config->h_sync_polarity + of_property_read_bool(dp_node, "hsync-active-high");
+
+ dp_video_config->v_sync_polarity + of_property_read_bool(dp_node, "vsync-active-high");
+
+ dp_video_config->interlaced + of_property_read_bool(dp_node, "interlaced");
+
+ if (of_property_read_u32(dp_node, "samsung,color-space",
+ &dp_video_config->color_space)) {
+ dev_err(dev, "failed to get color-space\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,dynamic-range",
+ &dp_video_config->dynamic_range)) {
+ dev_err(dev, "failed to get dynamic-range\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
+ &dp_video_config->ycbcr_coeff)) {
+ dev_err(dev, "failed to get ycbcr-coeff\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,color-depth",
+ &dp_video_config->color_depth)) {
+ dev_err(dev, "failed to get color-depth\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,link-rate",
+ &dp_video_config->link_rate)) {
+ dev_err(dev, "failed to get link-rate\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,lane-count",
+ &dp_video_config->lane_count)) {
+ dev_err(dev, "failed to get lane-count\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ return pd;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+ struct device_node *dp_phy_node;
+ u32 phy_base;
+
+ dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy");
+ if (!dp_phy_node) {
+ dev_err(dp->dev, "could not find dptx-phy node\n");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
+ dev_err(dp->dev, "faild to get reg for dptx-phy\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
+ &dp->enable_mask)) {
+ dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n");
+ return -EINVAL;
+ }
+
+ dp->phy_addr = ioremap(phy_base, SZ_4);
+ if (!dp->phy_addr) {
+ dev_err(dp->dev, "failed to ioremap dp-phy\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+ u32 reg;
+
+ reg = __raw_readl(dp->phy_addr);
+ reg |= dp->enable_mask;
+ __raw_writel(reg, dp->phy_addr);
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+ u32 reg;
+
+ reg = __raw_readl(dp->phy_addr);
+ reg &= ~(dp->enable_mask);
+ __raw_writel(reg, dp->phy_addr);
+}
+#else
+static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+ return NULL;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+ return -EINVAL;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+ return;
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+ return;
+}
+#endif /* CONFIG_OF */
+
static int __devinit exynos_dp_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -864,12 +1004,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
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 +1013,22 @@ 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);
+
+ ret = exynos_dp_dt_parse_phydata(dp);
+ if (!ret)
+ return ret;
+ } else {
+ pdata = pdev->dev.platform_data;
+ 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,8 +1059,14 @@ 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->phy_addr)
+ exynos_dp_phy_init(dp);
+ } else {
+ if (pdata->phy_init)
+ pdata->phy_init();
+ }
exynos_dp_init_dp(dp);
@@ -953,8 +1109,13 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
- if (pdata && pdata->phy_exit)
- pdata->phy_exit();
+ if (pdev->dev.of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_exit(dp);
+ } else {
+ if (pdata->phy_exit)
+ pdata->phy_exit();
+ }
clk_disable_unprepare(dp->clock);
@@ -968,8 +1129,13 @@ static int exynos_dp_suspend(struct device *dev)
struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
- if (pdata && pdata->phy_exit)
- pdata->phy_exit();
+ if (dev->of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_exit(dp);
+ } else {
+ if (pdata->phy_exit)
+ pdata->phy_exit();
+ }
clk_disable_unprepare(dp->clock);
@@ -982,8 +1148,13 @@ static int exynos_dp_resume(struct device *dev)
struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
- if (pdata && pdata->phy_init)
- pdata->phy_init();
+ if (dev->of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_init(dp);
+ } else {
+ if (pdata->phy_init)
+ pdata->phy_init();
+ }
clk_prepare_enable(dp->clock);
@@ -1013,6 +1184,12 @@ static const struct dev_pm_ops exynos_dp_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
};
+static const struct of_device_id exynos_dp_match[] = {
+ { .compatible = "samsung,exynos5-dp" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_match);
+
static struct platform_driver exynos_dp_driver = {
.probe = exynos_dp_probe,
.remove = __devexit_p(exynos_dp_remove),
@@ -1020,6 +1197,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..6dbeeb2 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 *phy_addr;
+ unsigned int enable_mask;
struct video_info *video_info;
struct link_train link_train;
--
1.7.1
^ permalink raw reply related
* [PATCH V6 2/2] video: exynos_dp: device tree documentation
From: Jingoo Han @ 2012-10-15 9:13 UTC (permalink / raw)
To: 'Florian Tobias Schandinat'
Cc: linux-fbdev, linux-samsung-soc, devicetree-discuss,
'Ajay Kumar', 'Sylwester Nawrocki',
'Tomasz Figa', 'Thomas Abraham',
'Jingoo Han'
In-Reply-To: <009e01cdaab5$25cff2c0$716fd840$%han@samsung.com>
From: Ajay Kumar <ajaykumar.rs@samsung.com>
Add documentation for the DT bindings in exynos display port driver.
Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
Changes since v6:
- Remove duplicated 'based on'
.../devicetree/bindings/video/exynos_dp.txt | 80 ++++++++++++++++++++
1 files changed, 80 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/video/exynos_dp.txt
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt
new file mode 100644
index 0000000..7cc7d9f
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/exynos_dp.txt
@@ -0,0 +1,80 @@
+The Exynos display port interface should be configured based on
+the type of panel connected to it.
+
+We use two nodes:
+ -display-port-controller node
+ -dptx-phy node(defined inside display-port-controller node)
+
+For the DP-PHY initialization, we use the dptx-phy node.
+Required properties for dptx-phy:
+ -reg:
+ Base address of DP PHY register.
+ -samsung,enable-mask:
+ The bit-mask used to enable/disable DP PHY.
+
+For the Panel initialization, we read data from display-port-controller node.
+Required properties for display-port-controller:
+ -compatible:
+ should be "samsung,exynos5-dp".
+ -reg:
+ physical base address of the controller and length
+ of memory mapped region.
+ -interrupts:
+ interrupt combiner values.
+ -interrupt-parent:
+ phandle to Interrupt combiner node.
+ -samsung,color-space:
+ input video data format.
+ COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
+ -samsung,dynamic-range:
+ dynamic range for input video data.
+ VESA = 0, CEA = 1
+ -samsung,ycbcr-coeff:
+ YCbCr co-efficients for input video.
+ COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
+ -samsung,color-depth:
+ number of bits per colour component.
+ COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
+ -samsung,link-rate:
+ link rate supported by the panel.
+ LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
+ -samsung,lane-count:
+ number of lanes supported by the panel.
+ LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
+
+Optional properties for display-port-controller:
+ -interlaced:
+ interlace scan mode.
+ Progressive if defined, Interlaced if not defined
+ -vsync-active-high:
+ VSYNC polarity configuration.
+ High if defined, Low if not defined
+ -hsync-active-high:
+ HSYNC polarity configuration.
+ High if defined, Low if not defined
+
+Example:
+
+SOC specific portion:
+ display-port-controller {
+ compatible = "samsung,exynos5-dp";
+ reg = <0x145b0000 0x10000>;
+ interrupts = <10 3>;
+ interrupt-parent = <&combiner>;
+
+ dptx-phy {
+ reg = <0x10040720>;
+ samsung,enable-mask = <1>;
+ };
+
+ };
+
+Board Specific portion:
+ display-port-controller {
+ samsung,color-space = <0>;
+ samsung,dynamic-range = <0>;
+ samsung,ycbcr-coeff = <0>;
+ samsung,color-depth = <1>;
+ samsung,link-rate = <0x0a>;
+ samsung,lane-count = <4>;
+ };
--
1.7.1
^ permalink raw reply related
* RE: [PATCH V6 1/2] video: exynos_dp: Add device tree support to DP driver
From: Jingoo Han @ 2012-10-15 9:44 UTC (permalink / raw)
To: 'Florian Tobias Schandinat'
Cc: linux-fbdev, linux-samsung-soc, devicetree-discuss,
'Ajay Kumar', 'Sylwester Nawrocki',
'Tomasz Figa', 'Thomas Abraham',
'Jingoo Han'
In-Reply-To: <009e01cdaab5$25cff2c0$716fd840$%han@samsung.com>
On Monday, October 15, 2012 6:12 PM Jingoo Han wrote
>
> From: Ajay Kumar <ajaykumar.rs@samsung.com>
>
> 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.
>
> Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
> Signed-off-by: Jingoo Han <jg1.han@samsung.com>
> ---
> This patch is tested with Exynos5250.
>
> Changes since v6:
> - Check return values of required properties
> - Replace dp_phy_addr with phy_addr
> - Remove unnecessary NULL deference checking for 'pdata'
> - Remove unncessary 'virt_phy_base' variable
> - Make functions static
> - Fix build errors when CONFIG_OF option is diabled
> - Add return values to exynos_dp_dt_parse_phydata()
>
> drivers/video/exynos/exynos_dp_core.c | 206 ++++++++++++++++++++++++++++++---
> drivers/video/exynos/exynos_dp_core.h | 2 +
> 2 files changed, 194 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
> index d55470e..0d9c0ee 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,6 +857,145 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
> return IRQ_HANDLED;
> }
>
> +#ifdef CONFIG_OF
> +static 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;
> +
> + dp_video_config->h_sync_polarity > + of_property_read_bool(dp_node, "hsync-active-high");
> +
> + dp_video_config->v_sync_polarity > + of_property_read_bool(dp_node, "vsync-active-high");
> +
> + dp_video_config->interlaced > + of_property_read_bool(dp_node, "interlaced");
> +
> + if (of_property_read_u32(dp_node, "samsung,color-space",
> + &dp_video_config->color_space)) {
> + dev_err(dev, "failed to get color-space\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + if (of_property_read_u32(dp_node, "samsung,dynamic-range",
> + &dp_video_config->dynamic_range)) {
> + dev_err(dev, "failed to get dynamic-range\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
> + &dp_video_config->ycbcr_coeff)) {
> + dev_err(dev, "failed to get ycbcr-coeff\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + if (of_property_read_u32(dp_node, "samsung,color-depth",
> + &dp_video_config->color_depth)) {
> + dev_err(dev, "failed to get color-depth\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + if (of_property_read_u32(dp_node, "samsung,link-rate",
> + &dp_video_config->link_rate)) {
> + dev_err(dev, "failed to get link-rate\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + if (of_property_read_u32(dp_node, "samsung,lane-count",
> + &dp_video_config->lane_count)) {
> + dev_err(dev, "failed to get lane-count\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + return pd;
> +}
> +
> +static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
> +{
> + struct device_node *dp_phy_node;
> + u32 phy_base;
> +
> + dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy");
> + if (!dp_phy_node) {
> + dev_err(dp->dev, "could not find dptx-phy node\n");
> + return -ENODEV;
> + }
> +
> + if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
> + dev_err(dp->dev, "faild to get reg for dptx-phy\n");
> + return -EINVAL;
> + }
> +
> + if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
> + &dp->enable_mask)) {
> + dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n");
> + return -EINVAL;
> + }
> +
> + dp->phy_addr = ioremap(phy_base, SZ_4);
> + if (!dp->phy_addr) {
> + dev_err(dp->dev, "failed to ioremap dp-phy\n");
> + return -ENOMEM;
> + }
> +
> + return 0;
> +}
> +
> +static void exynos_dp_phy_init(struct exynos_dp_device *dp)
> +{
> + u32 reg;
> +
> + reg = __raw_readl(dp->phy_addr);
> + reg |= dp->enable_mask;
> + __raw_writel(reg, dp->phy_addr);
> +}
> +
> +static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
> +{
> + u32 reg;
> +
> + reg = __raw_readl(dp->phy_addr);
> + reg &= ~(dp->enable_mask);
> + __raw_writel(reg, dp->phy_addr);
> +}
> +#else
> +static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
> +{
> + return NULL;
> +}
> +
> +static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
> +{
> + return -EINVAL;
> +}
> +
> +static void exynos_dp_phy_init(struct exynos_dp_device *dp)
> +{
> + return;
> +}
> +
> +static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
> +{
> + return;
> +}
> +#endif /* CONFIG_OF */
> +
> static int __devinit exynos_dp_probe(struct platform_device *pdev)
> {
> struct resource *res;
> @@ -864,12 +1004,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
>
> 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 +1013,22 @@ 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);
> +
> + ret = exynos_dp_dt_parse_phydata(dp);
> + if (!ret)
It should be 'if (ret)' instead of 'if (!ret)'.
It is my fault. I will send v7 patch, soon.
Sorry.
> + return ret;
> + } else {
> + pdata = pdev->dev.platform_data;
> + 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,8 +1059,14 @@ 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->phy_addr)
> + exynos_dp_phy_init(dp);
> + } else {
> + if (pdata->phy_init)
> + pdata->phy_init();
> + }
>
> exynos_dp_init_dp(dp);
>
> @@ -953,8 +1109,13 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
> struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> struct exynos_dp_device *dp = platform_get_drvdata(pdev);
>
> - if (pdata && pdata->phy_exit)
> - pdata->phy_exit();
> + if (pdev->dev.of_node) {
> + if (dp->phy_addr)
> + exynos_dp_phy_exit(dp);
> + } else {
> + if (pdata->phy_exit)
> + pdata->phy_exit();
> + }
>
> clk_disable_unprepare(dp->clock);
>
> @@ -968,8 +1129,13 @@ static int exynos_dp_suspend(struct device *dev)
> struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> struct exynos_dp_device *dp = platform_get_drvdata(pdev);
>
> - if (pdata && pdata->phy_exit)
> - pdata->phy_exit();
> + if (dev->of_node) {
> + if (dp->phy_addr)
> + exynos_dp_phy_exit(dp);
> + } else {
> + if (pdata->phy_exit)
> + pdata->phy_exit();
> + }
>
> clk_disable_unprepare(dp->clock);
>
> @@ -982,8 +1148,13 @@ static int exynos_dp_resume(struct device *dev)
> struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> struct exynos_dp_device *dp = platform_get_drvdata(pdev);
>
> - if (pdata && pdata->phy_init)
> - pdata->phy_init();
> + if (dev->of_node) {
> + if (dp->phy_addr)
> + exynos_dp_phy_init(dp);
> + } else {
> + if (pdata->phy_init)
> + pdata->phy_init();
> + }
>
> clk_prepare_enable(dp->clock);
>
> @@ -1013,6 +1184,12 @@ static const struct dev_pm_ops exynos_dp_pm_ops = {
> SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
> };
>
> +static const struct of_device_id exynos_dp_match[] = {
> + { .compatible = "samsung,exynos5-dp" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, exynos_dp_match);
> +
> static struct platform_driver exynos_dp_driver = {
> .probe = exynos_dp_probe,
> .remove = __devexit_p(exynos_dp_remove),
> @@ -1020,6 +1197,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..6dbeeb2 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 *phy_addr;
> + unsigned int enable_mask;
>
> struct video_info *video_info;
> struct link_train link_train;
> --
> 1.7.1
^ permalink raw reply
* [PATCH V7 1/2] video: exynos_dp: Add device tree support to DP driver
From: Jingoo Han @ 2012-10-15 9:56 UTC (permalink / raw)
To: 'Florian Tobias Schandinat'
Cc: linux-fbdev, linux-samsung-soc, devicetree-discuss,
'Ajay Kumar', 'Sylwester Nawrocki',
'Tomasz Figa', 'Thomas Abraham',
'Jingoo Han'
From: Ajay Kumar <ajaykumar.rs@samsung.com>
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.
Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
This patch is tested with Exynos5250.
Changes since v6:
- Fix return check for exynos_dp_dt_parse_phydata() in exynos_dp_probe()
drivers/video/exynos/exynos_dp_core.c | 206 ++++++++++++++++++++++++++++++---
drivers/video/exynos/exynos_dp_core.h | 2 +
2 files changed, 194 insertions(+), 14 deletions(-)
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index d55470e..0d9c0ee 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,6 +857,145 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
return IRQ_HANDLED;
}
+#ifdef CONFIG_OF
+static 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;
+
+ dp_video_config->h_sync_polarity + of_property_read_bool(dp_node, "hsync-active-high");
+
+ dp_video_config->v_sync_polarity + of_property_read_bool(dp_node, "vsync-active-high");
+
+ dp_video_config->interlaced + of_property_read_bool(dp_node, "interlaced");
+
+ if (of_property_read_u32(dp_node, "samsung,color-space",
+ &dp_video_config->color_space)) {
+ dev_err(dev, "failed to get color-space\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,dynamic-range",
+ &dp_video_config->dynamic_range)) {
+ dev_err(dev, "failed to get dynamic-range\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
+ &dp_video_config->ycbcr_coeff)) {
+ dev_err(dev, "failed to get ycbcr-coeff\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,color-depth",
+ &dp_video_config->color_depth)) {
+ dev_err(dev, "failed to get color-depth\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,link-rate",
+ &dp_video_config->link_rate)) {
+ dev_err(dev, "failed to get link-rate\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,lane-count",
+ &dp_video_config->lane_count)) {
+ dev_err(dev, "failed to get lane-count\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ return pd;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+ struct device_node *dp_phy_node;
+ u32 phy_base;
+
+ dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy");
+ if (!dp_phy_node) {
+ dev_err(dp->dev, "could not find dptx-phy node\n");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
+ dev_err(dp->dev, "faild to get reg for dptx-phy\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
+ &dp->enable_mask)) {
+ dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n");
+ return -EINVAL;
+ }
+
+ dp->phy_addr = ioremap(phy_base, SZ_4);
+ if (!dp->phy_addr) {
+ dev_err(dp->dev, "failed to ioremap dp-phy\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+ u32 reg;
+
+ reg = __raw_readl(dp->phy_addr);
+ reg |= dp->enable_mask;
+ __raw_writel(reg, dp->phy_addr);
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+ u32 reg;
+
+ reg = __raw_readl(dp->phy_addr);
+ reg &= ~(dp->enable_mask);
+ __raw_writel(reg, dp->phy_addr);
+}
+#else
+static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+ return NULL;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+ return -EINVAL;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+ return;
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+ return;
+}
+#endif /* CONFIG_OF */
+
static int __devinit exynos_dp_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -864,12 +1004,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
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 +1013,22 @@ 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);
+
+ ret = exynos_dp_dt_parse_phydata(dp);
+ if (ret)
+ return ret;
+ } else {
+ pdata = pdev->dev.platform_data;
+ 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,8 +1059,14 @@ 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->phy_addr)
+ exynos_dp_phy_init(dp);
+ } else {
+ if (pdata->phy_init)
+ pdata->phy_init();
+ }
exynos_dp_init_dp(dp);
@@ -953,8 +1109,13 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
- if (pdata && pdata->phy_exit)
- pdata->phy_exit();
+ if (pdev->dev.of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_exit(dp);
+ } else {
+ if (pdata->phy_exit)
+ pdata->phy_exit();
+ }
clk_disable_unprepare(dp->clock);
@@ -968,8 +1129,13 @@ static int exynos_dp_suspend(struct device *dev)
struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
- if (pdata && pdata->phy_exit)
- pdata->phy_exit();
+ if (dev->of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_exit(dp);
+ } else {
+ if (pdata->phy_exit)
+ pdata->phy_exit();
+ }
clk_disable_unprepare(dp->clock);
@@ -982,8 +1148,13 @@ static int exynos_dp_resume(struct device *dev)
struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
- if (pdata && pdata->phy_init)
- pdata->phy_init();
+ if (dev->of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_init(dp);
+ } else {
+ if (pdata->phy_init)
+ pdata->phy_init();
+ }
clk_prepare_enable(dp->clock);
@@ -1013,6 +1184,12 @@ static const struct dev_pm_ops exynos_dp_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
};
+static const struct of_device_id exynos_dp_match[] = {
+ { .compatible = "samsung,exynos5-dp" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_match);
+
static struct platform_driver exynos_dp_driver = {
.probe = exynos_dp_probe,
.remove = __devexit_p(exynos_dp_remove),
@@ -1020,6 +1197,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..6dbeeb2 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 *phy_addr;
+ unsigned int enable_mask;
struct video_info *video_info;
struct link_train link_train;
--
1.7.1
^ permalink raw reply related
* [PATCH V7 2/2] video: exynos_dp: device tree documentation
From: Jingoo Han @ 2012-10-15 9:57 UTC (permalink / raw)
To: 'Florian Tobias Schandinat'
Cc: linux-fbdev, linux-samsung-soc, devicetree-discuss,
'Ajay Kumar', 'Sylwester Nawrocki',
'Tomasz Figa', 'Thomas Abraham',
'Jingoo Han'
In-Reply-To: <00a201cdaabb$5f6eb6f0$1e4c24d0$%han@samsung.com>
From: Ajay Kumar <ajaykumar.rs@samsung.com>
Add documentation for the DT bindings in exynos display port driver.
Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
No changes since v6:
.../devicetree/bindings/video/exynos_dp.txt | 80 ++++++++++++++++++++
1 files changed, 80 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/video/exynos_dp.txt
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt
new file mode 100644
index 0000000..7cc7d9f
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/exynos_dp.txt
@@ -0,0 +1,80 @@
+The Exynos display port interface should be configured based on
+the type of panel connected to it.
+
+We use two nodes:
+ -display-port-controller node
+ -dptx-phy node(defined inside display-port-controller node)
+
+For the DP-PHY initialization, we use the dptx-phy node.
+Required properties for dptx-phy:
+ -reg:
+ Base address of DP PHY register.
+ -samsung,enable-mask:
+ The bit-mask used to enable/disable DP PHY.
+
+For the Panel initialization, we read data from display-port-controller node.
+Required properties for display-port-controller:
+ -compatible:
+ should be "samsung,exynos5-dp".
+ -reg:
+ physical base address of the controller and length
+ of memory mapped region.
+ -interrupts:
+ interrupt combiner values.
+ -interrupt-parent:
+ phandle to Interrupt combiner node.
+ -samsung,color-space:
+ input video data format.
+ COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
+ -samsung,dynamic-range:
+ dynamic range for input video data.
+ VESA = 0, CEA = 1
+ -samsung,ycbcr-coeff:
+ YCbCr co-efficients for input video.
+ COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
+ -samsung,color-depth:
+ number of bits per colour component.
+ COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
+ -samsung,link-rate:
+ link rate supported by the panel.
+ LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
+ -samsung,lane-count:
+ number of lanes supported by the panel.
+ LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
+
+Optional properties for display-port-controller:
+ -interlaced:
+ interlace scan mode.
+ Progressive if defined, Interlaced if not defined
+ -vsync-active-high:
+ VSYNC polarity configuration.
+ High if defined, Low if not defined
+ -hsync-active-high:
+ HSYNC polarity configuration.
+ High if defined, Low if not defined
+
+Example:
+
+SOC specific portion:
+ display-port-controller {
+ compatible = "samsung,exynos5-dp";
+ reg = <0x145b0000 0x10000>;
+ interrupts = <10 3>;
+ interrupt-parent = <&combiner>;
+
+ dptx-phy {
+ reg = <0x10040720>;
+ samsung,enable-mask = <1>;
+ };
+
+ };
+
+Board Specific portion:
+ display-port-controller {
+ samsung,color-space = <0>;
+ samsung,dynamic-range = <0>;
+ samsung,ycbcr-coeff = <0>;
+ samsung,color-depth = <1>;
+ samsung,link-rate = <0x0a>;
+ samsung,lane-count = <4>;
+ };
--
1.7.1
^ permalink raw reply related
* Re: [PATCH 0/2 v6] of: add display helper
From: Leela Krishna Amudala @ 2012-10-15 10:55 UTC (permalink / raw)
To: Steffen Trumtrar
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Tomi Valkeinen,
Laurent Pinchart, linux-media-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1349373560-11128-1-git-send-email-s.trumtrar-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Hello Steffen,
To which version of the kernel we can expect this patch set to be merged into?
Because I'm waiting for this from long time to add DT support for my
display controller :)
Best Wishes,
Leela Krishna Amudala.
On Thu, Oct 4, 2012 at 11:29 PM, Steffen Trumtrar
<s.trumtrar@pengutronix.de> wrote:
>
> Hi!
>
> In accordance with Stepehn Warren, I downsized the binding.
> Now, just the display-timing is described, as I think, it is way easier to
> agree
> on those and have a complete binding.
>
> Regards,
> Steffen
>
> Steffen Trumtrar (2):
> of: add helper to parse display timings
> of: add generic videomode description
>
> .../devicetree/bindings/video/display-timings.txt | 222
> ++++++++++++++++++++
> drivers/of/Kconfig | 10 +
> drivers/of/Makefile | 2 +
> drivers/of/of_display_timings.c | 183
> ++++++++++++++++
> drivers/of/of_videomode.c | 212
> +++++++++++++++++++
> include/linux/of_display_timings.h | 85 ++++++++
> include/linux/of_videomode.h | 41 ++++
> 7 files changed, 755 insertions(+)
> create mode 100644
> Documentation/devicetree/bindings/video/display-timings.txt
> create mode 100644 drivers/of/of_display_timings.c
> create mode 100644 drivers/of/of_videomode.c
> create mode 100644 include/linux/of_display_timings.h
> create mode 100644 include/linux/of_videomode.h
>
> --
> 1.7.10.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
* Re: [PATCH 0/2 v6] of: add display helper
From: Steffen Trumtrar @ 2012-10-15 14:17 UTC (permalink / raw)
To: Leela Krishna Amudala
Cc: linux-fbdev, devicetree-discuss, dri-devel, Tomi Valkeinen,
Laurent Pinchart, linux-media
In-Reply-To: <CAL1wa8fP8LBCUBVJS1=dy3cyFe+bY-Gu2+wtJyuCrgbP93m3Wg@mail.gmail.com>
Hi Leela,
On Mon, Oct 15, 2012 at 04:24:43PM +0530, Leela Krishna Amudala wrote:
> Hello Steffen,
>
> To which version of the kernel we can expect this patch set to be merged into?
> Because I'm waiting for this from long time to add DT support for my
> display controller :)
>
I have no idea, sorry. It seems like we have almost settled with the binding
(clock-name needs to be changed), but I'm not responsible for any merging/inclusions
in the kernel.
Regards,
Steffen
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* Re: [PATCH V5 1/2] video: exynos_dp: Add device tree support to DP driver
From: Sylwester Nawrocki @ 2012-10-15 21:14 UTC (permalink / raw)
To: Jingoo Han
Cc: 'Ajay Kumar', linux-samsung-soc, linux-fbdev,
devicetree-discuss, FlorianSchandinat, tomasz.figa, thomas.ab
In-Reply-To: <009d01cdaaad$0fa33230$2ee99690$%han@samsung.com>
On 10/15/2012 10:14 AM, Jingoo Han wrote:
> On Saturday, October 13, 2012 6:44 AM Sylwester Nawrocki wrote
>>
>> On 10/12/2012 10:47 PM, Ajay Kumar 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.
>>>
>>> Signed-off-by: Ajay Kumar<ajaykumar.rs@samsung.com>
>>> Acked-by: Jingoo Han<jg1.han@samsung.com>
>>> ---
>>> drivers/video/exynos/exynos_dp_core.c | 161 ++++++++++++++++++++++++++++++---
>>> drivers/video/exynos/exynos_dp_core.h | 2 +
>>> 2 files changed, 149 insertions(+), 14 deletions(-)
...
>>> @@ -953,8 +1062,13 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
>>> struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
>>> struct exynos_dp_device *dp = platform_get_drvdata(pdev);
>>
>> This doesn't belong to your patch, but the above 2 lines could be written as:
>>
>> struct exynos_dp_device *dp = dev_get_drvdata(&pdev->dev);
>>
>> Same in functions exynos_dp_suspend() and exynos_dp_resume().
>
> No, above 2 lines cannot be reduced to 1 line, as you mentioned.
> This is because it makes build error.
Sorry, my bad. It looks fine in case of exynos_dp_remove().
But at exynos_dp_suspend/resume() there is something like:
static int exynos_dp_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
You need only pdata and dp there. I think that simpler form would
do as well:
struct exynos_dp_device *dp = dev_get_drvdata(dev);
struct exynos_dp_platdata *pdata = dev->platform_data;
Sorry, this is just a nitpicking.
BTW, shouldn't CONFIG_EXYNOS_VIDEO depend on ARCH_EXYNOS ?
--
Regards,
Sylwester
^ permalink raw reply
* Re: [PATCH V5 1/2] video: exynos_dp: Add device tree support to DP driver
From: Jingoo Han @ 2012-10-16 2:02 UTC (permalink / raw)
To: 'Sylwester Nawrocki'
Cc: 'Florian Tobias Schandinat', 'Ajay Kumar',
linux-samsung-soc, linux-fbdev, devicetree-discuss,
'Tomasz Figa', 'Thomas Abraham',
'Jingoo Han'
In-Reply-To: <507C7C9E.1030503@gmail.com>
On Tuesday, October 16, 2012 6:14 AM Sylwester Nawrocki wrote
>
> On 10/15/2012 10:14 AM, Jingoo Han wrote:
> > On Saturday, October 13, 2012 6:44 AM Sylwester Nawrocki wrote
> >>
> >> On 10/12/2012 10:47 PM, Ajay Kumar 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.
> >>>
> >>> Signed-off-by: Ajay Kumar<ajaykumar.rs@samsung.com>
> >>> Acked-by: Jingoo Han<jg1.han@samsung.com>
> >>> ---
> >>> drivers/video/exynos/exynos_dp_core.c | 161 ++++++++++++++++++++++++++++++---
> >>> drivers/video/exynos/exynos_dp_core.h | 2 +
> >>> 2 files changed, 149 insertions(+), 14 deletions(-)
> ...
> >>> @@ -953,8 +1062,13 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
> >>> struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> >>> struct exynos_dp_device *dp = platform_get_drvdata(pdev);
> >>
> >> This doesn't belong to your patch, but the above 2 lines could be written as:
> >>
> >> struct exynos_dp_device *dp = dev_get_drvdata(&pdev->dev);
> >>
> >> Same in functions exynos_dp_suspend() and exynos_dp_resume().
> >
> > No, above 2 lines cannot be reduced to 1 line, as you mentioned.
> > This is because it makes build error.
>
> Sorry, my bad. It looks fine in case of exynos_dp_remove().
>
> But at exynos_dp_suspend/resume() there is something like:
>
>
> static int exynos_dp_suspend(struct device *dev)
> {
> struct platform_device *pdev = to_platform_device(dev);
> struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
> struct exynos_dp_device *dp = platform_get_drvdata(pdev);
>
>
> You need only pdata and dp there. I think that simpler form would
> do as well:
>
> struct exynos_dp_device *dp = dev_get_drvdata(dev);
> struct exynos_dp_platdata *pdata = dev->platform_data;
OK, I see.
I will accept your suggestion, because it is helpful to reduce
lines. Then, I will send v8 patch, soon.
>
>
> Sorry, this is just a nitpicking.
>
> BTW, shouldn't CONFIG_EXYNOS_VIDEO depend on ARCH_EXYNOS ?
>
>
> --
> Regards,
> Sylwester
> --
> 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 V8 1/2] video: exynos_dp: Add device tree support to DP driver
From: Jingoo Han @ 2012-10-16 2:16 UTC (permalink / raw)
To: 'Florian Tobias Schandinat'
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA, 'Jingoo Han',
'Ajay Kumar', 'Sylwester Nawrocki',
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
From: Ajay Kumar <ajaykumar.rs@samsung.com>
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.
Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
This patch is tested with Exynos5250.
Changes since v7:
- Replace platform_get_drvdata() with dev_get_drvdata() in suspend/resume
drivers/video/exynos/exynos_dp_core.c | 216 ++++++++++++++++++++++++++++++---
drivers/video/exynos/exynos_dp_core.h | 2 +
2 files changed, 198 insertions(+), 20 deletions(-)
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index d55470e..9a9ecc1 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,6 +857,145 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
return IRQ_HANDLED;
}
+#ifdef CONFIG_OF
+static 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;
+
+ dp_video_config->h_sync_polarity + of_property_read_bool(dp_node, "hsync-active-high");
+
+ dp_video_config->v_sync_polarity + of_property_read_bool(dp_node, "vsync-active-high");
+
+ dp_video_config->interlaced + of_property_read_bool(dp_node, "interlaced");
+
+ if (of_property_read_u32(dp_node, "samsung,color-space",
+ &dp_video_config->color_space)) {
+ dev_err(dev, "failed to get color-space\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,dynamic-range",
+ &dp_video_config->dynamic_range)) {
+ dev_err(dev, "failed to get dynamic-range\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
+ &dp_video_config->ycbcr_coeff)) {
+ dev_err(dev, "failed to get ycbcr-coeff\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,color-depth",
+ &dp_video_config->color_depth)) {
+ dev_err(dev, "failed to get color-depth\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,link-rate",
+ &dp_video_config->link_rate)) {
+ dev_err(dev, "failed to get link-rate\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,lane-count",
+ &dp_video_config->lane_count)) {
+ dev_err(dev, "failed to get lane-count\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ return pd;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+ struct device_node *dp_phy_node;
+ u32 phy_base;
+
+ dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy");
+ if (!dp_phy_node) {
+ dev_err(dp->dev, "could not find dptx-phy node\n");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
+ dev_err(dp->dev, "faild to get reg for dptx-phy\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
+ &dp->enable_mask)) {
+ dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n");
+ return -EINVAL;
+ }
+
+ dp->phy_addr = ioremap(phy_base, SZ_4);
+ if (!dp->phy_addr) {
+ dev_err(dp->dev, "failed to ioremap dp-phy\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+ u32 reg;
+
+ reg = __raw_readl(dp->phy_addr);
+ reg |= dp->enable_mask;
+ __raw_writel(reg, dp->phy_addr);
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+ u32 reg;
+
+ reg = __raw_readl(dp->phy_addr);
+ reg &= ~(dp->enable_mask);
+ __raw_writel(reg, dp->phy_addr);
+}
+#else
+static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+ return NULL;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+ return -EINVAL;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+ return;
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+ return;
+}
+#endif /* CONFIG_OF */
+
static int __devinit exynos_dp_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -864,12 +1004,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
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 +1013,22 @@ 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);
+
+ ret = exynos_dp_dt_parse_phydata(dp);
+ if (ret)
+ return ret;
+ } else {
+ pdata = pdev->dev.platform_data;
+ 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,8 +1059,14 @@ 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->phy_addr)
+ exynos_dp_phy_init(dp);
+ } else {
+ if (pdata->phy_init)
+ pdata->phy_init();
+ }
exynos_dp_init_dp(dp);
@@ -953,8 +1109,13 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
- if (pdata && pdata->phy_exit)
- pdata->phy_exit();
+ if (pdev->dev.of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_exit(dp);
+ } else {
+ if (pdata->phy_exit)
+ pdata->phy_exit();
+ }
clk_disable_unprepare(dp->clock);
@@ -964,12 +1125,16 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int exynos_dp_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
- struct exynos_dp_device *dp = platform_get_drvdata(pdev);
+ struct exynos_dp_platdata *pdata = dev->platform_data;
+ struct exynos_dp_device *dp = dev_get_drvdata(dev);
- if (pdata && pdata->phy_exit)
- pdata->phy_exit();
+ if (dev->of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_exit(dp);
+ } else {
+ if (pdata->phy_exit)
+ pdata->phy_exit();
+ }
clk_disable_unprepare(dp->clock);
@@ -978,12 +1143,16 @@ static int exynos_dp_suspend(struct device *dev)
static int exynos_dp_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
- struct exynos_dp_device *dp = platform_get_drvdata(pdev);
+ struct exynos_dp_platdata *pdata = dev->platform_data;
+ struct exynos_dp_device *dp = dev_get_drvdata(dev);
- if (pdata && pdata->phy_init)
- pdata->phy_init();
+ if (dev->of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_init(dp);
+ } else {
+ if (pdata->phy_init)
+ pdata->phy_init();
+ }
clk_prepare_enable(dp->clock);
@@ -1013,6 +1182,12 @@ static const struct dev_pm_ops exynos_dp_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
};
+static const struct of_device_id exynos_dp_match[] = {
+ { .compatible = "samsung,exynos5-dp" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_match);
+
static struct platform_driver exynos_dp_driver = {
.probe = exynos_dp_probe,
.remove = __devexit_p(exynos_dp_remove),
@@ -1020,6 +1195,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..6dbeeb2 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 *phy_addr;
+ unsigned int enable_mask;
struct video_info *video_info;
struct link_train link_train;
--
1.7.1
^ permalink raw reply related
* [PATCH V8 2/2] video: exynos_dp: device tree documentation
From: Jingoo Han @ 2012-10-16 2:17 UTC (permalink / raw)
To: 'Florian Tobias Schandinat'
Cc: linux-fbdev, linux-samsung-soc, devicetree-discuss,
'Ajay Kumar', 'Sylwester Nawrocki',
'Tomasz Figa', 'Thomas Abraham',
'Jingoo Han'
From: Ajay Kumar <ajaykumar.rs@samsung.com>
Add documentation for the DT bindings in exynos display port driver.
Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
No changes since v7:
.../devicetree/bindings/video/exynos_dp.txt | 80 ++++++++++++++++++++
1 files changed, 80 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/video/exynos_dp.txt
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt
new file mode 100644
index 0000000..7cc7d9f
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/exynos_dp.txt
@@ -0,0 +1,80 @@
+The Exynos display port interface should be configured based on
+the type of panel connected to it.
+
+We use two nodes:
+ -display-port-controller node
+ -dptx-phy node(defined inside display-port-controller node)
+
+For the DP-PHY initialization, we use the dptx-phy node.
+Required properties for dptx-phy:
+ -reg:
+ Base address of DP PHY register.
+ -samsung,enable-mask:
+ The bit-mask used to enable/disable DP PHY.
+
+For the Panel initialization, we read data from display-port-controller node.
+Required properties for display-port-controller:
+ -compatible:
+ should be "samsung,exynos5-dp".
+ -reg:
+ physical base address of the controller and length
+ of memory mapped region.
+ -interrupts:
+ interrupt combiner values.
+ -interrupt-parent:
+ phandle to Interrupt combiner node.
+ -samsung,color-space:
+ input video data format.
+ COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
+ -samsung,dynamic-range:
+ dynamic range for input video data.
+ VESA = 0, CEA = 1
+ -samsung,ycbcr-coeff:
+ YCbCr co-efficients for input video.
+ COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
+ -samsung,color-depth:
+ number of bits per colour component.
+ COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
+ -samsung,link-rate:
+ link rate supported by the panel.
+ LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
+ -samsung,lane-count:
+ number of lanes supported by the panel.
+ LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
+
+Optional properties for display-port-controller:
+ -interlaced:
+ interlace scan mode.
+ Progressive if defined, Interlaced if not defined
+ -vsync-active-high:
+ VSYNC polarity configuration.
+ High if defined, Low if not defined
+ -hsync-active-high:
+ HSYNC polarity configuration.
+ High if defined, Low if not defined
+
+Example:
+
+SOC specific portion:
+ display-port-controller {
+ compatible = "samsung,exynos5-dp";
+ reg = <0x145b0000 0x10000>;
+ interrupts = <10 3>;
+ interrupt-parent = <&combiner>;
+
+ dptx-phy {
+ reg = <0x10040720>;
+ samsung,enable-mask = <1>;
+ };
+
+ };
+
+Board Specific portion:
+ display-port-controller {
+ samsung,color-space = <0>;
+ samsung,dynamic-range = <0>;
+ samsung,ycbcr-coeff = <0>;
+ samsung,color-depth = <1>;
+ samsung,link-rate = <0x0a>;
+ samsung,lane-count = <4>;
+ };
--
1.7.1
^ permalink raw reply related
* [PATCH v2 0/2] da8xx-fb: LCDC driver cleanup
From: Manjunathappa, Prakash @ 2012-10-16 5:05 UTC (permalink / raw)
To: linux-fbdev
This patch series clean up driver as it is necessary for DT migration.
Manjunathappa, Prakash (2):
da8xx-fb: adopt fb_videomode data for panel information
da8xx-fb: cleanup LCDC configurations
arch/arm/mach-davinci/devices-da8xx.c | 22 +----
drivers/video/da8xx-fb.c | 167 +++++++++++++++------------------
include/video/da8xx-fb.h | 25 +----
3 files changed, 79 insertions(+), 135 deletions(-)
^ permalink raw reply
* [PATCH v2 1/2] da8xx-fb: adopt fb_videomode data for panel information
From: Manjunathappa, Prakash @ 2012-10-16 5:05 UTC (permalink / raw)
To: linux-fbdev
Adopt fb_videomode data instead of defining driver private
structure to hold panel information. This is the way standard FB
drivers maintain the panel information.
Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
---
Since v1:
Do not move panel information out of driver, adopt only fb_videomode data.
drivers/video/da8xx-fb.c | 130 +++++++++++++++++++++-------------------------
include/video/da8xx-fb.h | 3 +
2 files changed, 63 insertions(+), 70 deletions(-)
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 65a11ef..90cf33a 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -213,62 +213,50 @@ static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = {
.accel = FB_ACCEL_NONE
};
-struct da8xx_panel {
- const char name[25]; /* Full name <vendor>_<model> */
- unsigned short width;
- unsigned short height;
- int hfp; /* Horizontal front porch */
- int hbp; /* Horizontal back porch */
- int hsw; /* Horizontal Sync Pulse Width */
- int vfp; /* Vertical front porch */
- int vbp; /* Vertical back porch */
- int vsw; /* Vertical Sync Pulse Width */
- unsigned int pxl_clk; /* Pixel clock */
- unsigned char invert_pxl_clk; /* Invert Pixel clock */
-};
-
-static struct da8xx_panel known_lcd_panels[] = {
+static struct fb_videomode known_lcd_panels[] = {
/* Sharp LCD035Q3DG01 */
[0] = {
- .name = "Sharp_LCD035Q3DG01",
- .width = 320,
- .height = 240,
- .hfp = 8,
- .hbp = 6,
- .hsw = 0,
- .vfp = 2,
- .vbp = 2,
- .vsw = 0,
- .pxl_clk = 4608000,
- .invert_pxl_clk = 1,
+ .name = "Sharp_LCD035Q3DG01",
+ .xres = 320,
+ .yres = 240,
+ .pixclock = 4608000,
+ .left_margin = 6,
+ .right_margin = 8,
+ .upper_margin = 2,
+ .lower_margin = 2,
+ .hsync_len = 0,
+ .vsync_len = 0,
+ .sync = FB_SYNC_CLK_INVERT,
},
/* Sharp LK043T1DG01 */
[1] = {
- .name = "Sharp_LK043T1DG01",
- .width = 480,
- .height = 272,
- .hfp = 2,
- .hbp = 2,
- .hsw = 41,
- .vfp = 2,
- .vbp = 2,
- .vsw = 10,
- .pxl_clk = 7833600,
- .invert_pxl_clk = 0,
+ .name = "Sharp_LK043T1DG01",
+ .xres = 480,
+ .yres = 272,
+ .pixclock = 7833600,
+ .left_margin = 2,
+ .right_margin = 2,
+ .upper_margin = 2,
+ .lower_margin = 2,
+ .hsync_len = 41,
+ .vsync_len = 10,
+ .sync = 0,
+ .flag = 0,
},
[2] = {
/* Hitachi SP10Q010 */
- .name = "SP10Q010",
- .width = 320,
- .height = 240,
- .hfp = 10,
- .hbp = 10,
- .hsw = 10,
- .vfp = 10,
- .vbp = 10,
- .vsw = 10,
- .pxl_clk = 7833600,
- .invert_pxl_clk = 0,
+ .name = "SP10Q010",
+ .xres = 320,
+ .yres = 240,
+ .pixclock = 7833600,
+ .left_margin = 10,
+ .right_margin = 10,
+ .upper_margin = 10,
+ .lower_margin = 10,
+ .hsync_len = 10,
+ .vsync_len = 10,
+ .sync = 0,
+ .flag = 0,
},
};
@@ -728,7 +716,7 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
}
static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
- struct da8xx_panel *panel)
+ struct fb_videomode *panel)
{
u32 bpp;
int ret = 0;
@@ -738,7 +726,7 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
/* Calculate the divider */
lcd_calc_clk_divider(par);
- if (panel->invert_pxl_clk)
+ if (panel->sync & FB_SYNC_CLK_INVERT)
lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
else
@@ -754,8 +742,10 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
/* Configure the vertical and horizontal sync properties. */
- lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp);
- lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp);
+ lcd_cfg_vertical_sync(panel->lower_margin, panel->vsync_len,
+ panel->upper_margin);
+ lcd_cfg_horizontal_sync(panel->right_margin, panel->hsync_len,
+ panel->left_margin);
/* Configure for disply */
ret = lcd_cfg_display(cfg);
@@ -772,8 +762,8 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
bpp = cfg->p_disp_panel->max_bpp;
if (bpp = 12)
bpp = 16;
- ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width,
- (unsigned int)panel->height, bpp,
+ ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->xres,
+ (unsigned int)panel->yres, bpp,
cfg->raster_order);
if (ret < 0)
return ret;
@@ -1235,7 +1225,7 @@ static int __devinit fb_probe(struct platform_device *device)
struct da8xx_lcdc_platform_data *fb_pdata device->dev.platform_data;
struct lcd_ctrl_config *lcd_cfg;
- struct da8xx_panel *lcdc_info;
+ struct fb_videomode *lcdc_info;
struct fb_info *da8xx_fb_info;
struct clk *fb_clk = NULL;
struct da8xx_fb_par *par;
@@ -1323,7 +1313,7 @@ static int __devinit fb_probe(struct platform_device *device)
#ifdef CONFIG_CPU_FREQ
par->lcd_fck_rate = clk_get_rate(fb_clk);
#endif
- par->pxl_clk = lcdc_info->pxl_clk;
+ par->pxl_clk = lcdc_info->pixclock;
if (fb_pdata->panel_power_ctrl) {
par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
par->panel_power_ctrl(1);
@@ -1336,8 +1326,8 @@ static int __devinit fb_probe(struct platform_device *device)
}
/* allocate frame buffer */
- par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp;
- ulcm = lcm((lcdc_info->width * lcd_cfg->bpp)/8, PAGE_SIZE);
+ par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
+ ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
par->vram_size = roundup(par->vram_size/8, ulcm);
par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
@@ -1355,10 +1345,10 @@ static int __devinit fb_probe(struct platform_device *device)
da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;
da8xx_fb_fix.smem_start = par->vram_phys;
da8xx_fb_fix.smem_len = par->vram_size;
- da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8;
+ da8xx_fb_fix.line_length = (lcdc_info->xres * lcd_cfg->bpp) / 8;
par->dma_start = par->vram_phys;
- par->dma_end = par->dma_start + lcdc_info->height *
+ par->dma_end = par->dma_start + lcdc_info->yres *
da8xx_fb_fix.line_length - 1;
/* allocate palette buffer */
@@ -1384,22 +1374,22 @@ static int __devinit fb_probe(struct platform_device *device)
/* Initialize par */
da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
- da8xx_fb_var.xres = lcdc_info->width;
- da8xx_fb_var.xres_virtual = lcdc_info->width;
+ da8xx_fb_var.xres = lcdc_info->xres;
+ da8xx_fb_var.xres_virtual = lcdc_info->xres;
- da8xx_fb_var.yres = lcdc_info->height;
- da8xx_fb_var.yres_virtual = lcdc_info->height * LCD_NUM_BUFFERS;
+ da8xx_fb_var.yres = lcdc_info->yres;
+ da8xx_fb_var.yres_virtual = lcdc_info->yres * LCD_NUM_BUFFERS;
da8xx_fb_var.grayscale lcd_cfg->p_disp_panel->panel_shade = MONOCHROME ? 1 : 0;
da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
- da8xx_fb_var.hsync_len = lcdc_info->hsw;
- da8xx_fb_var.vsync_len = lcdc_info->vsw;
- da8xx_fb_var.right_margin = lcdc_info->hfp;
- da8xx_fb_var.left_margin = lcdc_info->hbp;
- da8xx_fb_var.lower_margin = lcdc_info->vfp;
- da8xx_fb_var.upper_margin = lcdc_info->vbp;
+ da8xx_fb_var.hsync_len = lcdc_info->hsync_len;
+ da8xx_fb_var.vsync_len = lcdc_info->vsync_len;
+ da8xx_fb_var.right_margin = lcdc_info->right_margin;
+ da8xx_fb_var.left_margin = lcdc_info->left_margin;
+ da8xx_fb_var.lower_margin = lcdc_info->lower_margin;
+ da8xx_fb_var.upper_margin = lcdc_info->upper_margin;
da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
/* Initialize fbinfo */
diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h
index 5a0e4f9..12e4e1d 100644
--- a/include/video/da8xx-fb.h
+++ b/include/video/da8xx-fb.h
@@ -103,5 +103,8 @@ struct lcd_sync_arg {
#define FBIPUT_HSYNC _IOW('F', 9, int)
#define FBIPUT_VSYNC _IOW('F', 10, int)
+/* Proprietary FB_SYNC_ flags */
+#define FB_SYNC_CLK_INVERT 0x40000000
+
#endif /* ifndef DA8XX_FB_H */
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2 2/2] da8xx-fb: cleanup LCDC configurations
From: Manjunathappa, Prakash @ 2012-10-16 5:05 UTC (permalink / raw)
To: linux-fbdev
Configure below LCDC configurations to optimal values, also have an
option configure these optional parameters for platform.
1) AC bias configuration: Required only for passive panels
2) Dma_burst_size:
3) FIFO_DMA_DELAY:
4) FIFO threshold: Does not apply for da830 LCDC.
Patch is verified for 16bpp and 24bpp configurations on da830, da850 and
am335x EVMs.
Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
---
Since v1:
One of the patch in the series has changed, no change in this patch.
arch/arm/mach-davinci/devices-da8xx.c | 22 +----------------
drivers/video/da8xx-fb.c | 43 +++++++++++++--------------------
include/video/da8xx-fb.h | 22 +----------------
3 files changed, 19 insertions(+), 68 deletions(-)
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 783eab6..a61860a 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -524,29 +524,9 @@ void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata)
}
}
-static const struct display_panel disp_panel = {
- QVGA,
- 16,
- 16,
- COLOR_ACTIVE,
-};
-
static struct lcd_ctrl_config lcd_cfg = {
- &disp_panel,
- .ac_bias = 255,
- .ac_bias_intrpt = 0,
- .dma_burst_sz = 16,
+ .panel_shade = COLOR_ACTIVE,
.bpp = 16,
- .fdd = 255,
- .tft_alt_mode = 0,
- .stn_565_mode = 0,
- .mono_8bit_mode = 0,
- .invert_line_clock = 1,
- .invert_frm_clock = 1,
- .sync_edge = 0,
- .sync_ctrl = 1,
- .raster_order = 0,
- .fifo_th = 6,
};
struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata = {
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 90cf33a..f0f21c8 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -226,7 +226,8 @@ static struct fb_videomode known_lcd_panels[] = {
.lower_margin = 2,
.hsync_len = 0,
.vsync_len = 0,
- .sync = FB_SYNC_CLK_INVERT,
+ .sync = FB_SYNC_CLK_INVERT |
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
},
/* Sharp LK043T1DG01 */
[1] = {
@@ -240,7 +241,7 @@ static struct fb_videomode known_lcd_panels[] = {
.lower_margin = 2,
.hsync_len = 41,
.vsync_len = 10,
- .sync = 0,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.flag = 0,
},
[2] = {
@@ -255,7 +256,7 @@ static struct fb_videomode known_lcd_panels[] = {
.lower_margin = 10,
.hsync_len = 10,
.vsync_len = 10,
- .sync = 0,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.flag = 0,
},
};
@@ -387,10 +388,9 @@ static int lcd_cfg_dma(int burst_size, int fifo_th)
reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
break;
case 16:
+ default:
reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
break;
- default:
- return -EINVAL;
}
reg |= (fifo_th << 8);
@@ -435,7 +435,8 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
}
-static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
+static int lcd_cfg_display(const struct lcd_ctrl_config *cfg,
+ struct fb_videomode *panel)
{
u32 reg;
u32 reg_int;
@@ -444,7 +445,7 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
LCD_MONO_8BIT_MODE |
LCD_MONOCHROME_MODE);
- switch (cfg->p_disp_panel->panel_shade) {
+ switch (cfg->panel_shade) {
case MONOCHROME:
reg |= LCD_MONOCHROME_MODE;
if (cfg->mono_8bit_mode)
@@ -457,7 +458,9 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
break;
case COLOR_PASSIVE:
- if (cfg->stn_565_mode)
+ /* AC bias applicable only for Pasive panels */
+ lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
+ if (cfg->bpp = 12 && cfg->stn_565_mode)
reg |= LCD_STN_565_ENABLE;
break;
@@ -478,22 +481,19 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
- if (cfg->sync_ctrl)
- reg |= LCD_SYNC_CTRL;
- else
- reg &= ~LCD_SYNC_CTRL;
+ reg |= LCD_SYNC_CTRL;
if (cfg->sync_edge)
reg |= LCD_SYNC_EDGE;
else
reg &= ~LCD_SYNC_EDGE;
- if (cfg->invert_line_clock)
+ if (panel->sync & FB_SYNC_HOR_HIGH_ACT)
reg |= LCD_INVERT_LINE_CLOCK;
else
reg &= ~LCD_INVERT_LINE_CLOCK;
- if (cfg->invert_frm_clock)
+ if (panel->sync & FB_SYNC_VERT_HIGH_ACT)
reg |= LCD_INVERT_FRAME_CLOCK;
else
reg &= ~LCD_INVERT_FRAME_CLOCK;
@@ -738,9 +738,6 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
if (ret < 0)
return ret;
- /* Configure the AC bias properties. */
- lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
-
/* Configure the vertical and horizontal sync properties. */
lcd_cfg_vertical_sync(panel->lower_margin, panel->vsync_len,
panel->upper_margin);
@@ -748,18 +745,12 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
panel->left_margin);
/* Configure for disply */
- ret = lcd_cfg_display(cfg);
+ ret = lcd_cfg_display(cfg, panel);
if (ret < 0)
return ret;
- if (QVGA != cfg->p_disp_panel->panel_type)
- return -EINVAL;
+ bpp = cfg->bpp;
- if (cfg->bpp <= cfg->p_disp_panel->max_bpp &&
- cfg->bpp >= cfg->p_disp_panel->min_bpp)
- bpp = cfg->bpp;
- else
- bpp = cfg->p_disp_panel->max_bpp;
if (bpp = 12)
bpp = 16;
ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->xres,
@@ -1381,7 +1372,7 @@ static int __devinit fb_probe(struct platform_device *device)
da8xx_fb_var.yres_virtual = lcdc_info->yres * LCD_NUM_BUFFERS;
da8xx_fb_var.grayscale - lcd_cfg->p_disp_panel->panel_shade = MONOCHROME ? 1 : 0;
+ lcd_cfg->panel_shade = MONOCHROME ? 1 : 0;
da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
da8xx_fb_var.hsync_len = lcdc_info->hsync_len;
diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h
index 12e4e1d..f888259 100644
--- a/include/video/da8xx-fb.h
+++ b/include/video/da8xx-fb.h
@@ -12,10 +12,6 @@
#ifndef DA8XX_FB_H
#define DA8XX_FB_H
-enum panel_type {
- QVGA = 0
-};
-
enum panel_shade {
MONOCHROME = 0,
COLOR_ACTIVE,
@@ -27,13 +23,6 @@ enum raster_load_mode {
LOAD_PALETTE,
};
-struct display_panel {
- enum panel_type panel_type; /* QVGA */
- int max_bpp;
- int min_bpp;
- enum panel_shade panel_shade;
-};
-
struct da8xx_lcdc_platform_data {
const char manu_name[10];
void *controller_data;
@@ -42,7 +31,7 @@ struct da8xx_lcdc_platform_data {
};
struct lcd_ctrl_config {
- const struct display_panel *p_disp_panel;
+ enum panel_shade panel_shade;
/* AC Bias Pin Frequency */
int ac_bias;
@@ -68,18 +57,9 @@ struct lcd_ctrl_config {
/* Mono 8-bit Mode: 1Ð-D7 or 0Ð-D3 */
unsigned char mono_8bit_mode;
- /* Invert line clock */
- unsigned char invert_line_clock;
-
- /* Invert frame clock */
- unsigned char invert_frm_clock;
-
/* Horizontal and Vertical Sync Edge: 0=rising 1úlling */
unsigned char sync_edge;
- /* Horizontal and Vertical Sync: Control: 0=ignore */
- unsigned char sync_ctrl;
-
/* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */
unsigned char raster_order;
--
1.7.0.4
^ permalink raw reply related
* [PATCH] video: s3c-fb: use dev_get_drvdata() instead of platform_get_drvdata()
From: Jingoo Han @ 2012-10-16 7:21 UTC (permalink / raw)
To: linux-fbdev
Because there is no need to access to the platform device in
suspend/resume and runtime_suspend/resume, dev_get_drvdata()
can be used instead of platform_get_drvdata() to make the code
smaller.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
drivers/video/s3c-fb.c | 14 +++++---------
1 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 2ed7b63..95c6e30 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1544,8 +1544,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int s3c_fb_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct s3c_fb *sfb = platform_get_drvdata(pdev);
+ struct s3c_fb *sfb = dev_get_drvdata(dev);
struct s3c_fb_win *win;
int win_no;
@@ -1572,8 +1571,7 @@ static int s3c_fb_suspend(struct device *dev)
static int s3c_fb_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct s3c_fb *sfb = platform_get_drvdata(pdev);
+ struct s3c_fb *sfb = dev_get_drvdata(dev);
struct s3c_fb_platdata *pd = sfb->pdata;
struct s3c_fb_win *win;
int win_no;
@@ -1623,7 +1621,7 @@ static int s3c_fb_resume(struct device *dev)
if (!win)
continue;
- dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
+ dev_dbg(dev, "resuming window %d\n", win_no);
s3c_fb_set_par(win->fbinfo);
}
@@ -1636,8 +1634,7 @@ static int s3c_fb_resume(struct device *dev)
#ifdef CONFIG_PM_RUNTIME
static int s3c_fb_runtime_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct s3c_fb *sfb = platform_get_drvdata(pdev);
+ struct s3c_fb *sfb = dev_get_drvdata(dev);
if (!sfb->variant.has_clksel)
clk_disable_unprepare(sfb->lcd_clk);
@@ -1649,8 +1646,7 @@ static int s3c_fb_runtime_suspend(struct device *dev)
static int s3c_fb_runtime_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct s3c_fb *sfb = platform_get_drvdata(pdev);
+ struct s3c_fb *sfb = dev_get_drvdata(dev);
struct s3c_fb_platdata *pd = sfb->pdata;
clk_prepare_enable(sfb->bus_clk);
--
1.7.1
^ permalink raw reply related
* Re: [PATCH V5 1/2] video: exynos_dp: Add device tree support to DP driver
From: Sylwester Nawrocki @ 2012-10-16 11:07 UTC (permalink / raw)
To: Jingoo Han
Cc: 'Sylwester Nawrocki', 'Florian Tobias Schandinat',
'Ajay Kumar', linux-samsung-soc, linux-fbdev,
devicetree-discuss, 'Tomasz Figa',
'Thomas Abraham'
In-Reply-To: <005a01cdab42$5a8ca390$0fa5eab0$%han@samsung.com>
On 10/16/2012 04:02 AM, Jingoo Han wrote:
> On Tuesday, October 16, 2012 6:14 AM Sylwester Nawrocki wrote
>> On 10/15/2012 10:14 AM, Jingoo Han wrote:
>>> On Saturday, October 13, 2012 6:44 AM Sylwester Nawrocki wrote
>>>>
>>>> On 10/12/2012 10:47 PM, Ajay Kumar 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.
>>>>>
>>>>> Signed-off-by: Ajay Kumar<ajaykumar.rs@samsung.com>
>>>>> Acked-by: Jingoo Han<jg1.han@samsung.com>
>>>>> ---
>>>>> drivers/video/exynos/exynos_dp_core.c | 161 ++++++++++++++++++++++++++++++---
>>>>> drivers/video/exynos/exynos_dp_core.h | 2 +
>>>>> 2 files changed, 149 insertions(+), 14 deletions(-)
>> ...
>>>>> @@ -953,8 +1062,13 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
>>>>> struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
>>>>> struct exynos_dp_device *dp = platform_get_drvdata(pdev);
>>>>
>>>> This doesn't belong to your patch, but the above 2 lines could be written as:
>>>>
>>>> struct exynos_dp_device *dp = dev_get_drvdata(&pdev->dev);
>>>>
>>>> Same in functions exynos_dp_suspend() and exynos_dp_resume().
>>>
>>> No, above 2 lines cannot be reduced to 1 line, as you mentioned.
>>> This is because it makes build error.
>>
>> Sorry, my bad. It looks fine in case of exynos_dp_remove().
>>
>> But at exynos_dp_suspend/resume() there is something like:
>>
>>
>> static int exynos_dp_suspend(struct device *dev)
>> {
>> struct platform_device *pdev = to_platform_device(dev);
>> struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
>> struct exynos_dp_device *dp = platform_get_drvdata(pdev);
>>
>>
>> You need only pdata and dp there. I think that simpler form would
>> do as well:
>>
>> struct exynos_dp_device *dp = dev_get_drvdata(dev);
>> struct exynos_dp_platdata *pdata = dev->platform_data;
>
> OK, I see.
> I will accept your suggestion, because it is helpful to reduce
> lines. Then, I will send v8 patch, soon.
OK. I thought about it more as a candidate for a separate. But you seem
to have already sent new version, it's probably fine this way too.
--
Regards,
Sylwester
^ permalink raw reply
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