* Re: [PATCH v7 2/2] video: backlight: support s6e8ax0 panel driver based on MIPI DSI
From: Tomi Valkeinen @ 2012-01-26 15:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4F17AA14.8030100@samsung.com>
[-- Attachment #1: Type: text/plain, Size: 1331 bytes --]
Hi,
On Thu, 2012-01-19 at 14:28 +0900, Donghwa Lee wrote:
> This patch is amoled panel driver based MIPI DSI interface.
> S6E8AX0 means it may includes many other ldi controllers, for example,
> S6E8AA0, S6E8AB0, and so on.
>
> This patch can be modified depending on each panel properites. For example,
> second parameter of panel condition register can be changed depending on
> ldi controller or amoled type.
>
> Changes since v6:
> - change data type from const to static const
>
> Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
> Signed-off-by: Inki Dae <inki.dae@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> drivers/video/backlight/Kconfig | 7 +
> drivers/video/backlight/Makefile | 1 +
> drivers/video/backlight/s6e8ax0.c | 898 +++++++++++++++++++++++++++++++++++++
> drivers/video/backlight/s6e8ax0.h | 21 +
> 4 files changed, 927 insertions(+), 0 deletions(-)
> create mode 100644 drivers/video/backlight/s6e8ax0.c
> create mode 100644 drivers/video/backlight/s6e8ax0.h
Why is this in backlight directory? It's a panel driver, not a backlight
driver.
And the driver is s5p specific, wouldn't a directory like
drivers/video/s5p/, where both the s5p DSI driver from the previous
patch and this panel driver could be?
Tomi
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH] fbdev: sh_mipi_dsi: add extra settings method for platform
From: Kuninori Morimoto @ 2012-01-27 0:53 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <874nvnhupd.wl%kuninori.morimoto.gx@renesas.com>
Hi
> How does TI handle that for the OMAP platform ? I don't think they configure
> the LCD module/panel in board code. Maybe we should ask them if they have a
> solution, or even plans to handle the problem ? Tomi Valkeinen is probably the
> right person to ask.
I asked it to Tomi (off-list), and I got one solution.
I will create SuperH panel driver for it.
Thank you Laurent, Tomi.
Best regards
---
Kuninori Morimoto
^ permalink raw reply
* Re: [PATCH v7 1/2] video: support MIPI-DSI controller driver
From: Donghwa Lee @ 2012-01-27 1:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1327592757.2843.1.camel@lappy>
2012년 01월 27일 00:45, Tomi Valkeinen 쓴 글:
> Hi,
>
> On Wed, 2012-01-25 at 09:14 +0900, Donghwa Lee wrote:
>> On Sat, 21 Jan 2012 08:51, Andrew Morton wrote:
>>
>>> On Thu, 19 Jan 2012 20:08:07 +0530
>>> Archit <a0393947@ti.com> wrote:
>>>
>>>> On Thursday 19 January 2012 10:58 AM, Donghwa Lee wrote:
>>>>> Samsung S5PC210 and EXYNOS SoC platform has MIPI-DSI controller and MIPI-DSI
>>>>> based LCD Panel could be used with it. This patch supports MIPI-DSI driver
>>>>> based Samsung SoC chip.
>>>>>
>>>>> LCD panel driver based MIPI-DSI should be registered to MIPI-DSI driver at
>>>>> machine code and LCD panel driver specific function registered to mipi_dsim_ddi
>>>>> structure at lcd panel init function called system init.
>>>>> In the MIPI-DSI driver, find lcd panel driver by using registered
>>>>> lcd panel name, and then initialize lcd panel driver.
>>>>>
>>>>> Changes since v6:
>>>>> - remove obscure compile problems.
>>>>> - remove useless codes.
>>>>> - modify return errno codes properly
>>>>
>>>> One more comment about 'mipi_dsim.h', it would be better to put it in
>>>> include/video and not 'include/linux'.
>>>
>>> Yes, that is desirable.
>>>
>>>>> ---
>>>>> drivers/video/Kconfig | 6 +
>>>>> drivers/video/Makefile | 2 +
>>>>> drivers/video/s5p_mipi_dsi.c | 599 ++++++++++++++++++++++
>>>>> drivers/video/s5p_mipi_dsi_common.c | 896 +++++++++++++++++++++++++++++++++
>>>>> drivers/video/s5p_mipi_dsi_common.h | 46 ++
>>>>> drivers/video/s5p_mipi_dsi_lowlevel.c | 617 +++++++++++++++++++++++
>>>>> drivers/video/s5p_mipi_dsi_lowlevel.h | 112 ++++
>>>>> drivers/video/s5p_mipi_dsi_regs.h | 149 ++++++
>>>>> include/linux/mipi_dsim.h | 359 +++++++++++++
>>>>> 9 files changed, 2786 insertions(+), 0 deletions(-)
>>>
>>> or we could put it in drivers/video/. It all depends on which other
>>> drivers we expect will need access to this header.
>>>
>>
>> No, mipi_dsim.h file includes global interface data, callback function called by machine
>> file, platform data for mipi-dsi driver and so on. So I think it would be better to put
>> in 'include/video' or 'include/linux'.
>> Of course it is much better to change name to 's5p_mipi_dsim.h'
>
> The header file looks like a platform specific header, so I agree that
> it should start with s5p.
>
> I think we should finally start working on a common DSI framework =).
>
> Tomi
>
Yes, I agree with you. I will resend next version patch set changed file name
from 'mipi_dsim.h' to 's5p_mipi_dsim.h'
Thank you,
Donghwa Lee
^ permalink raw reply
* RE: [PATCH v7 2/2] video: backlight: support s6e8ax0 panel driver based on MIPI DSI
From: Inki Dae @ 2012-01-27 2:07 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <4F17AA14.8030100@samsung.com>
Hi, Tomi.
Below is my comments.
> -----Original Message-----
> From: Tomi Valkeinen [mailto:tomi.valkeinen@ti.com]
> Sent: Friday, January 27, 2012 12:53 AM
> To: Donghwa Lee
> Cc: linux-fbdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> Florian Tobias Schandinat; Andrew Morton; rpurdie@linux.intel.com;
> inki.dae@samsung.com; kyungmin.park@samsung.com
> Subject: Re: [PATCH v7 2/2] video: backlight: support s6e8ax0 panel driver
> based on MIPI DSI
>
> Hi,
>
> On Thu, 2012-01-19 at 14:28 +0900, Donghwa Lee wrote:
> > This patch is amoled panel driver based MIPI DSI interface.
> > S6E8AX0 means it may includes many other ldi controllers, for example,
> > S6E8AA0, S6E8AB0, and so on.
> >
> > This patch can be modified depending on each panel properites. For
> > example, second parameter of panel condition register can be changed
> > depending on ldi controller or amoled type.
> >
> > Changes since v6:
> > - change data type from const to static const
> >
> > Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
> > Signed-off-by: Inki Dae <inki.dae@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > ---
> > drivers/video/backlight/Kconfig | 7 +
> > drivers/video/backlight/Makefile | 1 +
> > drivers/video/backlight/s6e8ax0.c | 898
> +++++++++++++++++++++++++++++++++++++
> > drivers/video/backlight/s6e8ax0.h | 21 +
> > 4 files changed, 927 insertions(+), 0 deletions(-) create mode
> > 100644 drivers/video/backlight/s6e8ax0.c create mode 100644
> > drivers/video/backlight/s6e8ax0.h
>
> Why is this in backlight directory? It's a panel driver, not a backlight
> driver.
>
Yes, right. this backlight driver is specific to our mipi dsi driver because this uses the interface of mipi dsi driver to send some commands to real lcd panel.
> And the driver is s5p specific, wouldn't a directory like
> drivers/video/s5p/, where both the s5p DSI driver from the previous patch
> and this panel driver could be?
>
Ok, we will create new directory, "exynos" instead of "s5p" because our SoC chip doesn't use such prefix(s5p, and s3c) anymore. and also as you mentioned, we should working on a common DSI framework. do you have any plan for this?
Thanks,
Inki Dae.
> Tomi
^ permalink raw reply
* RE: [PATCH v7 2/2] video: backlight: support s6e8ax0 panel driver based on MIPI DSI
From: Jingoo Han @ 2012-01-27 3:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <001901ccdc98$755d4bd0$6017e370$%dae@samsung.com>
Hi, Inki Dae.
> -----Original Message-----
> From: linux-fbdev-owner@vger.kernel.org [mailto:linux-fbdev-owner@vger.kernel.org] On Behalf Of Inki
> Dae
> Sent: Friday, January 27, 2012 11:08 AM
> To: 'Tomi Valkeinen'; 'Donghwa Lee'
> Cc: linux-fbdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org; 'Florian Tobias Schandinat';
> 'Andrew Morton'; rpurdie@linux.intel.com; kyungmin.park@samsung.com
> Subject: RE: [PATCH v7 2/2] video: backlight: support s6e8ax0 panel driver based on MIPI DSI
>
> Hi, Tomi.
>
> Below is my comments.
>
> > -----Original Message-----
> > From: Tomi Valkeinen [mailto:tomi.valkeinen@ti.com]
> > Sent: Friday, January 27, 2012 12:53 AM
> > To: Donghwa Lee
> > Cc: linux-fbdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > Florian Tobias Schandinat; Andrew Morton; rpurdie@linux.intel.com;
> > inki.dae@samsung.com; kyungmin.park@samsung.com
> > Subject: Re: [PATCH v7 2/2] video: backlight: support s6e8ax0 panel driver
> > based on MIPI DSI
> >
> > Hi,
> >
> > On Thu, 2012-01-19 at 14:28 +0900, Donghwa Lee wrote:
> > > This patch is amoled panel driver based MIPI DSI interface.
> > > S6E8AX0 means it may includes many other ldi controllers, for example,
> > > S6E8AA0, S6E8AB0, and so on.
> > >
> > > This patch can be modified depending on each panel properites. For
> > > example, second parameter of panel condition register can be changed
> > > depending on ldi controller or amoled type.
> > >
> > > Changes since v6:
> > > - change data type from const to static const
> > >
> > > Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
> > > Signed-off-by: Inki Dae <inki.dae@samsung.com>
> > > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > ---
> > > drivers/video/backlight/Kconfig | 7 +
> > > drivers/video/backlight/Makefile | 1 +
> > > drivers/video/backlight/s6e8ax0.c | 898
> > +++++++++++++++++++++++++++++++++++++
> > > drivers/video/backlight/s6e8ax0.h | 21 +
> > > 4 files changed, 927 insertions(+), 0 deletions(-) create mode
> > > 100644 drivers/video/backlight/s6e8ax0.c create mode 100644
> > > drivers/video/backlight/s6e8ax0.h
> >
> > Why is this in backlight directory? It's a panel driver, not a backlight
> > driver.
> >
>
> Yes, right. this backlight driver is specific to our mipi dsi driver because this uses the interface
> of mipi dsi driver to send some commands to real lcd panel.
>
> > And the driver is s5p specific, wouldn't a directory like
> > drivers/video/s5p/, where both the s5p DSI driver from the previous patch
> > and this panel driver could be?
> >
>
> Ok, we will create new directory, "exynos" instead of "s5p" because our SoC chip doesn't use such
> prefix(s5p, and s3c) anymore. and also as you mentioned, we should working on a common DSI framework.
> do you have any plan for this?
I think so. New directory, "exynos" is necessary.
The "exynos" directory can include IPs such as MIPI, which are related to FB stack
and are used for exynos SoC series.
However, s3c-fb.c will remain in "drivers/video" directory, because s3c-fb.c can be
used for s3c24xx, s5p64xx SoC series as well as exynos series.
Thank you.
>
> Thanks,
> Inki Dae.
>
> > Tomi
>
>
> --
> 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 v7 1/2] video: support MIPI-DSI controller driver
From: Jingoo Han @ 2012-01-27 3:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1327592757.2843.1.camel@lappy>
Hi, Tomi.
> -----Original Message-----
> From: linux-fbdev-owner@vger.kernel.org [mailto:linux-fbdev-owner@vger.kernel.org] On Behalf Of Tomi
> Valkeinen
> Sent: Friday, January 27, 2012 12:46 AM
> To: Donghwa Lee
> Cc: Andrew Morton; Archit; linux-fbdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org; Florian
> Tobias Schandinat; rpurdie@linux.intel.com; inki.dae@samsung.com; kyungmin.park@samsung.com
> Subject: Re: [PATCH v7 1/2] video: support MIPI-DSI controller driver
>
> Hi,
>
> On Wed, 2012-01-25 at 09:14 +0900, Donghwa Lee wrote:
> > On Sat, 21 Jan 2012 08:51, Andrew Morton wrote:
> >
> > > On Thu, 19 Jan 2012 20:08:07 +0530
> > > Archit <a0393947@ti.com> wrote:
> > >
> > >> On Thursday 19 January 2012 10:58 AM, Donghwa Lee wrote:
> > >>> Samsung S5PC210 and EXYNOS SoC platform has MIPI-DSI controller and MIPI-DSI
> > >>> based LCD Panel could be used with it. This patch supports MIPI-DSI driver
> > >>> based Samsung SoC chip.
> > >>>
> > >>> LCD panel driver based MIPI-DSI should be registered to MIPI-DSI driver at
> > >>> machine code and LCD panel driver specific function registered to mipi_dsim_ddi
> > >>> structure at lcd panel init function called system init.
> > >>> In the MIPI-DSI driver, find lcd panel driver by using registered
> > >>> lcd panel name, and then initialize lcd panel driver.
> > >>>
> > >>> Changes since v6:
> > >>> - remove obscure compile problems.
> > >>> - remove useless codes.
> > >>> - modify return errno codes properly
> > >>
> > >> One more comment about 'mipi_dsim.h', it would be better to put it in
> > >> include/video and not 'include/linux'.
> > >
> > > Yes, that is desirable.
> > >
> > >>> ---
> > >>> drivers/video/Kconfig | 6 +
> > >>> drivers/video/Makefile | 2 +
> > >>> drivers/video/s5p_mipi_dsi.c | 599 ++++++++++++++++++++++
> > >>> drivers/video/s5p_mipi_dsi_common.c | 896 +++++++++++++++++++++++++++++++++
> > >>> drivers/video/s5p_mipi_dsi_common.h | 46 ++
> > >>> drivers/video/s5p_mipi_dsi_lowlevel.c | 617 +++++++++++++++++++++++
> > >>> drivers/video/s5p_mipi_dsi_lowlevel.h | 112 ++++
> > >>> drivers/video/s5p_mipi_dsi_regs.h | 149 ++++++
> > >>> include/linux/mipi_dsim.h | 359 +++++++++++++
> > >>> 9 files changed, 2786 insertions(+), 0 deletions(-)
> > >
> > > or we could put it in drivers/video/. It all depends on which other
> > > drivers we expect will need access to this header.
> > >
> >
> > No, mipi_dsim.h file includes global interface data, callback function called by machine
> > file, platform data for mipi-dsi driver and so on. So I think it would be better to put
> > in 'include/video' or 'include/linux'.
> > Of course it is much better to change name to 's5p_mipi_dsim.h'
>
> The header file looks like a platform specific header, so I agree that
> it should start with s5p.
>
> I think we should finally start working on a common DSI framework =).
I agree with you in your opinion.
The common DSI framework would be useful.
Thank you.
>
> Tomi
^ permalink raw reply
* [PATCH 1/2] video: s3c-fb: add alpha value width setting
From: Jingoo Han @ 2012-01-27 5:47 UTC (permalink / raw)
To: linux-fbdev
This patch adds alpha value width setting according to
transparency value of each window format, using BLENDCON
register. When alpha value is 8 bits, BLENDCON will set
alpha value width as 8 bits.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
arch/arm/plat-samsung/include/plat/regs-fb.h | 6 ++++++
drivers/video/s3c-fb.c | 18 ++++++++++++++++++
2 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h
index 8f39aa5..6bf68ed 100644
--- a/arch/arm/plat-samsung/include/plat/regs-fb.h
+++ b/arch/arm/plat-samsung/include/plat/regs-fb.h
@@ -384,3 +384,9 @@
#define WPALCON_W0PAL_16BPP_A555 (0x5 << 0)
#define WPALCON_W0PAL_16BPP_565 (0x6 << 0)
+/* Blending equation control */
+#define BLENDCON (0x260)
+#define BLENDCON_NEW_MASK (1 << 0)
+#define BLENDCON_NEW_8BIT_ALPHA_VALUE (1 << 0)
+#define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0)
+
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 0c63b69..e92be55 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -81,6 +81,7 @@ struct s3c_fb;
* @palette: Address of palette memory, or 0 if none.
* @has_prtcon: Set if has PRTCON register.
* @has_shadowcon: Set if has SHADOWCON register.
+ * @has_blendcon: Set if has BLENDCON register.
* @has_clksel: Set if VIDCON0 register has CLKSEL bit.
*/
struct s3c_fb_variant {
@@ -99,6 +100,7 @@ struct s3c_fb_variant {
unsigned int has_prtcon:1;
unsigned int has_shadowcon:1;
+ unsigned int has_blendcon:1;
unsigned int has_clksel:1;
};
@@ -692,6 +694,17 @@ static int s3c_fb_set_par(struct fb_info *info)
writel(data, regs + sfb->variant.wincon + (win_no * 4));
writel(0x0, regs + sfb->variant.winmap + (win_no * 4));
+ /* Set alpha value width */
+ if (sfb->variant.has_blendcon) {
+ data = readl(sfb->regs + BLENDCON);
+ data &= ~BLENDCON_NEW_MASK;
+ if (var->transp.length > 4)
+ data |= BLENDCON_NEW_8BIT_ALPHA_VALUE;
+ else
+ data |= BLENDCON_NEW_4BIT_ALPHA_VALUE;
+ writel(data, sfb->regs + BLENDCON);
+ }
+
shadow_protect_win(win, 0);
pm_runtime_put_sync(sfb->dev);
@@ -1819,6 +1832,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
},
.has_prtcon = 1,
+ .has_blendcon = 1,
.has_clksel = 1,
},
.win[0] = &s3c_fb_data_s5p_wins[0],
@@ -1850,6 +1864,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
},
.has_shadowcon = 1,
+ .has_blendcon = 1,
.has_clksel = 1,
},
.win[0] = &s3c_fb_data_s5p_wins[0],
@@ -1881,6 +1896,7 @@ static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
},
.has_shadowcon = 1,
+ .has_blendcon = 1,
},
.win[0] = &s3c_fb_data_s5p_wins[0],
.win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1944,6 +1960,8 @@ static struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = {
[1] = 0x2800,
[2] = 0x2c00,
},
+
+ .has_blendcon = 1,
},
.win[0] = &s3c_fb_data_s5p_wins[0],
.win[1] = &s3c_fb_data_s5p_wins[1],
--
1.7.1
^ permalink raw reply related
* [PATCH 2/2] video: s3c-fb: add video clock running at data under-flow
From: Jingoo Han @ 2012-01-27 5:47 UTC (permalink / raw)
To: linux-fbdev
This patch adds video clock running at data under-flow.
It means that the pixel clock is continuously provided
to lcd module, even when under-run occurs.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
arch/arm/plat-samsung/include/plat/regs-fb.h | 3 +++
drivers/video/s3c-fb.c | 23 +++++++++++++++++++++++
2 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h
index 6bf68ed..bbb16e0 100644
--- a/arch/arm/plat-samsung/include/plat/regs-fb.h
+++ b/arch/arm/plat-samsung/include/plat/regs-fb.h
@@ -91,6 +91,9 @@
#define VIDCON1_VSTATUS_BACKPORCH (0x1 << 13)
#define VIDCON1_VSTATUS_ACTIVE (0x2 << 13)
#define VIDCON1_VSTATUS_FRONTPORCH (0x0 << 13)
+#define VIDCON1_VCLK_MASK (0x3 << 9)
+#define VIDCON1_VCLK_HOLD (0x0 << 9)
+#define VIDCON1_VCLK_RUN (0x1 << 9)
#define VIDCON1_INV_VCLK (1 << 7)
#define VIDCON1_INV_HSYNC (1 << 6)
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index e92be55..71902cb 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -83,6 +83,7 @@ struct s3c_fb;
* @has_shadowcon: Set if has SHADOWCON register.
* @has_blendcon: Set if has BLENDCON register.
* @has_clksel: Set if VIDCON0 register has CLKSEL bit.
+ * @has_fixvclk: Set if VIDCON1 register has FIXVCLK bits.
*/
struct s3c_fb_variant {
unsigned int is_2443:1;
@@ -102,6 +103,7 @@ struct s3c_fb_variant {
unsigned int has_shadowcon:1;
unsigned int has_blendcon:1;
unsigned int has_clksel:1;
+ unsigned int has_fixvclk:1;
};
/**
@@ -1359,6 +1361,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
struct resource *res;
int win;
int ret = 0;
+ u32 reg;
platid = platform_get_device_id(pdev);
fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
@@ -1457,6 +1460,14 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
writel(pd->vidcon1, sfb->regs + VIDCON1);
+ /* set video clock running at under-run */
+ if (sfb->variant.has_fixvclk) {
+ reg = readl(sfb->regs + VIDCON1);
+ reg &= ~VIDCON1_VCLK_MASK;
+ reg |= VIDCON1_VCLK_RUN;
+ writel(reg, sfb->regs + VIDCON1);
+ }
+
/* zero all windows before we do anything */
for (win = 0; win < fbdrv->variant.nr_windows; win++)
@@ -1592,6 +1603,7 @@ static int s3c_fb_resume(struct device *dev)
struct s3c_fb_platdata *pd = sfb->pdata;
struct s3c_fb_win *win;
int win_no;
+ u32 reg;
clk_enable(sfb->bus_clk);
@@ -1602,6 +1614,14 @@ static int s3c_fb_resume(struct device *dev)
pd->setup_gpio();
writel(pd->vidcon1, sfb->regs + VIDCON1);
+ /* set video clock running at under-run */
+ if (sfb->variant.has_fixvclk) {
+ reg = readl(sfb->regs + VIDCON1);
+ reg &= ~VIDCON1_VCLK_MASK;
+ reg |= VIDCON1_VCLK_RUN;
+ writel(reg, sfb->regs + VIDCON1);
+ }
+
/* zero all windows before we do anything */
for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
s3c_fb_clear_win(sfb, win_no);
@@ -1866,6 +1886,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
.has_shadowcon = 1,
.has_blendcon = 1,
.has_clksel = 1,
+ .has_fixvclk = 1,
},
.win[0] = &s3c_fb_data_s5p_wins[0],
.win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1897,6 +1918,7 @@ static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
.has_shadowcon = 1,
.has_blendcon = 1,
+ .has_fixvclk = 1,
},
.win[0] = &s3c_fb_data_s5p_wins[0],
.win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1962,6 +1984,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = {
},
.has_blendcon = 1,
+ .has_fixvclk = 1,
},
.win[0] = &s3c_fb_data_s5p_wins[0],
.win[1] = &s3c_fb_data_s5p_wins[1],
--
1.7.1
^ permalink raw reply related
* [PATCH] video: convert drivers/video/* to use module_spi_driver()
From: Axel Lin @ 2012-01-27 8:02 UTC (permalink / raw)
To: linux-kernel
Cc: Imre Deak, Roger Quadros, Steve Sakoman, Erik Gilling,
Gra Ignotas, Tomi Valkeinen, Florian Tobias Schandinat,
linux-fbdev, linux-omap
This patch converts the drivers in drivers/video/* to use the
module_spi_driver() macro which makes the code smaller and a bit simpler.
Signed-off-by: Axel Lin <axel.lin@gmail.com>
Cc: Imre Deak <imre.deak@nokia.com>
Cc: Roger Quadros <roger.quadros@nokia.com>
Cc: Steve Sakoman <steve@sakoman.com>
Cc: Erik Gilling <konkers@android.com>
Cc: Gražvydas Ignotas <notasas@gmail.com>
---
drivers/video/omap/lcd_mipid.c | 14 +-------------
drivers/video/omap2/displays/panel-acx565akm.c | 13 +------------
.../omap2/displays/panel-lgphilips-lb035q02.c | 12 +-----------
.../omap2/displays/panel-nec-nl8048hl11-01b.c | 12 +-----------
.../video/omap2/displays/panel-tpo-td043mtea1.c | 13 +------------
5 files changed, 5 insertions(+), 59 deletions(-)
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
index 8d546dd..e3880c4 100644
--- a/drivers/video/omap/lcd_mipid.c
+++ b/drivers/video/omap/lcd_mipid.c
@@ -609,19 +609,7 @@ static struct spi_driver mipid_spi_driver = {
.remove = __devexit_p(mipid_spi_remove),
};
-static int __init mipid_drv_init(void)
-{
- spi_register_driver(&mipid_spi_driver);
-
- return 0;
-}
-module_init(mipid_drv_init);
-
-static void __exit mipid_drv_cleanup(void)
-{
- spi_unregister_driver(&mipid_spi_driver);
-}
-module_exit(mipid_drv_cleanup);
+module_spi_driver(mipid_spi_driver);
MODULE_DESCRIPTION("MIPI display driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index 51a87e1..d26f37a 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -809,18 +809,7 @@ static struct spi_driver acx565akm_spi_driver = {
.remove = __devexit_p(acx565akm_spi_remove),
};
-static int __init acx565akm_init(void)
-{
- return spi_register_driver(&acx565akm_spi_driver);
-}
-
-static void __exit acx565akm_exit(void)
-{
- spi_unregister_driver(&acx565akm_spi_driver);
-}
-
-module_init(acx565akm_init);
-module_exit(acx565akm_exit);
+module_spi_driver(acx565akm_spi_driver);
MODULE_AUTHOR("Nokia Corporation");
MODULE_DESCRIPTION("acx565akm LCD Driver");
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
index e0eb35b..0841cc2 100644
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -264,16 +264,6 @@ static struct spi_driver lb035q02_spi_driver = {
.remove = __devexit_p(lb035q02_panel_spi_remove),
};
-static int __init lb035q02_panel_drv_init(void)
-{
- return spi_register_driver(&lb035q02_spi_driver);
-}
-
-static void __exit lb035q02_panel_drv_exit(void)
-{
- spi_unregister_driver(&lb035q02_spi_driver);
-}
+module_spi_driver(lb035q02_spi_driver);
-module_init(lb035q02_panel_drv_init);
-module_exit(lb035q02_panel_drv_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index 0eb31ca..8b38b39 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -350,18 +350,8 @@ static struct spi_driver nec_8048_spi_driver = {
},
};
-static int __init nec_8048_lcd_init(void)
-{
- return spi_register_driver(&nec_8048_spi_driver);
-}
-
-static void __exit nec_8048_lcd_exit(void)
-{
- return spi_unregister_driver(&nec_8048_spi_driver);
-}
+module_spi_driver(nec_8048_spi_driver);
-module_init(nec_8048_lcd_init);
-module_exit(nec_8048_lcd_exit);
MODULE_AUTHOR("Erik Gilling <konkers@android.com>");
MODULE_DESCRIPTION("NEC-nl8048hl11-01b Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index e6649aa..1d6b7fb 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -518,18 +518,7 @@ static struct spi_driver tpo_td043_spi_driver = {
.remove = __devexit_p(tpo_td043_spi_remove),
};
-static int __init tpo_td043_init(void)
-{
- return spi_register_driver(&tpo_td043_spi_driver);
-}
-
-static void __exit tpo_td043_exit(void)
-{
- spi_unregister_driver(&tpo_td043_spi_driver);
-}
-
-module_init(tpo_td043_init);
-module_exit(tpo_td043_exit);
+module_spi_driver(tpo_td043_spi_driver);
MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
--
1.7.5.4
^ permalink raw reply related
* [PATCH v8 1/2] video: support MIPI-DSI controller driver
From: Donghwa Lee @ 2012-01-27 9:12 UTC (permalink / raw)
To: linux-arm-kernel
Samsung S5PC210 and EXYNOS SoC platform has MIPI-DSI controller and MIPI-DSI
based LCD Panel could be used with it. This patch supports MIPI-DSI driver
based Samsung SoC chip.
LCD panel driver based MIPI-DSI should be registered to MIPI-DSI driver at
machine code and LCD panel driver specific function registered to mipi_dsim_ddi
structure at lcd panel init function called system init.
In the MIPI-DSI driver, find lcd panel driver by using registered
lcd panel name, and then initialize lcd panel driver.
Changes since v7:
- create new directory related exynos video driver
- move all new files to driver/video/exynos
- change name from "mipi_dsim.h" to "exynos_mipi_dsim.h".
Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Jingoo Han <jg1.han@samsung.com>
---
drivers/video/Kconfig | 1 +
drivers/video/Makefile | 2 +
drivers/video/exynos/Kconfig | 22 +
drivers/video/exynos/Makefile | 6 +
drivers/video/exynos/exynos_mipi_dsi.c | 600 +++++++++++++++
drivers/video/exynos/exynos_mipi_dsi_common.c | 896 +++++++++++++++++++++++
drivers/video/exynos/exynos_mipi_dsi_common.h | 46 ++
drivers/video/exynos/exynos_mipi_dsi_lowlevel.c | 618 ++++++++++++++++
drivers/video/exynos/exynos_mipi_dsi_lowlevel.h | 112 +++
drivers/video/exynos/exynos_mipi_dsi_regs.h | 149 ++++
include/video/exynos_mipi_dsim.h | 359 +++++++++
11 files changed, 2811 insertions(+), 0 deletions(-)
create mode 100644 drivers/video/exynos/Kconfig
create mode 100644 drivers/video/exynos/Makefile
create mode 100644 drivers/video/exynos/exynos_mipi_dsi.c
create mode 100644 drivers/video/exynos/exynos_mipi_dsi_common.c
create mode 100644 drivers/video/exynos/exynos_mipi_dsi_common.h
create mode 100644 drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
create mode 100644 drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
create mode 100644 drivers/video/exynos/exynos_mipi_dsi_regs.h
create mode 100644 include/video/exynos_mipi_dsim.h
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index d83e967..f2e05c0 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2414,6 +2414,7 @@ source "drivers/video/omap2/Kconfig"
source "drivers/video/backlight/Kconfig"
source "drivers/video/display/Kconfig"
+source "drivers/video/exynos/Kconfig"
if VT
source "drivers/video/console/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9b9d8ff..762a916 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -15,6 +15,8 @@ obj-$(CONFIG_VT) += console/
obj-$(CONFIG_LOGO) += logo/
obj-y += backlight/ display/
+obj-$(CONFIG_EXYNOS_VIDEO) += exynos/
+
obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
new file mode 100644
index 0000000..645b8a5
--- /dev/null
+++ b/drivers/video/exynos/Kconfig
@@ -0,0 +1,22 @@
+#
+# Exynos Video configuration
+#
+
+menuconfig EXYNOS_VIDEO
+ bool "Exynos Video driver support"
+ help
+ This enables support for EXYNOS Video device.
+
+if EXYNOS_VIDEO
+
+#
+# MIPI DSI driver
+#
+
+config EXYNOS_MIPI_DSI
+ bool "EXYNOS MIPI DSI driver support."
+ depends on (ARCH_S5PV210 || ARCH_EXYNOS)
+ help
+ This enables support for MIPI-DSI device.
+
+endif # EXYNOS_VIDEO
diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile
new file mode 100644
index 0000000..a1ae82a
--- /dev/null
+++ b/drivers/video/exynos/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the exynos video drivers.
+#
+
+obj-$(CONFIG_EXYNOS_MIPI_DSI) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \
+ exynos_mipi_dsi_lowlevel.o
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c
new file mode 100644
index 0000000..557091d
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi.c
@@ -0,0 +1,600 @@
+/* linux/drivers/video/exynos/exynos_mipi_dsi.c
+ *
+ * Samsung SoC MIPI-DSIM driver.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae, <inki.dae@samsung.com>
+ * Donghwa Lee, <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/ctype.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/memory.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+#include <linux/notifier.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+
+#include <video/exynos_mipi_dsim.h>
+
+#include <plat/fb.h>
+
+#include "exynos_mipi_dsi_common.h"
+#include "exynos_mipi_dsi_lowlevel.h"
+
+struct mipi_dsim_ddi {
+ int bus_id;
+ struct list_head list;
+ struct mipi_dsim_lcd_device *dsim_lcd_dev;
+ struct mipi_dsim_lcd_driver *dsim_lcd_drv;
+};
+
+static LIST_HEAD(dsim_ddi_list);
+
+static DEFINE_MUTEX(mipi_dsim_lock);
+
+static struct mipi_dsim_platform_data *to_dsim_plat(struct platform_device
+ *pdev)
+{
+ return pdev->dev.platform_data;
+}
+
+static struct regulator_bulk_data supplies[] = {
+ { .supply = "vdd10", },
+ { .supply = "vdd18", },
+};
+
+static int exynos_mipi_regulator_enable(struct mipi_dsim_device *dsim)
+{
+ int ret;
+
+ mutex_lock(&dsim->lock);
+ ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
+ mutex_unlock(&dsim->lock);
+
+ return ret;
+}
+
+static int exynos_mipi_regulator_disable(struct mipi_dsim_device *dsim)
+{
+ int ret;
+
+ mutex_lock(&dsim->lock);
+ ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
+ mutex_unlock(&dsim->lock);
+
+ return ret;
+}
+
+/* update all register settings to MIPI DSI controller. */
+static void exynos_mipi_update_cfg(struct mipi_dsim_device *dsim)
+{
+ /*
+ * data from Display controller(FIMD) is not transferred in video mode
+ * but in case of command mode, all settings is not updated to
+ * registers.
+ */
+ exynos_mipi_dsi_stand_by(dsim, 0);
+
+ exynos_mipi_dsi_init_dsim(dsim);
+ exynos_mipi_dsi_init_link(dsim);
+
+ exynos_mipi_dsi_set_hs_enable(dsim);
+
+ /* set display timing. */
+ exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
+
+ /*
+ * data from Display controller(FIMD) is transferred in video mode
+ * but in case of command mode, all settigs is updated to registers.
+ */
+ exynos_mipi_dsi_stand_by(dsim, 1);
+}
+
+static int exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim,
+ int power)
+{
+ struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
+ struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
+
+ switch (power) {
+ case FB_BLANK_POWERDOWN:
+ if (dsim->suspended)
+ return 0;
+
+ if (client_drv && client_drv->suspend)
+ client_drv->suspend(client_dev);
+
+ clk_disable(dsim->clock);
+
+ exynos_mipi_regulator_disable(dsim);
+
+ dsim->suspended = true;
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
+{
+ struct platform_device *pdev = to_platform_device(dsim->dev);
+ struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
+ struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
+
+ switch (power) {
+ case FB_BLANK_UNBLANK:
+ if (!dsim->suspended)
+ return 0;
+
+ /* lcd panel power on. */
+ if (client_drv && client_drv->power_on)
+ client_drv->power_on(client_dev, 1);
+
+ exynos_mipi_regulator_disable(dsim);
+
+ /* enable MIPI-DSI PHY. */
+ if (dsim->pd->phy_enable)
+ dsim->pd->phy_enable(pdev, true);
+
+ clk_enable(dsim->clock);
+
+ exynos_mipi_update_cfg(dsim);
+
+ /* set lcd panel sequence commands. */
+ if (client_drv && client_drv->set_sequence)
+ client_drv->set_sequence(client_dev);
+
+ dsim->suspended = false;
+
+ break;
+ case FB_BLANK_NORMAL:
+ /* TODO. */
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
+{
+ struct mipi_dsim_ddi *dsim_ddi;
+
+ if (!lcd_dev->name) {
+ pr_err("dsim_lcd_device name is NULL.\n");
+ return -EFAULT;
+ }
+
+ dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
+ if (!dsim_ddi) {
+ pr_err("failed to allocate dsim_ddi object.\n");
+ return -ENOMEM;
+ }
+
+ dsim_ddi->dsim_lcd_dev = lcd_dev;
+
+ mutex_lock(&mipi_dsim_lock);
+ list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
+ mutex_unlock(&mipi_dsim_lock);
+
+ return 0;
+}
+
+struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv)
+{
+ struct mipi_dsim_ddi *dsim_ddi, *next;
+ struct mipi_dsim_lcd_device *lcd_dev;
+
+ mutex_lock(&mipi_dsim_lock);
+
+ list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
+ if (!dsim_ddi)
+ goto out;
+
+ lcd_dev = dsim_ddi->dsim_lcd_dev;
+ if (!lcd_dev)
+ continue;
+
+ if ((strcmp(lcd_drv->name, lcd_dev->name)) = 0) {
+ /**
+ * bus_id would be used to identify
+ * connected bus.
+ */
+ dsim_ddi->bus_id = lcd_dev->bus_id;
+ mutex_unlock(&mipi_dsim_lock);
+
+ return dsim_ddi;
+ }
+
+ list_del(&dsim_ddi->list);
+ kfree(dsim_ddi);
+ }
+
+out:
+ mutex_unlock(&mipi_dsim_lock);
+
+ return NULL;
+}
+
+int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
+{
+ struct mipi_dsim_ddi *dsim_ddi;
+
+ if (!lcd_drv->name) {
+ pr_err("dsim_lcd_driver name is NULL.\n");
+ return -EFAULT;
+ }
+
+ dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv);
+ if (!dsim_ddi) {
+ pr_err("mipi_dsim_ddi object not found.\n");
+ return -EFAULT;
+ }
+
+ dsim_ddi->dsim_lcd_drv = lcd_drv;
+
+ pr_info("registered panel driver(%s) to mipi-dsi driver.\n",
+ lcd_drv->name);
+
+ return 0;
+
+}
+
+struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim,
+ const char *name)
+{
+ struct mipi_dsim_ddi *dsim_ddi, *next;
+ struct mipi_dsim_lcd_driver *lcd_drv;
+ struct mipi_dsim_lcd_device *lcd_dev;
+ int ret;
+
+ mutex_lock(&dsim->lock);
+
+ list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
+ lcd_drv = dsim_ddi->dsim_lcd_drv;
+ lcd_dev = dsim_ddi->dsim_lcd_dev;
+ if (!lcd_drv || !lcd_dev ||
+ (dsim->id != dsim_ddi->bus_id))
+ continue;
+
+ dev_dbg(dsim->dev, "lcd_drv->id = %d, lcd_dev->id = %d\n",
+ lcd_drv->id, lcd_dev->id);
+ dev_dbg(dsim->dev, "lcd_dev->bus_id = %d, dsim->id = %d\n",
+ lcd_dev->bus_id, dsim->id);
+
+ if ((strcmp(lcd_drv->name, name) = 0)) {
+ lcd_dev->master = dsim;
+
+ lcd_dev->dev.parent = dsim->dev;
+ dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name);
+
+ ret = device_register(&lcd_dev->dev);
+ if (ret < 0) {
+ dev_err(dsim->dev,
+ "can't register %s, status %d\n",
+ dev_name(&lcd_dev->dev), ret);
+ mutex_unlock(&dsim->lock);
+
+ return NULL;
+ }
+
+ dsim->dsim_lcd_dev = lcd_dev;
+ dsim->dsim_lcd_drv = lcd_drv;
+
+ mutex_unlock(&dsim->lock);
+
+ return dsim_ddi;
+ }
+ }
+
+ mutex_unlock(&dsim->lock);
+
+ return NULL;
+}
+
+/* define MIPI-DSI Master operations. */
+static struct mipi_dsim_master_ops master_ops = {
+ .cmd_read = exynos_mipi_dsi_rd_data,
+ .cmd_write = exynos_mipi_dsi_wr_data,
+ .get_dsim_frame_done = exynos_mipi_dsi_get_frame_done_status,
+ .clear_dsim_frame_done = exynos_mipi_dsi_clear_frame_done,
+ .set_early_blank_mode = exynos_mipi_dsi_early_blank_mode,
+ .set_blank_mode = exynos_mipi_dsi_blank_mode,
+};
+
+static int exynos_mipi_dsi_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct mipi_dsim_device *dsim;
+ struct mipi_dsim_config *dsim_config;
+ struct mipi_dsim_platform_data *dsim_pd;
+ struct mipi_dsim_ddi *dsim_ddi;
+ int ret = -EINVAL;
+
+ dsim = kzalloc(sizeof(struct mipi_dsim_device), GFP_KERNEL);
+ if (!dsim) {
+ dev_err(&pdev->dev, "failed to allocate dsim object.\n");
+ return -ENOMEM;
+ }
+
+ dsim->pd = to_dsim_plat(pdev);
+ dsim->dev = &pdev->dev;
+ dsim->id = pdev->id;
+
+ /* get mipi_dsim_platform_data. */
+ dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
+ if (dsim_pd = NULL) {
+ dev_err(&pdev->dev, "failed to get platform data for dsim.\n");
+ goto err_clock_get;
+ }
+ /* get mipi_dsim_config. */
+ dsim_config = dsim_pd->dsim_config;
+ if (dsim_config = NULL) {
+ dev_err(&pdev->dev, "failed to get dsim config data.\n");
+ goto err_clock_get;
+ }
+
+ dsim->dsim_config = dsim_config;
+ dsim->master_ops = &master_ops;
+
+ mutex_init(&dsim->lock);
+
+ ret = regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies), supplies);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret);
+ goto err_clock_get;
+ }
+
+ dsim->clock = clk_get(&pdev->dev, "dsim0");
+ if (IS_ERR(dsim->clock)) {
+ dev_err(&pdev->dev, "failed to get dsim clock source\n");
+ goto err_clock_get;
+ }
+
+ clk_enable(dsim->clock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get io memory region\n");
+ goto err_platform_get;
+ }
+
+ dsim->res = request_mem_region(res->start, resource_size(res),
+ dev_name(&pdev->dev));
+ if (!dsim->res) {
+ dev_err(&pdev->dev, "failed to request io memory region\n");
+ ret = -ENOMEM;
+ goto err_mem_region;
+ }
+
+ dsim->reg_base = ioremap(res->start, resource_size(res));
+ if (!dsim->reg_base) {
+ dev_err(&pdev->dev, "failed to remap io region\n");
+ ret = -ENOMEM;
+ goto err_ioremap;
+ }
+
+ mutex_init(&dsim->lock);
+
+ /* bind lcd ddi matched with panel name. */
+ dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
+ if (!dsim_ddi) {
+ dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
+ goto err_bind;
+ }
+
+ dsim->irq = platform_get_irq(pdev, 0);
+ if (dsim->irq < 0) {
+ dev_err(&pdev->dev, "failed to request dsim irq resource\n");
+ ret = -EINVAL;
+ goto err_platform_get_irq;
+ }
+
+ ret = request_irq(dsim->irq, exynos_mipi_dsi_interrupt_handler,
+ IRQF_SHARED, pdev->name, dsim);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "failed to request dsim irq\n");
+ ret = -EINVAL;
+ goto err_bind;
+ }
+
+ init_completion(&dsim_wr_comp);
+ init_completion(&dsim_rd_comp);
+
+ /* enable interrupt */
+ exynos_mipi_dsi_init_interrupt(dsim);
+
+ /* initialize mipi-dsi client(lcd panel). */
+ if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe)
+ dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev);
+
+ /* in case that mipi got enabled at bootloader. */
+ if (dsim_pd->enabled)
+ goto out;
+
+ /* lcd panel power on. */
+ if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on)
+ dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev, 1);
+
+ exynos_mipi_regulator_enable(dsim);
+
+ /* enable MIPI-DSI PHY. */
+ if (dsim->pd->phy_enable)
+ dsim->pd->phy_enable(pdev, true);
+
+ exynos_mipi_update_cfg(dsim);
+
+ /* set lcd panel sequence commands. */
+ if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->set_sequence)
+ dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev);
+
+ dsim->suspended = false;
+
+out:
+ platform_set_drvdata(pdev, dsim);
+
+ dev_dbg(&pdev->dev, "mipi-dsi driver(%s mode) has been probed.\n",
+ (dsim_config->e_interface = DSIM_COMMAND) ?
+ "CPU" : "RGB");
+
+ return 0;
+
+err_bind:
+ iounmap(dsim->reg_base);
+
+err_ioremap:
+ release_mem_region(dsim->res->start, resource_size(dsim->res));
+
+err_mem_region:
+ release_resource(dsim->res);
+
+err_platform_get:
+ clk_disable(dsim->clock);
+ clk_put(dsim->clock);
+err_clock_get:
+ kfree(dsim);
+
+err_platform_get_irq:
+ return ret;
+}
+
+static int __devexit exynos_mipi_dsi_remove(struct platform_device *pdev)
+{
+ struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
+ struct mipi_dsim_ddi *dsim_ddi, *next;
+ struct mipi_dsim_lcd_driver *dsim_lcd_drv;
+
+ iounmap(dsim->reg_base);
+
+ clk_disable(dsim->clock);
+ clk_put(dsim->clock);
+
+ release_resource(dsim->res);
+ release_mem_region(dsim->res->start, resource_size(dsim->res));
+
+ list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
+ if (dsim_ddi) {
+ if (dsim->id != dsim_ddi->bus_id)
+ continue;
+
+ dsim_lcd_drv = dsim_ddi->dsim_lcd_drv;
+
+ if (dsim_lcd_drv->remove)
+ dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev);
+
+ kfree(dsim_ddi);
+ }
+ }
+
+ regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
+ kfree(dsim);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int exynos_mipi_dsi_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
+ struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
+ struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
+
+ disable_irq(dsim->irq);
+
+ if (dsim->suspended)
+ return 0;
+
+ if (client_drv && client_drv->suspend)
+ client_drv->suspend(client_dev);
+
+ /* enable MIPI-DSI PHY. */
+ if (dsim->pd->phy_enable)
+ dsim->pd->phy_enable(pdev, false);
+
+ clk_disable(dsim->clock);
+
+ exynos_mipi_regulator_disable(dsim);
+
+ dsim->suspended = true;
+
+ return 0;
+}
+
+static int exynos_mipi_dsi_resume(struct platform_device *pdev)
+{
+ struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
+ struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
+ struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
+
+ enable_irq(dsim->irq);
+
+ if (!dsim->suspended)
+ return 0;
+
+ /* lcd panel power on. */
+ if (client_drv && client_drv->power_on)
+ client_drv->power_on(client_dev, 1);
+
+ exynos_mipi_regulator_enable(dsim);
+
+ /* enable MIPI-DSI PHY. */
+ if (dsim->pd->phy_enable)
+ dsim->pd->phy_enable(pdev, true);
+
+ clk_enable(dsim->clock);
+
+ exynos_mipi_update_cfg(dsim);
+
+ /* set lcd panel sequence commands. */
+ if (client_drv && client_drv->set_sequence)
+ client_drv->set_sequence(client_dev);
+
+ dsim->suspended = false;
+
+ return 0;
+}
+#else
+#define exynos_mipi_dsi_suspend NULL
+#define exynos_mipi_dsi_resume NULL
+#endif
+
+static struct platform_driver exynos_mipi_dsi_driver = {
+ .probe = exynos_mipi_dsi_probe,
+ .remove = __devexit_p(exynos_mipi_dsi_remove),
+ .suspend = exynos_mipi_dsi_suspend,
+ .resume = exynos_mipi_dsi_resume,
+ .driver = {
+ .name = "exynos-mipi-dsim",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(exynos_mipi_dsi_driver);
+
+MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samusung SoC MIPI-DSI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c
new file mode 100644
index 0000000..14909c1
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_common.c
@@ -0,0 +1,896 @@
+/* linux/drivers/video/exynos/exynos_mipi_dsi_common.c
+ *
+ * Samsung SoC MIPI-DSI common driver.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae, <inki.dae@samsung.com>
+ * Donghwa Lee, <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/ctype.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/memory.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+
+#include <video/mipi_display.h>
+#include <video/exynos_mipi_dsim.h>
+
+#include <mach/map.h>
+
+#include "exynos_mipi_dsi_regs.h"
+#include "exynos_mipi_dsi_lowlevel.h"
+#include "exynos_mipi_dsi_common.h"
+
+#define MIPI_FIFO_TIMEOUT msecs_to_jiffies(250)
+#define MIPI_RX_FIFO_READ_DONE 0x30800002
+#define MIPI_MAX_RX_FIFO 20
+#define MHZ (1000 * 1000)
+#define FIN_HZ (24 * MHZ)
+
+#define DFIN_PLL_MIN_HZ (6 * MHZ)
+#define DFIN_PLL_MAX_HZ (12 * MHZ)
+
+#define DFVCO_MIN_HZ (500 * MHZ)
+#define DFVCO_MAX_HZ (1000 * MHZ)
+
+#define TRY_GET_FIFO_TIMEOUT (5000 * 2)
+#define TRY_FIFO_CLEAR (10)
+
+/* MIPI-DSIM status types. */
+enum {
+ DSIM_STATE_INIT, /* should be initialized. */
+ DSIM_STATE_STOP, /* CPU and LCDC are LP mode. */
+ DSIM_STATE_HSCLKEN, /* HS clock was enabled. */
+ DSIM_STATE_ULPS
+};
+
+/* define DSI lane types. */
+enum {
+ DSIM_LANE_CLOCK = (1 << 0),
+ DSIM_LANE_DATA0 = (1 << 1),
+ DSIM_LANE_DATA1 = (1 << 2),
+ DSIM_LANE_DATA2 = (1 << 3),
+ DSIM_LANE_DATA3 = (1 << 4)
+};
+
+static unsigned int dpll_table[15] = {
+ 100, 120, 170, 220, 270,
+ 320, 390, 450, 510, 560,
+ 640, 690, 770, 870, 950
+};
+
+irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id)
+{
+ unsigned int intsrc = 0;
+ unsigned int intmsk = 0;
+ struct mipi_dsim_device *dsim = NULL;
+
+ dsim = dev_id;
+ if (!dsim) {
+ dev_dbg(dsim->dev, KERN_ERR "%s:error: wrong parameter\n",
+ __func__);
+ return IRQ_HANDLED;
+ }
+
+ intsrc = exynos_mipi_dsi_read_interrupt(dsim);
+ intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim);
+
+ intmsk = ~(intmsk) & intsrc;
+
+ switch (intmsk) {
+ case INTMSK_RX_DONE:
+ complete(&dsim_rd_comp);
+ dev_dbg(dsim->dev, "MIPI INTMSK_RX_DONE\n");
+ break;
+ case INTMSK_FIFO_EMPTY:
+ complete(&dsim_wr_comp);
+ dev_dbg(dsim->dev, "MIPI INTMSK_FIFO_EMPTY\n");
+ break;
+ default:
+ break;
+ }
+
+ exynos_mipi_dsi_clear_interrupt(dsim, intmsk);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * write long packet to mipi dsi slave
+ * @dsim: mipi dsim device structure.
+ * @data0: packet data to send.
+ * @data1: size of packet data
+ */
+static void exynos_mipi_dsi_long_data_wr(struct mipi_dsim_device *dsim,
+ const unsigned char *data0, unsigned int data_size)
+{
+ unsigned int data_cnt = 0, payload = 0;
+
+ /* in case that data count is more then 4 */
+ for (data_cnt = 0; data_cnt < data_size; data_cnt += 4) {
+ /*
+ * after sending 4bytes per one time,
+ * send remainder data less then 4.
+ */
+ if ((data_size - data_cnt) < 4) {
+ if ((data_size - data_cnt) = 3) {
+ payload = data0[data_cnt] |
+ data0[data_cnt + 1] << 8 |
+ data0[data_cnt + 2] << 16;
+ dev_dbg(dsim->dev, "count = 3 payload = %x, %x %x %x\n",
+ payload, data0[data_cnt],
+ data0[data_cnt + 1],
+ data0[data_cnt + 2]);
+ } else if ((data_size - data_cnt) = 2) {
+ payload = data0[data_cnt] |
+ data0[data_cnt + 1] << 8;
+ dev_dbg(dsim->dev,
+ "count = 2 payload = %x, %x %x\n", payload,
+ data0[data_cnt],
+ data0[data_cnt + 1]);
+ } else if ((data_size - data_cnt) = 1) {
+ payload = data0[data_cnt];
+ }
+
+ exynos_mipi_dsi_wr_tx_data(dsim, payload);
+ /* send 4bytes per one time. */
+ } else {
+ payload = data0[data_cnt] |
+ data0[data_cnt + 1] << 8 |
+ data0[data_cnt + 2] << 16 |
+ data0[data_cnt + 3] << 24;
+
+ dev_dbg(dsim->dev,
+ "count = 4 payload = %x, %x %x %x %x\n",
+ payload, *(u8 *)(data0 + data_cnt),
+ data0[data_cnt + 1],
+ data0[data_cnt + 2],
+ data0[data_cnt + 3]);
+
+ exynos_mipi_dsi_wr_tx_data(dsim, payload);
+ }
+ }
+}
+
+int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
+ const unsigned char *data0, unsigned int data_size)
+{
+ unsigned int check_rx_ack = 0;
+
+ if (dsim->state = DSIM_STATE_ULPS) {
+ dev_err(dsim->dev, "state is ULPS.\n");
+
+ return -EINVAL;
+ }
+
+ /* FIXME!!! why does it need this delay? */
+ msleep(20);
+
+ mutex_lock(&dsim->lock);
+
+ switch (data_id) {
+ /* short packet types of packet types for command. */
+ case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
+ case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
+ case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
+ case MIPI_DSI_DCS_SHORT_WRITE:
+ case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+ case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
+ exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);
+ if (check_rx_ack) {
+ /* process response func should be implemented */
+ mutex_unlock(&dsim->lock);
+ return 0;
+ } else {
+ mutex_unlock(&dsim->lock);
+ return -EINVAL;
+ }
+
+ /* general command */
+ case MIPI_DSI_COLOR_MODE_OFF:
+ case MIPI_DSI_COLOR_MODE_ON:
+ case MIPI_DSI_SHUTDOWN_PERIPHERAL:
+ case MIPI_DSI_TURN_ON_PERIPHERAL:
+ exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);
+ if (check_rx_ack) {
+ /* process response func should be implemented. */
+ mutex_unlock(&dsim->lock);
+ return 0;
+ } else {
+ mutex_unlock(&dsim->lock);
+ return -EINVAL;
+ }
+
+ /* packet types for video data */
+ case MIPI_DSI_V_SYNC_START:
+ case MIPI_DSI_V_SYNC_END:
+ case MIPI_DSI_H_SYNC_START:
+ case MIPI_DSI_H_SYNC_END:
+ case MIPI_DSI_END_OF_TRANSMISSION:
+ mutex_unlock(&dsim->lock);
+ return 0;
+
+ /* long packet type and null packet */
+ case MIPI_DSI_NULL_PACKET:
+ case MIPI_DSI_BLANKING_PACKET:
+ mutex_unlock(&dsim->lock);
+ return 0;
+ case MIPI_DSI_GENERIC_LONG_WRITE:
+ case MIPI_DSI_DCS_LONG_WRITE:
+ {
+ unsigned int size, payload = 0;
+ INIT_COMPLETION(dsim_wr_comp);
+
+ size = data_size * 4;
+
+ /* if data count is less then 4, then send 3bytes data. */
+ if (data_size < 4) {
+ payload = data0[0] |
+ data0[1] << 8 |
+ data0[2] << 16;
+
+ exynos_mipi_dsi_wr_tx_data(dsim, payload);
+
+ dev_dbg(dsim->dev, "count = %d payload = %x,%x %x %x\n",
+ data_size, payload, data0[0],
+ data0[1], data0[2]);
+
+ /* in case that data count is more then 4 */
+ } else
+ exynos_mipi_dsi_long_data_wr(dsim, data0, data_size);
+
+ /* put data into header fifo */
+ exynos_mipi_dsi_wr_tx_header(dsim, data_id, data_size & 0xff,
+ (data_size & 0xff00) >> 8);
+
+ if (!wait_for_completion_interruptible_timeout(&dsim_wr_comp,
+ MIPI_FIFO_TIMEOUT)) {
+ dev_warn(dsim->dev, "command write timeout.\n");
+ mutex_unlock(&dsim->lock);
+ return -EAGAIN;
+ }
+
+ if (check_rx_ack) {
+ /* process response func should be implemented. */
+ mutex_unlock(&dsim->lock);
+ return 0;
+ } else {
+ mutex_unlock(&dsim->lock);
+ return -EINVAL;
+ }
+ }
+
+ /* packet typo for video data */
+ case MIPI_DSI_PACKED_PIXEL_STREAM_16:
+ case MIPI_DSI_PACKED_PIXEL_STREAM_18:
+ case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
+ case MIPI_DSI_PACKED_PIXEL_STREAM_24:
+ if (check_rx_ack) {
+ /* process response func should be implemented. */
+ mutex_unlock(&dsim->lock);
+ return 0;
+ } else {
+ mutex_unlock(&dsim->lock);
+ return -EINVAL;
+ }
+ default:
+ dev_warn(dsim->dev,
+ "data id %x is not supported current DSI spec.\n",
+ data_id);
+
+ mutex_unlock(&dsim->lock);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&dsim->lock);
+ return 0;
+}
+
+static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device *dsim,
+ unsigned int req_size, unsigned int rx_data, u8 *rx_buf)
+{
+ unsigned int rcv_pkt, i, j;
+ u16 rxsize;
+
+ /* for long packet */
+ rxsize = (u16)((rx_data & 0x00ffff00) >> 8);
+ dev_dbg(dsim->dev, "mipi dsi rx size : %d\n", rxsize);
+ if (rxsize != req_size) {
+ dev_dbg(dsim->dev,
+ "received size mismatch received: %d, requested: %d\n",
+ rxsize, req_size);
+ goto err;
+ }
+
+ for (i = 0; i < (rxsize >> 2); i++) {
+ rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
+ dev_dbg(dsim->dev, "received pkt : %08x\n", rcv_pkt);
+ for (j = 0; j < 4; j++) {
+ rx_buf[(i * 4) + j] + (u8)(rcv_pkt >> (j * 8)) & 0xff;
+ dev_dbg(dsim->dev, "received value : %02x\n",
+ (rcv_pkt >> (j * 8)) & 0xff);
+ }
+ }
+ if (rxsize % 4) {
+ rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
+ dev_dbg(dsim->dev, "received pkt : %08x\n", rcv_pkt);
+ for (j = 0; j < (rxsize % 4); j++) {
+ rx_buf[(i * 4) + j] + (u8)(rcv_pkt >> (j * 8)) & 0xff;
+ dev_dbg(dsim->dev, "received value : %02x\n",
+ (rcv_pkt >> (j * 8)) & 0xff);
+ }
+ }
+
+ return rxsize;
+
+err:
+ return -EINVAL;
+}
+
+static unsigned int exynos_mipi_dsi_response_size(unsigned int req_size)
+{
+ switch (req_size) {
+ case 1:
+ return MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE;
+ case 2:
+ return MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE;
+ default:
+ return MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE;
+ }
+}
+
+int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
+ unsigned int data0, unsigned int req_size, u8 *rx_buf)
+{
+ unsigned int rx_data, rcv_pkt, i;
+ u8 response = 0;
+ u16 rxsize;
+
+ if (dsim->state = DSIM_STATE_ULPS) {
+ dev_err(dsim->dev, "state is ULPS.\n");
+
+ return -EINVAL;
+ }
+
+ /* FIXME!!! */
+ msleep(20);
+
+ mutex_lock(&dsim->lock);
+ INIT_COMPLETION(dsim_rd_comp);
+ exynos_mipi_dsi_rd_tx_header(dsim,
+ MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, req_size);
+
+ response = exynos_mipi_dsi_response_size(req_size);
+
+ switch (data_id) {
+ case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
+ case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
+ case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
+ case MIPI_DSI_DCS_READ:
+ exynos_mipi_dsi_rd_tx_header(dsim,
+ data_id, data0);
+ /* process response func should be implemented. */
+ break;
+ default:
+ dev_warn(dsim->dev,
+ "data id %x is not supported current DSI spec.\n",
+ data_id);
+
+ return -EINVAL;
+ }
+
+ if (!wait_for_completion_interruptible_timeout(&dsim_rd_comp,
+ MIPI_FIFO_TIMEOUT)) {
+ pr_err("RX done interrupt timeout\n");
+ mutex_unlock(&dsim->lock);
+ return 0;
+ }
+
+ msleep(20);
+
+ rx_data = exynos_mipi_dsi_rd_rx_fifo(dsim);
+
+ if ((u8)(rx_data & 0xff) != response) {
+ printk(KERN_ERR
+ "mipi dsi wrong response rx_data : %x, response:%x\n",
+ rx_data, response);
+ goto clear_rx_fifo;
+ }
+
+ if (req_size <= 2) {
+ /* for short packet */
+ for (i = 0; i < req_size; i++)
+ rx_buf[i] = (rx_data >> (8 + (i * 8))) & 0xff;
+ rxsize = req_size;
+ } else {
+ /* for long packet */
+ rxsize = exynos_mipi_dsi_long_data_rd(dsim, req_size, rx_data,
+ rx_buf);
+ if (rxsize != req_size)
+ goto clear_rx_fifo;
+ }
+
+ rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
+
+ msleep(20);
+
+ if (rcv_pkt != MIPI_RX_FIFO_READ_DONE) {
+ dev_info(dsim->dev,
+ "Can't found RX FIFO READ DONE FLAG : %x\n", rcv_pkt);
+ goto clear_rx_fifo;
+ }
+
+ mutex_unlock(&dsim->lock);
+
+ return rxsize;
+
+clear_rx_fifo:
+ i = 0;
+ while (1) {
+ rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
+ if ((rcv_pkt = MIPI_RX_FIFO_READ_DONE)
+ || (i > MIPI_MAX_RX_FIFO))
+ break;
+ dev_dbg(dsim->dev,
+ "mipi dsi clear rx fifo : %08x\n", rcv_pkt);
+ i++;
+ }
+ dev_info(dsim->dev,
+ "mipi dsi rx done count : %d, rcv_pkt : %08x\n", i, rcv_pkt);
+
+ mutex_unlock(&dsim->lock);
+
+ return 0;
+}
+
+static int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim,
+ unsigned int enable)
+{
+ int sw_timeout;
+
+ if (enable) {
+ sw_timeout = 1000;
+
+ exynos_mipi_dsi_enable_pll(dsim, 1);
+ while (1) {
+ sw_timeout--;
+ if (exynos_mipi_dsi_is_pll_stable(dsim))
+ return 0;
+ if (sw_timeout = 0)
+ return -EINVAL;
+ }
+ } else
+ exynos_mipi_dsi_enable_pll(dsim, 0);
+
+ return 0;
+}
+
+static unsigned long exynos_mipi_dsi_change_pll(struct mipi_dsim_device *dsim,
+ unsigned int pre_divider, unsigned int main_divider,
+ unsigned int scaler)
+{
+ unsigned long dfin_pll, dfvco, dpll_out;
+ unsigned int i, freq_band = 0xf;
+
+ dfin_pll = (FIN_HZ / pre_divider);
+
+ /******************************************************
+ * Serial Clock(=ByteClk X 8) FreqBand[3:0] *
+ ******************************************************
+ * ~ 99.99 MHz 0000
+ * 100 ~ 119.99 MHz 0001
+ * 120 ~ 159.99 MHz 0010
+ * 160 ~ 199.99 MHz 0011
+ * 200 ~ 239.99 MHz 0100
+ * 140 ~ 319.99 MHz 0101
+ * 320 ~ 389.99 MHz 0110
+ * 390 ~ 449.99 MHz 0111
+ * 450 ~ 509.99 MHz 1000
+ * 510 ~ 559.99 MHz 1001
+ * 560 ~ 639.99 MHz 1010
+ * 640 ~ 689.99 MHz 1011
+ * 690 ~ 769.99 MHz 1100
+ * 770 ~ 869.99 MHz 1101
+ * 870 ~ 949.99 MHz 1110
+ * 950 ~ 1000 MHz 1111
+ ******************************************************/
+ if (dfin_pll < DFIN_PLL_MIN_HZ || dfin_pll > DFIN_PLL_MAX_HZ) {
+ dev_warn(dsim->dev, "fin_pll range should be 6MHz ~ 12MHz\n");
+ exynos_mipi_dsi_enable_afc(dsim, 0, 0);
+ } else {
+ if (dfin_pll < 7 * MHZ)
+ exynos_mipi_dsi_enable_afc(dsim, 1, 0x1);
+ else if (dfin_pll < 8 * MHZ)
+ exynos_mipi_dsi_enable_afc(dsim, 1, 0x0);
+ else if (dfin_pll < 9 * MHZ)
+ exynos_mipi_dsi_enable_afc(dsim, 1, 0x3);
+ else if (dfin_pll < 10 * MHZ)
+ exynos_mipi_dsi_enable_afc(dsim, 1, 0x2);
+ else if (dfin_pll < 11 * MHZ)
+ exynos_mipi_dsi_enable_afc(dsim, 1, 0x5);
+ else
+ exynos_mipi_dsi_enable_afc(dsim, 1, 0x4);
+ }
+
+ dfvco = dfin_pll * main_divider;
+ dev_dbg(dsim->dev, "dfvco = %lu, dfin_pll = %lu, main_divider = %d\n",
+ dfvco, dfin_pll, main_divider);
+ if (dfvco < DFVCO_MIN_HZ || dfvco > DFVCO_MAX_HZ)
+ dev_warn(dsim->dev, "fvco range should be 500MHz ~ 1000MHz\n");
+
+ dpll_out = dfvco / (1 << scaler);
+ dev_dbg(dsim->dev, "dpll_out = %lu, dfvco = %lu, scaler = %d\n",
+ dpll_out, dfvco, scaler);
+
+ for (i = 0; i < ARRAY_SIZE(dpll_table); i++) {
+ if (dpll_out < dpll_table[i] * MHZ) {
+ freq_band = i;
+ break;
+ }
+ }
+
+ dev_dbg(dsim->dev, "freq_band = %d\n", freq_band);
+
+ exynos_mipi_dsi_pll_freq(dsim, pre_divider, main_divider, scaler);
+
+ exynos_mipi_dsi_hs_zero_ctrl(dsim, 0);
+ exynos_mipi_dsi_prep_ctrl(dsim, 0);
+
+ /* Freq Band */
+ exynos_mipi_dsi_pll_freq_band(dsim, freq_band);
+
+ /* Stable time */
+ exynos_mipi_dsi_pll_stable_time(dsim, dsim->dsim_config->pll_stable_time);
+
+ /* Enable PLL */
+ dev_dbg(dsim->dev, "FOUT of mipi dphy pll is %luMHz\n",
+ (dpll_out / MHZ));
+
+ return dpll_out;
+}
+
+static int exynos_mipi_dsi_set_clock(struct mipi_dsim_device *dsim,
+ unsigned int byte_clk_sel, unsigned int enable)
+{
+ unsigned int esc_div;
+ unsigned long esc_clk_error_rate;
+ unsigned long hs_clk = 0, byte_clk = 0, escape_clk = 0;
+
+ if (enable) {
+ dsim->e_clk_src = byte_clk_sel;
+
+ /* Escape mode clock and byte clock source */
+ exynos_mipi_dsi_set_byte_clock_src(dsim, byte_clk_sel);
+
+ /* DPHY, DSIM Link : D-PHY clock out */
+ if (byte_clk_sel = DSIM_PLL_OUT_DIV8) {
+ hs_clk = exynos_mipi_dsi_change_pll(dsim,
+ dsim->dsim_config->p, dsim->dsim_config->m,
+ dsim->dsim_config->s);
+ if (hs_clk = 0) {
+ dev_err(dsim->dev,
+ "failed to get hs clock.\n");
+ return -EINVAL;
+ }
+
+ byte_clk = hs_clk / 8;
+ exynos_mipi_dsi_enable_pll_bypass(dsim, 0);
+ exynos_mipi_dsi_pll_on(dsim, 1);
+ /* DPHY : D-PHY clock out, DSIM link : external clock out */
+ } else if (byte_clk_sel = DSIM_EXT_CLK_DIV8) {
+ dev_warn(dsim->dev, "this project is not support\n");
+ dev_warn(dsim->dev,
+ "external clock source for MIPI DSIM.\n");
+ } else if (byte_clk_sel = DSIM_EXT_CLK_BYPASS) {
+ dev_warn(dsim->dev, "this project is not support\n");
+ dev_warn(dsim->dev,
+ "external clock source for MIPI DSIM\n");
+ }
+
+ /* escape clock divider */
+ esc_div = byte_clk / (dsim->dsim_config->esc_clk);
+ dev_dbg(dsim->dev,
+ "esc_div = %d, byte_clk = %lu, esc_clk = %lu\n",
+ esc_div, byte_clk, dsim->dsim_config->esc_clk);
+ if ((byte_clk / esc_div) >= (20 * MHZ) ||
+ (byte_clk / esc_div) >
+ dsim->dsim_config->esc_clk)
+ esc_div += 1;
+
+ escape_clk = byte_clk / esc_div;
+ dev_dbg(dsim->dev,
+ "escape_clk = %lu, byte_clk = %lu, esc_div = %d\n",
+ escape_clk, byte_clk, esc_div);
+
+ /* enable escape clock. */
+ exynos_mipi_dsi_enable_byte_clock(dsim, 1);
+
+ /* enable byte clk and escape clock */
+ exynos_mipi_dsi_set_esc_clk_prs(dsim, 1, esc_div);
+ /* escape clock on lane */
+ exynos_mipi_dsi_enable_esc_clk_on_lane(dsim,
+ (DSIM_LANE_CLOCK | dsim->data_lane), 1);
+
+ dev_dbg(dsim->dev, "byte clock is %luMHz\n",
+ (byte_clk / MHZ));
+ dev_dbg(dsim->dev, "escape clock that user's need is %lu\n",
+ (dsim->dsim_config->esc_clk / MHZ));
+ dev_dbg(dsim->dev, "escape clock divider is %x\n", esc_div);
+ dev_dbg(dsim->dev, "escape clock is %luMHz\n",
+ ((byte_clk / esc_div) / MHZ));
+
+ if ((byte_clk / esc_div) > escape_clk) {
+ esc_clk_error_rate = escape_clk /
+ (byte_clk / esc_div);
+ dev_warn(dsim->dev, "error rate is %lu over.\n",
+ (esc_clk_error_rate / 100));
+ } else if ((byte_clk / esc_div) < (escape_clk)) {
+ esc_clk_error_rate = (byte_clk / esc_div) /
+ escape_clk;
+ dev_warn(dsim->dev, "error rate is %lu under.\n",
+ (esc_clk_error_rate / 100));
+ }
+ } else {
+ exynos_mipi_dsi_enable_esc_clk_on_lane(dsim,
+ (DSIM_LANE_CLOCK | dsim->data_lane), 0);
+ exynos_mipi_dsi_set_esc_clk_prs(dsim, 0, 0);
+
+ /* disable escape clock. */
+ exynos_mipi_dsi_enable_byte_clock(dsim, 0);
+
+ if (byte_clk_sel = DSIM_PLL_OUT_DIV8)
+ exynos_mipi_dsi_pll_on(dsim, 0);
+ }
+
+ return 0;
+}
+
+int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim)
+{
+ dsim->state = DSIM_STATE_INIT;
+
+ switch (dsim->dsim_config->e_no_data_lane) {
+ case DSIM_DATA_LANE_1:
+ dsim->data_lane = DSIM_LANE_DATA0;
+ break;
+ case DSIM_DATA_LANE_2:
+ dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1;
+ break;
+ case DSIM_DATA_LANE_3:
+ dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
+ DSIM_LANE_DATA2;
+ break;
+ case DSIM_DATA_LANE_4:
+ dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
+ DSIM_LANE_DATA2 | DSIM_LANE_DATA3;
+ break;
+ default:
+ dev_info(dsim->dev, "data lane is invalid.\n");
+ return -EINVAL;
+ };
+
+ exynos_mipi_dsi_sw_reset(dsim);
+ exynos_mipi_dsi_func_reset(dsim);
+
+ exynos_mipi_dsi_dp_dn_swap(dsim, 0);
+
+ return 0;
+}
+
+void exynos_mipi_dsi_init_interrupt(struct mipi_dsim_device *dsim)
+{
+ unsigned int src = 0;
+
+ src = (INTSRC_SFR_FIFO_EMPTY | INTSRC_RX_DATA_DONE);
+ exynos_mipi_dsi_set_interrupt(dsim, src, 1);
+
+ src = 0;
+ src = ~(INTMSK_RX_DONE | INTMSK_FIFO_EMPTY);
+ exynos_mipi_dsi_set_interrupt_mask(dsim, src, 1);
+}
+
+int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim,
+ unsigned int enable)
+{
+ /* enable only frame done interrupt */
+ exynos_mipi_dsi_set_interrupt_mask(dsim, INTMSK_FRAME_DONE, enable);
+
+ return 0;
+}
+
+void exynos_mipi_dsi_stand_by(struct mipi_dsim_device *dsim,
+ unsigned int enable)
+{
+
+ /* consider Main display and Sub display. */
+
+ exynos_mipi_dsi_set_main_stand_by(dsim, enable);
+}
+
+int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim,
+ struct mipi_dsim_config *dsim_config)
+{
+ struct mipi_dsim_platform_data *dsim_pd;
+ struct fb_videomode *timing;
+
+ dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
+ timing = (struct fb_videomode *)dsim_pd->lcd_panel_info;
+
+ /* in case of VIDEO MODE (RGB INTERFACE), it sets polarities. */
+ if (dsim_config->e_interface = (u32) DSIM_VIDEO) {
+ if (dsim_config->auto_vertical_cnt = 0) {
+ exynos_mipi_dsi_set_main_disp_vporch(dsim,
+ dsim_config->cmd_allow,
+ timing->upper_margin,
+ timing->lower_margin);
+ exynos_mipi_dsi_set_main_disp_hporch(dsim,
+ timing->left_margin,
+ timing->right_margin);
+ exynos_mipi_dsi_set_main_disp_sync_area(dsim,
+ timing->vsync_len,
+ timing->hsync_len);
+ }
+ }
+
+ exynos_mipi_dsi_set_main_disp_resol(dsim, timing->xres,
+ timing->yres);
+
+ exynos_mipi_dsi_display_config(dsim, dsim_config);
+
+ dev_info(dsim->dev, "lcd panel => width = %d, height = %d\n",
+ timing->xres, timing->yres);
+
+ return 0;
+}
+
+int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim)
+{
+ unsigned int time_out = 100;
+
+ switch (dsim->state) {
+ case DSIM_STATE_INIT:
+ exynos_mipi_dsi_init_fifo_pointer(dsim, 0x1f);
+
+ /* dsi configuration */
+ exynos_mipi_dsi_init_config(dsim);
+ exynos_mipi_dsi_enable_lane(dsim, DSIM_LANE_CLOCK, 1);
+ exynos_mipi_dsi_enable_lane(dsim, dsim->data_lane, 1);
+
+ /* set clock configuration */
+ exynos_mipi_dsi_set_clock(dsim, dsim->dsim_config->e_byte_clk, 1);
+
+ /* check clock and data lane state are stop state */
+ while (!(exynos_mipi_dsi_is_lane_state(dsim))) {
+ time_out--;
+ if (time_out = 0) {
+ dev_err(dsim->dev,
+ "DSI Master is not stop state.\n");
+ dev_err(dsim->dev,
+ "Check initialization process\n");
+
+ return -EINVAL;
+ }
+ }
+ if (time_out != 0) {
+ dev_info(dsim->dev,
+ "DSI Master driver has been completed.\n");
+ dev_info(dsim->dev, "DSI Master state is stop state\n");
+ }
+
+ dsim->state = DSIM_STATE_STOP;
+
+ /* BTA sequence counters */
+ exynos_mipi_dsi_set_stop_state_counter(dsim,
+ dsim->dsim_config->stop_holding_cnt);
+ exynos_mipi_dsi_set_bta_timeout(dsim,
+ dsim->dsim_config->bta_timeout);
+ exynos_mipi_dsi_set_lpdr_timeout(dsim,
+ dsim->dsim_config->rx_timeout);
+
+ return 0;
+ default:
+ dev_info(dsim->dev, "DSI Master is already init.\n");
+ return 0;
+ }
+
+ return 0;
+}
+
+int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim)
+{
+ if (dsim->state != DSIM_STATE_STOP) {
+ dev_warn(dsim->dev, "DSIM is not in stop state.\n");
+ return 0;
+ }
+
+ if (dsim->e_clk_src = DSIM_EXT_CLK_BYPASS) {
+ dev_warn(dsim->dev, "clock source is external bypass.\n");
+ return 0;
+ }
+
+ dsim->state = DSIM_STATE_HSCLKEN;
+
+ /* set LCDC and CPU transfer mode to HS. */
+ exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0);
+ exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0);
+ exynos_mipi_dsi_enable_hs_clock(dsim, 1);
+
+ return 0;
+}
+
+int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim,
+ unsigned int mode)
+{
+ if (mode) {
+ if (dsim->state != DSIM_STATE_HSCLKEN) {
+ dev_err(dsim->dev, "HS Clock lane is not enabled.\n");
+ return -EINVAL;
+ }
+
+ exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0);
+ } else {
+ if (dsim->state = DSIM_STATE_INIT || dsim->state =
+ DSIM_STATE_ULPS) {
+ dev_err(dsim->dev,
+ "DSI Master is not STOP or HSDT state.\n");
+ return -EINVAL;
+ }
+
+ exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0);
+ }
+
+ return 0;
+}
+
+int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim)
+{
+ return _exynos_mipi_dsi_get_frame_done_status(dsim);
+}
+
+int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim)
+{
+ _exynos_mipi_dsi_clear_frame_done(dsim);
+
+ return 0;
+}
+
+int exynos_mipi_dsi_fifo_clear(struct mipi_dsim_device *dsim,
+ unsigned int val)
+{
+ int try = TRY_FIFO_CLEAR;
+
+ exynos_mipi_dsi_sw_reset_release(dsim);
+ exynos_mipi_dsi_func_reset(dsim);
+
+ do {
+ if (exynos_mipi_dsi_get_sw_reset_release(dsim)) {
+ exynos_mipi_dsi_init_interrupt(dsim);
+ dev_dbg(dsim->dev, "reset release done.\n");
+ return 0;
+ }
+ } while (--try);
+
+ dev_err(dsim->dev, "failed to clear dsim fifo.\n");
+ return -EAGAIN;
+}
+
+MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("Samusung SoC MIPI-DSI common driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.h b/drivers/video/exynos/exynos_mipi_dsi_common.h
new file mode 100644
index 0000000..4125522
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_common.h
@@ -0,0 +1,46 @@
+/* linux/drivers/video/exynos_mipi_dsi_common.h
+ *
+ * Header file for Samsung SoC MIPI-DSI common driver.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae <inki.dae@samsung.com>
+ * Donghwa Lee <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _EXYNOS_MIPI_DSI_COMMON_H
+#define _EXYNOS_MIPI_DSI_COMMON_H
+
+static DECLARE_COMPLETION(dsim_rd_comp);
+static DECLARE_COMPLETION(dsim_wr_comp);
+
+int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
+ const unsigned char *data0, unsigned int data_size);
+int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
+ unsigned int data0, unsigned int req_size, u8 *rx_buf);
+irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id);
+void exynos_mipi_dsi_init_interrupt(struct mipi_dsim_device *dsim);
+int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_stand_by(struct mipi_dsim_device *dsim,
+ unsigned int enable);
+int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim,
+ struct mipi_dsim_config *dsim_info);
+int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim);
+int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim);
+int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim,
+ unsigned int mode);
+int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim,
+ unsigned int enable);
+int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim);
+int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);
+
+extern struct fb_info *registered_fb[FB_MAX] __read_mostly;
+
+int exynos_mipi_dsi_fifo_clear(struct mipi_dsim_device *dsim,
+ unsigned int val);
+
+#endif /* _EXYNOS_MIPI_DSI_COMMON_H */
diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
new file mode 100644
index 0000000..0ef38ce
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
@@ -0,0 +1,618 @@
+/* linux/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
+ *
+ * Samsung SoC MIPI-DSI lowlevel driver.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae, <inki.dae@samsung.com>
+ * Donghwa Lee, <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+
+#include <video/exynos_mipi_dsim.h>
+
+#include <mach/map.h>
+
+#include "exynos_mipi_dsi_regs.h"
+
+void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim)
+{
+ unsigned int reg;
+
+ reg = readl(dsim->reg_base + EXYNOS_DSIM_SWRST);
+
+ reg |= DSIM_FUNCRST;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_SWRST);
+}
+
+void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim)
+{
+ unsigned int reg;
+
+ reg = readl(dsim->reg_base + EXYNOS_DSIM_SWRST);
+
+ reg |= DSIM_SWRST;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_SWRST);
+}
+
+void exynos_mipi_dsi_sw_reset_release(struct mipi_dsim_device *dsim)
+{
+ unsigned int reg;
+
+ reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
+
+ reg |= INTSRC_SW_RST_RELEASE;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
+}
+
+int exynos_mipi_dsi_get_sw_reset_release(struct mipi_dsim_device *dsim)
+{
+ return (readl(dsim->reg_base + EXYNOS_DSIM_INTSRC)) &
+ INTSRC_SW_RST_RELEASE;
+}
+
+unsigned int exynos_mipi_dsi_read_interrupt_mask(struct mipi_dsim_device *dsim)
+{
+ unsigned int reg;
+
+ reg = readl(dsim->reg_base + EXYNOS_DSIM_INTMSK);
+
+ return reg;
+}
+
+void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim,
+ unsigned int mode, unsigned int mask)
+{
+ unsigned int reg = 0;
+
+ if (mask)
+ reg |= mode;
+ else
+ reg &= ~mode;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_INTMSK);
+}
+
+void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim,
+ unsigned int cfg)
+{
+ unsigned int reg;
+
+ reg = readl(dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
+
+ writel(reg & ~(cfg), dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
+ mdelay(10);
+ reg |= cfg;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
+}
+
+/*
+ * this function set PLL P, M and S value in D-PHY
+ */
+void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
+ unsigned int value)
+{
+ writel(DSIM_AFC_CTL(value), dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
+}
+
+void exynos_mipi_dsi_set_main_stand_by(struct mipi_dsim_device *dsim,
+ unsigned int enable)
+{
+ unsigned int reg;
+
+ reg = readl(dsim->reg_base + EXYNOS_DSIM_MDRESOL);
+
+ reg &= ~DSIM_MAIN_STAND_BY;
+
+ if (enable)
+ reg |= DSIM_MAIN_STAND_BY;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
+}
+
+void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim,
+ unsigned int width_resol, unsigned int height_resol)
+{
+ unsigned int reg;
+
+ /* standby should be set after configuration so set to not ready*/
+ reg = (readl(dsim->reg_base + EXYNOS_DSIM_MDRESOL)) &
+ ~(DSIM_MAIN_STAND_BY);
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
+
+ reg &= ~((0x7ff << 16) | (0x7ff << 0));
+ reg |= DSIM_MAIN_VRESOL(height_resol) | DSIM_MAIN_HRESOL(width_resol);
+
+ reg |= DSIM_MAIN_STAND_BY;
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
+}
+
+void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim,
+ unsigned int cmd_allow, unsigned int vfront, unsigned int vback)
+{
+ unsigned int reg;
+
+ reg = (readl(dsim->reg_base + EXYNOS_DSIM_MVPORCH)) &
+ ~((DSIM_CMD_ALLOW_MASK) | (DSIM_STABLE_VFP_MASK) |
+ (DSIM_MAIN_VBP_MASK));
+
+ reg |= (DSIM_CMD_ALLOW_SHIFT(cmd_allow & 0xf) |
+ DSIM_STABLE_VFP_SHIFT(vfront & 0x7ff) |
+ DSIM_MAIN_VBP_SHIFT(vback & 0x7ff));
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_MVPORCH);
+}
+
+void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim,
+ unsigned int front, unsigned int back)
+{
+ unsigned int reg;
+
+ reg = (readl(dsim->reg_base + EXYNOS_DSIM_MHPORCH)) &
+ ~((DSIM_MAIN_HFP_MASK) | (DSIM_MAIN_HBP_MASK));
+
+ reg |= DSIM_MAIN_HFP_SHIFT(front) | DSIM_MAIN_HBP_SHIFT(back);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_MHPORCH);
+}
+
+void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim,
+ unsigned int vert, unsigned int hori)
+{
+ unsigned int reg;
+
+ reg = (readl(dsim->reg_base + EXYNOS_DSIM_MSYNC)) &
+ ~((DSIM_MAIN_VSA_MASK) | (DSIM_MAIN_HSA_MASK));
+
+ reg |= (DSIM_MAIN_VSA_SHIFT(vert & 0x3ff) |
+ DSIM_MAIN_HSA_SHIFT(hori));
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_MSYNC);
+}
+
+void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim,
+ unsigned int vert, unsigned int hori)
+{
+ unsigned int reg;
+
+ reg = (readl(dsim->reg_base + EXYNOS_DSIM_SDRESOL)) &
+ ~(DSIM_SUB_STANDY_MASK);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
+
+ reg &= ~(DSIM_SUB_VRESOL_MASK) | ~(DSIM_SUB_HRESOL_MASK);
+ reg |= (DSIM_SUB_VRESOL_SHIFT(vert & 0x7ff) |
+ DSIM_SUB_HRESOL_SHIFT(hori & 0x7ff));
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
+
+ reg |= DSIM_SUB_STANDY_SHIFT(1);
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
+}
+
+void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim)
+{
+ struct mipi_dsim_config *dsim_config = dsim->dsim_config;
+
+ unsigned int cfg = (readl(dsim->reg_base + EXYNOS_DSIM_CONFIG)) &
+ ~((1 << 28) | (0x1f << 20) | (0x3 << 5));
+
+ cfg = ((DSIM_AUTO_FLUSH(dsim_config->auto_flush)) |
+ (DSIM_EOT_DISABLE(dsim_config->eot_disable)) |
+ (DSIM_AUTO_MODE_SHIFT(dsim_config->auto_vertical_cnt)) |
+ (DSIM_HSE_MODE_SHIFT(dsim_config->hse)) |
+ (DSIM_HFP_MODE_SHIFT(dsim_config->hfp)) |
+ (DSIM_HBP_MODE_SHIFT(dsim_config->hbp)) |
+ (DSIM_HSA_MODE_SHIFT(dsim_config->hsa)) |
+ (DSIM_NUM_OF_DATALANE_SHIFT(dsim_config->e_no_data_lane)));
+
+ writel(cfg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
+}
+
+void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim,
+ struct mipi_dsim_config *dsim_config)
+{
+ u32 reg = (readl(dsim->reg_base + EXYNOS_DSIM_CONFIG)) &
+ ~((0x3 << 26) | (1 << 25) | (0x3 << 18) | (0x7 << 12) |
+ (0x3 << 16) | (0x7 << 8));
+
+ if (dsim_config->e_interface = DSIM_VIDEO)
+ reg |= (1 << 25);
+ else if (dsim_config->e_interface = DSIM_COMMAND)
+ reg &= ~(1 << 25);
+ else {
+ dev_err(dsim->dev, "unknown lcd type.\n");
+ return;
+ }
+
+ /* main lcd */
+ reg |= ((u8) (dsim_config->e_burst_mode) & 0x3) << 26 |
+ ((u8) (dsim_config->e_virtual_ch) & 0x3) << 18 |
+ ((u8) (dsim_config->e_pixel_format) & 0x7) << 12;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
+}
+
+void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, unsigned int lane,
+ unsigned int enable)
+{
+ unsigned int reg;
+
+ reg = readl(dsim->reg_base + EXYNOS_DSIM_CONFIG);
+
+ if (enable)
+ reg |= DSIM_LANE_ENx(lane);
+ else
+ reg &= ~DSIM_LANE_ENx(lane);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
+}
+
+
+void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
+ unsigned int count)
+{
+ unsigned int cfg;
+
+ /* get the data lane number. */
+ cfg = DSIM_NUM_OF_DATALANE_SHIFT(count);
+
+ writel(cfg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
+}
+
+void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, unsigned int enable,
+ unsigned int afc_code)
+{
+ unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
+
+ if (enable) {
+ reg |= (1 << 14);
+ reg &= ~(0x7 << 5);
+ reg |= (afc_code & 0x7) << 5;
+ } else
+ reg &= ~(1 << 14);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
+}
+
+void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim,
+ unsigned int enable)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
+ ~(DSIM_PLL_BYPASS_SHIFT(0x1));
+
+ reg |= DSIM_PLL_BYPASS_SHIFT(enable);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+}
+
+void exynos_mipi_dsi_set_pll_pms(struct mipi_dsim_device *dsim, unsigned int p,
+ unsigned int m, unsigned int s)
+{
+ unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+
+ reg |= ((p & 0x3f) << 13) | ((m & 0x1ff) << 4) | ((s & 0x7) << 1);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+}
+
+void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim,
+ unsigned int freq_band)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
+ ~(DSIM_FREQ_BAND_SHIFT(0x1f));
+
+ reg |= DSIM_FREQ_BAND_SHIFT(freq_band & 0x1f);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+}
+
+void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim,
+ unsigned int pre_divider, unsigned int main_divider,
+ unsigned int scaler)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
+ ~(0x7ffff << 1);
+
+ reg |= (pre_divider & 0x3f) << 13 | (main_divider & 0x1ff) << 4 |
+ (scaler & 0x7) << 1;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+}
+
+void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim,
+ unsigned int lock_time)
+{
+ writel(lock_time, dsim->reg_base + EXYNOS_DSIM_PLLTMR);
+}
+
+void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim, unsigned int enable)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
+ ~(DSIM_PLL_EN_SHIFT(0x1));
+
+ reg |= DSIM_PLL_EN_SHIFT(enable & 0x1);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+}
+
+void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim,
+ unsigned int src)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
+ ~(DSIM_BYTE_CLK_SRC_SHIFT(0x3));
+
+ reg |= (DSIM_BYTE_CLK_SRC_SHIFT(src));
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+}
+
+void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim,
+ unsigned int enable)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
+ ~(DSIM_BYTE_CLKEN_SHIFT(0x1));
+
+ reg |= DSIM_BYTE_CLKEN_SHIFT(enable);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+}
+
+void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim,
+ unsigned int enable, unsigned int prs_val)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
+ ~(DSIM_ESC_CLKEN_SHIFT(0x1) | 0xffff);
+
+ reg |= DSIM_ESC_CLKEN_SHIFT(enable);
+ if (enable)
+ reg |= prs_val;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+}
+
+void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim,
+ unsigned int lane_sel, unsigned int enable)
+{
+ unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+
+ if (enable)
+ reg |= DSIM_LANE_ESC_CLKEN(lane_sel);
+ else
+
+ reg &= ~DSIM_LANE_ESC_CLKEN(lane_sel);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+}
+
+void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim,
+ unsigned int enable)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE)) &
+ ~(DSIM_FORCE_STOP_STATE_SHIFT(0x1));
+
+ reg |= (DSIM_FORCE_STOP_STATE_SHIFT(enable & 0x1));
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
+}
+
+unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim)
+{
+ unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_STATUS);
+
+ /**
+ * check clock and data lane states.
+ * if MIPI-DSI controller was enabled at bootloader then
+ * TX_READY_HS_CLK is enabled otherwise STOP_STATE_CLK.
+ * so it should be checked for two case.
+ */
+ if ((reg & DSIM_STOP_STATE_DAT(0xf)) &&
+ ((reg & DSIM_STOP_STATE_CLK) ||
+ (reg & DSIM_TX_READY_HS_CLK)))
+ return 1;
+
+ return 0;
+}
+
+void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim,
+ unsigned int cnt_val)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE)) &
+ ~(DSIM_STOP_STATE_CNT_SHIFT(0x7ff));
+
+ reg |= (DSIM_STOP_STATE_CNT_SHIFT(cnt_val & 0x7ff));
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
+}
+
+void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim,
+ unsigned int timeout)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_TIMEOUT)) &
+ ~(DSIM_BTA_TOUT_SHIFT(0xff));
+
+ reg |= (DSIM_BTA_TOUT_SHIFT(timeout));
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_TIMEOUT);
+}
+
+void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim,
+ unsigned int timeout)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_TIMEOUT)) &
+ ~(DSIM_LPDR_TOUT_SHIFT(0xffff));
+
+ reg |= (DSIM_LPDR_TOUT_SHIFT(timeout));
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_TIMEOUT);
+}
+
+void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim,
+ unsigned int lp)
+{
+ unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE);
+
+ reg &= ~DSIM_CMD_LPDT_LP;
+
+ if (lp)
+ reg |= DSIM_CMD_LPDT_LP;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
+}
+
+void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim,
+ unsigned int lp)
+{
+ unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE);
+
+ reg &= ~DSIM_TX_LPDT_LP;
+
+ if (lp)
+ reg |= DSIM_TX_LPDT_LP;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
+}
+
+void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim,
+ unsigned int enable)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
+ ~(DSIM_TX_REQUEST_HSCLK_SHIFT(0x1));
+
+ reg |= DSIM_TX_REQUEST_HSCLK_SHIFT(enable);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
+}
+
+void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim,
+ unsigned int swap_en)
+{
+ unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PHYACCHR1);
+
+ reg &= ~(0x3 << 0);
+ reg |= (swap_en & 0x3) << 0;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_PHYACCHR1);
+}
+
+void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
+ unsigned int hs_zero)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
+ ~(0xf << 28);
+
+ reg |= ((hs_zero & 0xf) << 28);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+}
+
+void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep)
+{
+ unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
+ ~(0x7 << 20);
+
+ reg |= ((prep & 0x7) << 20);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
+}
+
+unsigned int exynos_mipi_dsi_read_interrupt(struct mipi_dsim_device *dsim)
+{
+ return readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
+}
+
+void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
+ unsigned int src)
+{
+ unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
+
+ reg |= src;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
+}
+
+void exynos_mipi_dsi_set_interrupt(struct mipi_dsim_device *dsim,
+ unsigned int src, unsigned int enable)
+{
+ unsigned int reg = 0;
+
+ if (enable)
+ reg |= src;
+ else
+ reg &= ~src;
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
+}
+
+unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim)
+{
+ unsigned int reg;
+
+ reg = readl(dsim->reg_base + EXYNOS_DSIM_STATUS);
+
+ return reg & (1 << 31) ? 1 : 0;
+}
+
+unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim)
+{
+ return readl(dsim->reg_base + EXYNOS_DSIM_FIFOCTRL) & ~(0x1f);
+}
+
+void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim,
+ unsigned int di, unsigned int data0, unsigned int data1)
+{
+ unsigned int reg = (data1 << 16) | (data0 << 8) | ((di & 0x3f) << 0);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_PKTHDR);
+}
+
+void exynos_mipi_dsi_rd_tx_header(struct mipi_dsim_device *dsim,
+ unsigned int di, unsigned int data0)
+{
+ unsigned int reg = (data0 << 8) | (di << 0);
+
+ writel(reg, dsim->reg_base + EXYNOS_DSIM_PKTHDR);
+}
+
+unsigned int exynos_mipi_dsi_rd_rx_fifo(struct mipi_dsim_device *dsim)
+{
+ return readl(dsim->reg_base + EXYNOS_DSIM_RXFIFO);
+}
+
+unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim)
+{
+ unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
+
+ return (reg & INTSRC_FRAME_DONE) ? 1 : 0;
+}
+
+void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim)
+{
+ unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
+
+ writel(reg | INTSRC_FRAME_DONE, dsim->reg_base +
+ EXYNOS_DSIM_INTSRC);
+}
+
+void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,
+ unsigned int tx_data)
+{
+ writel(tx_data, dsim->reg_base + EXYNOS_DSIM_PAYLOAD);
+}
diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
new file mode 100644
index 0000000..8546070
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
@@ -0,0 +1,112 @@
+/* linux/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
+ *
+ * Header file for Samsung SoC MIPI-DSI lowlevel driver.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae <inki.dae@samsung.com>
+ * Donghwa Lee <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _EXYNOS_MIPI_DSI_LOWLEVEL_H
+#define _EXYNOS_MIPI_DSI_LOWLEVEL_H
+
+void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_sw_reset_release(struct mipi_dsim_device *dsim);
+int exynos_mipi_dsi_get_sw_reset_release(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim,
+ unsigned int mode, unsigned int mask);
+void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
+ unsigned int count);
+void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim,
+ unsigned int cfg);
+void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
+ unsigned int value);
+void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
+ unsigned int value);
+void exynos_mipi_dsi_set_main_stand_by(struct mipi_dsim_device *dsim,
+ unsigned int enable);
+void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim,
+ unsigned int width_resol, unsigned int height_resol);
+void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim,
+ unsigned int cmd_allow, unsigned int vfront, unsigned int vback);
+void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim,
+ unsigned int front, unsigned int back);
+void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim,
+ unsigned int vert, unsigned int hori);
+void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim,
+ unsigned int vert, unsigned int hori);
+void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim,
+ struct mipi_dsim_config *dsim_config);
+void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
+ unsigned int count);
+void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, unsigned int lane,
+ unsigned int enable);
+void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, unsigned int enable,
+ unsigned int afc_code);
+void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim,
+ unsigned int enable);
+void exynos_mipi_dsi_set_pll_pms(struct mipi_dsim_device *dsim, unsigned int p,
+ unsigned int m, unsigned int s);
+void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim,
+ unsigned int freq_band);
+void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim,
+ unsigned int pre_divider, unsigned int main_divider,
+ unsigned int scaler);
+void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim,
+ unsigned int lock_time);
+void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim,
+ unsigned int enable);
+void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim,
+ unsigned int src);
+void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim,
+ unsigned int enable);
+void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim,
+ unsigned int enable, unsigned int prs_val);
+void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim,
+ unsigned int lane_sel, unsigned int enable);
+void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim,
+ unsigned int enable);
+unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim,
+ unsigned int cnt_val);
+void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim,
+ unsigned int timeout);
+void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim,
+ unsigned int timeout);
+void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim,
+ unsigned int lp);
+void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim,
+ unsigned int lp);
+void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim,
+ unsigned int enable);
+void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim,
+ unsigned int swap_en);
+void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
+ unsigned int hs_zero);
+void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep);
+unsigned int exynos_mipi_dsi_read_interrupt(struct mipi_dsim_device *dsim);
+unsigned int exynos_mipi_dsi_read_interrupt_mask(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
+ unsigned int src);
+void exynos_mipi_dsi_set_interrupt(struct mipi_dsim_device *dsim,
+ unsigned int src, unsigned int enable);
+unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim);
+unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim);
+unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim);
+void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim, unsigned int di,
+ unsigned int data0, unsigned int data1);
+void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,
+ unsigned int tx_data);
+void exynos_mipi_dsi_rd_tx_header(struct mipi_dsim_device *dsim,
+ unsigned int data0, unsigned int data1);
+unsigned int exynos_mipi_dsi_rd_rx_fifo(struct mipi_dsim_device *dsim);
+
+#endif /* _EXYNOS_MIPI_DSI_LOWLEVEL_H */
diff --git a/drivers/video/exynos/exynos_mipi_dsi_regs.h b/drivers/video/exynos/exynos_mipi_dsi_regs.h
new file mode 100644
index 0000000..4227106
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_regs.h
@@ -0,0 +1,149 @@
+/* linux/driver/video/exynos/exynos_mipi_dsi_regs.h
+ *
+ * Register definition file for Samsung MIPI-DSIM driver
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae <inki.dae@samsung.com>
+ * Donghwa Lee <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _EXYNOS_MIPI_DSI_REGS_H
+#define _EXYNOS_MIPI_DSI_REGS_H
+
+#define EXYNOS_DSIM_STATUS 0x0 /* Status register */
+#define EXYNOS_DSIM_SWRST 0x4 /* Software reset register */
+#define EXYNOS_DSIM_CLKCTRL 0x8 /* Clock control register */
+#define EXYNOS_DSIM_TIMEOUT 0xc /* Time out register */
+#define EXYNOS_DSIM_CONFIG 0x10 /* Configuration register */
+#define EXYNOS_DSIM_ESCMODE 0x14 /* Escape mode register */
+
+/* Main display image resolution register */
+#define EXYNOS_DSIM_MDRESOL 0x18
+#define EXYNOS_DSIM_MVPORCH 0x1c /* Main display Vporch register */
+#define EXYNOS_DSIM_MHPORCH 0x20 /* Main display Hporch register */
+#define EXYNOS_DSIM_MSYNC 0x24 /* Main display sync area register */
+
+/* Sub display image resolution register */
+#define EXYNOS_DSIM_SDRESOL 0x28
+#define EXYNOS_DSIM_INTSRC 0x2c /* Interrupt source register */
+#define EXYNOS_DSIM_INTMSK 0x30 /* Interrupt mask register */
+#define EXYNOS_DSIM_PKTHDR 0x34 /* Packet Header FIFO register */
+#define EXYNOS_DSIM_PAYLOAD 0x38 /* Payload FIFO register */
+#define EXYNOS_DSIM_RXFIFO 0x3c /* Read FIFO register */
+#define EXYNOS_DSIM_FIFOTHLD 0x40 /* FIFO threshold level register */
+#define EXYNOS_DSIM_FIFOCTRL 0x44 /* FIFO status and control register */
+
+/* FIFO memory AC characteristic register */
+#define EXYNOS_DSIM_PLLCTRL 0x4c /* PLL control register */
+#define EXYNOS_DSIM_PLLTMR 0x50 /* PLL timer register */
+#define EXYNOS_DSIM_PHYACCHR 0x54 /* D-PHY AC characteristic register */
+#define EXYNOS_DSIM_PHYACCHR1 0x58 /* D-PHY AC characteristic register1 */
+
+/* DSIM_STATUS */
+#define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
+#define DSIM_STOP_STATE_CLK (1 << 8)
+#define DSIM_TX_READY_HS_CLK (1 << 10)
+
+/* DSIM_SWRST */
+#define DSIM_FUNCRST (1 << 16)
+#define DSIM_SWRST (1 << 0)
+
+/* EXYNOS_DSIM_TIMEOUT */
+#define DSIM_LPDR_TOUT_SHIFT(x) ((x) << 0)
+#define DSIM_BTA_TOUT_SHIFT(x) ((x) << 16)
+
+/* EXYNOS_DSIM_CLKCTRL */
+#define DSIM_LANE_ESC_CLKEN(x) (((x) & 0x1f) << 19)
+#define DSIM_BYTE_CLKEN_SHIFT(x) ((x) << 24)
+#define DSIM_BYTE_CLK_SRC_SHIFT(x) ((x) << 25)
+#define DSIM_PLL_BYPASS_SHIFT(x) ((x) << 27)
+#define DSIM_ESC_CLKEN_SHIFT(x) ((x) << 28)
+#define DSIM_TX_REQUEST_HSCLK_SHIFT(x) ((x) << 31)
+
+/* EXYNOS_DSIM_CONFIG */
+#define DSIM_LANE_ENx(x) (((x) & 0x1f) << 0)
+#define DSIM_NUM_OF_DATALANE_SHIFT(x) ((x) << 5)
+#define DSIM_HSA_MODE_SHIFT(x) ((x) << 20)
+#define DSIM_HBP_MODE_SHIFT(x) ((x) << 21)
+#define DSIM_HFP_MODE_SHIFT(x) ((x) << 22)
+#define DSIM_HSE_MODE_SHIFT(x) ((x) << 23)
+#define DSIM_AUTO_MODE_SHIFT(x) ((x) << 24)
+#define DSIM_EOT_DISABLE(x) ((x) << 28)
+#define DSIM_AUTO_FLUSH(x) ((x) << 29)
+
+#define DSIM_NUM_OF_DATA_LANE(x) ((x) << DSIM_NUM_OF_DATALANE_SHIFT)
+
+/* EXYNOS_DSIM_ESCMODE */
+#define DSIM_TX_LPDT_LP (1 << 6)
+#define DSIM_CMD_LPDT_LP (1 << 7)
+#define DSIM_FORCE_STOP_STATE_SHIFT(x) ((x) << 20)
+#define DSIM_STOP_STATE_CNT_SHIFT(x) ((x) << 21)
+
+/* EXYNOS_DSIM_MDRESOL */
+#define DSIM_MAIN_STAND_BY (1 << 31)
+#define DSIM_MAIN_VRESOL(x) (((x) & 0x7ff) << 16)
+#define DSIM_MAIN_HRESOL(x) (((x) & 0X7ff) << 0)
+
+/* EXYNOS_DSIM_MVPORCH */
+#define DSIM_CMD_ALLOW_SHIFT(x) ((x) << 28)
+#define DSIM_STABLE_VFP_SHIFT(x) ((x) << 16)
+#define DSIM_MAIN_VBP_SHIFT(x) ((x) << 0)
+#define DSIM_CMD_ALLOW_MASK (0xf << 28)
+#define DSIM_STABLE_VFP_MASK (0x7ff << 16)
+#define DSIM_MAIN_VBP_MASK (0x7ff << 0)
+
+/* EXYNOS_DSIM_MHPORCH */
+#define DSIM_MAIN_HFP_SHIFT(x) ((x) << 16)
+#define DSIM_MAIN_HBP_SHIFT(x) ((x) << 0)
+#define DSIM_MAIN_HFP_MASK ((0xffff) << 16)
+#define DSIM_MAIN_HBP_MASK ((0xffff) << 0)
+
+/* EXYNOS_DSIM_MSYNC */
+#define DSIM_MAIN_VSA_SHIFT(x) ((x) << 22)
+#define DSIM_MAIN_HSA_SHIFT(x) ((x) << 0)
+#define DSIM_MAIN_VSA_MASK ((0x3ff) << 22)
+#define DSIM_MAIN_HSA_MASK ((0xffff) << 0)
+
+/* EXYNOS_DSIM_SDRESOL */
+#define DSIM_SUB_STANDY_SHIFT(x) ((x) << 31)
+#define DSIM_SUB_VRESOL_SHIFT(x) ((x) << 16)
+#define DSIM_SUB_HRESOL_SHIFT(x) ((x) << 0)
+#define DSIM_SUB_STANDY_MASK ((0x1) << 31)
+#define DSIM_SUB_VRESOL_MASK ((0x7ff) << 16)
+#define DSIM_SUB_HRESOL_MASK ((0x7ff) << 0)
+
+/* EXYNOS_DSIM_INTSRC */
+#define INTSRC_PLL_STABLE (1 << 31)
+#define INTSRC_SW_RST_RELEASE (1 << 30)
+#define INTSRC_SFR_FIFO_EMPTY (1 << 29)
+#define INTSRC_FRAME_DONE (1 << 24)
+#define INTSRC_RX_DATA_DONE (1 << 18)
+
+/* EXYNOS_DSIM_INTMSK */
+#define INTMSK_FIFO_EMPTY (1 << 29)
+#define INTMSK_BTA (1 << 25)
+#define INTMSK_FRAME_DONE (1 << 24)
+#define INTMSK_RX_TIMEOUT (1 << 21)
+#define INTMSK_BTA_TIMEOUT (1 << 20)
+#define INTMSK_RX_DONE (1 << 18)
+#define INTMSK_RX_TE (1 << 17)
+#define INTMSK_RX_ACK (1 << 16)
+#define INTMSK_RX_ECC_ERR (1 << 15)
+#define INTMSK_RX_CRC_ERR (1 << 14)
+
+/* EXYNOS_DSIM_FIFOCTRL */
+#define SFR_HEADER_EMPTY (1 << 22)
+
+/* EXYNOS_DSIM_PHYACCHR */
+#define DSIM_AFC_CTL(x) (((x) & 0x7) << 5)
+
+/* EXYNOS_DSIM_PLLCTRL */
+#define DSIM_PLL_EN_SHIFT(x) ((x) << 23)
+#define DSIM_FREQ_BAND_SHIFT(x) ((x) << 24)
+
+#endif /* _EXYNOS_MIPI_DSI_REGS_H */
diff --git a/include/video/exynos_mipi_dsim.h b/include/video/exynos_mipi_dsim.h
new file mode 100644
index 0000000..772c770
--- /dev/null
+++ b/include/video/exynos_mipi_dsim.h
@@ -0,0 +1,359 @@
+/* include/video/exynos_mipi_dsim.h
+ *
+ * Platform data header for Samsung SoC MIPI-DSIM.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd
+ *
+ * InKi Dae <inki.dae@samsung.com>
+ * Donghwa Lee <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _EXYNOS_MIPI_DSIM_H
+#define _EXYNOS_MIPI_DSIM_H
+
+#include <linux/device.h>
+#include <linux/fb.h>
+
+#define PANEL_NAME_SIZE (32)
+
+/*
+ * Enumerate display interface type.
+ *
+ * DSIM_COMMAND means cpu interface and rgb interface for DSIM_VIDEO.
+ *
+ * P.S. MIPI DSI Master has two display controller intefaces, RGB Interface
+ * for main display and CPU Interface(same as I80 Interface) for main
+ * and sub display.
+ */
+enum mipi_dsim_interface_type {
+ DSIM_COMMAND,
+ DSIM_VIDEO
+};
+
+enum mipi_dsim_virtual_ch_no {
+ DSIM_VIRTUAL_CH_0,
+ DSIM_VIRTUAL_CH_1,
+ DSIM_VIRTUAL_CH_2,
+ DSIM_VIRTUAL_CH_3
+};
+
+enum mipi_dsim_burst_mode_type {
+ DSIM_NON_BURST_SYNC_EVENT,
+ DSIM_BURST_SYNC_EVENT,
+ DSIM_NON_BURST_SYNC_PULSE,
+ DSIM_BURST,
+ DSIM_NON_VIDEO_MODE
+};
+
+enum mipi_dsim_no_of_data_lane {
+ DSIM_DATA_LANE_1,
+ DSIM_DATA_LANE_2,
+ DSIM_DATA_LANE_3,
+ DSIM_DATA_LANE_4
+};
+
+enum mipi_dsim_byte_clk_src {
+ DSIM_PLL_OUT_DIV8,
+ DSIM_EXT_CLK_DIV8,
+ DSIM_EXT_CLK_BYPASS
+};
+
+enum mipi_dsim_pixel_format {
+ DSIM_CMD_3BPP,
+ DSIM_CMD_8BPP,
+ DSIM_CMD_12BPP,
+ DSIM_CMD_16BPP,
+ DSIM_VID_16BPP_565,
+ DSIM_VID_18BPP_666PACKED,
+ DSIM_18BPP_666LOOSELYPACKED,
+ DSIM_24BPP_888
+};
+
+/*
+ * struct mipi_dsim_config - interface for configuring mipi-dsi controller.
+ *
+ * @auto_flush: enable or disable Auto flush of MD FIFO using VSYNC pulse.
+ * @eot_disable: enable or disable EoT packet in HS mode.
+ * @auto_vertical_cnt: specifies auto vertical count mode.
+ * in Video mode, the vertical line transition uses line counter
+ * configured by VSA, VBP, and Vertical resolution.
+ * If this bit is set to '1', the line counter does not use VSA and VBP
+ * registers.(in command mode, this variable is ignored)
+ * @hse: set horizontal sync event mode.
+ * In VSYNC pulse and Vporch area, MIPI DSI master transfers only HSYNC
+ * start packet to MIPI DSI slave at MIPI DSI spec1.1r02.
+ * this bit transfers HSYNC end packet in VSYNC pulse and Vporch area
+ * (in mommand mode, this variable is ignored)
+ * @hfp: specifies HFP disable mode.
+ * if this variable is set, DSI master ignores HFP area in VIDEO mode.
+ * (in command mode, this variable is ignored)
+ * @hbp: specifies HBP disable mode.
+ * if this variable is set, DSI master ignores HBP area in VIDEO mode.
+ * (in command mode, this variable is ignored)
+ * @hsa: specifies HSA disable mode.
+ * if this variable is set, DSI master ignores HSA area in VIDEO mode.
+ * (in command mode, this variable is ignored)
+ * @cma_allow: specifies the number of horizontal lines, where command packet
+ * transmission is allowed after Stable VFP period.
+ * @e_interface: specifies interface to be used.(CPU or RGB interface)
+ * @e_virtual_ch: specifies virtual channel number that main or
+ * sub diaplsy uses.
+ * @e_pixel_format: specifies pixel stream format for main or sub display.
+ * @e_burst_mode: selects Burst mode in Video mode.
+ * in Non-burst mode, RGB data area is filled with RGB data and NULL
+ * packets, according to input bandwidth of RGB interface.
+ * In Burst mode, RGB data area is filled with RGB data only.
+ * @e_no_data_lane: specifies data lane count to be used by Master.
+ * @e_byte_clk: select byte clock source. (it must be DSIM_PLL_OUT_DIV8)
+ * DSIM_EXT_CLK_DIV8 and DSIM_EXT_CLK_BYPASSS are not supported.
+ * @pll_stable_time: specifies the PLL Timer for stability of the ganerated
+ * clock(System clock cycle base)
+ * if the timer value goes to 0x00000000, the clock stable bit of status
+ * and interrupt register is set.
+ * @esc_clk: specifies escape clock frequency for getting the escape clock
+ * prescaler value.
+ * @stop_holding_cnt: specifies the interval value between transmitting
+ * read packet(or write "set_tear_on" command) and BTA request.
+ * after transmitting read packet or write "set_tear_on" command,
+ * BTA requests to D-PHY automatically. this counter value specifies
+ * the interval between them.
+ * @bta_timeout: specifies the timer for BTA.
+ * this register specifies time out from BTA request to change
+ * the direction with respect to Tx escape clock.
+ * @rx_timeout: specifies the timer for LP Rx mode timeout.
+ * this register specifies time out on how long RxValid deasserts,
+ * after RxLpdt asserts with respect to Tx escape clock.
+ * - RxValid specifies Rx data valid indicator.
+ * - RxLpdt specifies an indicator that D-PHY is under RxLpdt mode.
+ * - RxValid and RxLpdt specifies signal from D-PHY.
+ */
+struct mipi_dsim_config {
+ unsigned char auto_flush;
+ unsigned char eot_disable;
+
+ unsigned char auto_vertical_cnt;
+ unsigned char hse;
+ unsigned char hfp;
+ unsigned char hbp;
+ unsigned char hsa;
+ unsigned char cmd_allow;
+
+ enum mipi_dsim_interface_type e_interface;
+ enum mipi_dsim_virtual_ch_no e_virtual_ch;
+ enum mipi_dsim_pixel_format e_pixel_format;
+ enum mipi_dsim_burst_mode_type e_burst_mode;
+ enum mipi_dsim_no_of_data_lane e_no_data_lane;
+ enum mipi_dsim_byte_clk_src e_byte_clk;
+
+ /*
+ * =====================+ * | P | M | S | MHz |
+ * -------------------------------------------
+ * | 3 | 100 | 3 | 100 |
+ * | 3 | 100 | 2 | 200 |
+ * | 3 | 63 | 1 | 252 |
+ * | 4 | 100 | 1 | 300 |
+ * | 4 | 110 | 1 | 330 |
+ * | 12 | 350 | 1 | 350 |
+ * | 3 | 100 | 1 | 400 |
+ * | 4 | 150 | 1 | 450 |
+ * | 6 | 118 | 1 | 472 |
+ * | 3 | 120 | 1 | 480 |
+ * | 12 | 250 | 0 | 500 |
+ * | 4 | 100 | 0 | 600 |
+ * | 3 | 81 | 0 | 648 |
+ * | 3 | 88 | 0 | 704 |
+ * | 3 | 90 | 0 | 720 |
+ * | 3 | 100 | 0 | 800 |
+ * | 12 | 425 | 0 | 850 |
+ * | 4 | 150 | 0 | 900 |
+ * | 12 | 475 | 0 | 950 |
+ * | 6 | 250 | 0 | 1000 |
+ * -------------------------------------------
+ */
+
+ /*
+ * pms could be calculated as the following.
+ * M * 24 / P * 2 ^ S = MHz
+ */
+ unsigned char p;
+ unsigned short m;
+ unsigned char s;
+
+ unsigned int pll_stable_time;
+ unsigned long esc_clk;
+
+ unsigned short stop_holding_cnt;
+ unsigned char bta_timeout;
+ unsigned short rx_timeout;
+};
+
+/*
+ * struct mipi_dsim_device - global interface for mipi-dsi driver.
+ *
+ * @dev: driver model representation of the device.
+ * @id: unique device id.
+ * @clock: pointer to MIPI-DSI clock of clock framework.
+ * @irq: interrupt number to MIPI-DSI controller.
+ * @reg_base: base address to memory mapped SRF of MIPI-DSI controller.
+ * (virtual address)
+ * @lock: the mutex protecting this data structure.
+ * @dsim_info: infomation for configuring mipi-dsi controller.
+ * @master_ops: callbacks to mipi-dsi operations.
+ * @dsim_lcd_dev: pointer to activated ddi device.
+ * (it would be registered by mipi-dsi driver.)
+ * @dsim_lcd_drv: pointer to activated_ddi driver.
+ * (it would be registered by mipi-dsi driver.)
+ * @lcd_info: pointer to mipi_lcd_info structure.
+ * @state: specifies status of MIPI-DSI controller.
+ * the status could be RESET, INIT, STOP, HSCLKEN and ULPS.
+ * @data_lane: specifiec enabled data lane number.
+ * this variable would be set by driver according to e_no_data_lane
+ * automatically.
+ * @e_clk_src: select byte clock source.
+ * @pd: pointer to MIPI-DSI driver platform data.
+ */
+struct mipi_dsim_device {
+ struct device *dev;
+ int id;
+ struct resource *res;
+ struct clk *clock;
+ unsigned int irq;
+ void __iomem *reg_base;
+ struct mutex lock;
+
+ struct mipi_dsim_config *dsim_config;
+ struct mipi_dsim_master_ops *master_ops;
+ struct mipi_dsim_lcd_device *dsim_lcd_dev;
+ struct mipi_dsim_lcd_driver *dsim_lcd_drv;
+
+ unsigned int state;
+ unsigned int data_lane;
+ unsigned int e_clk_src;
+ bool suspended;
+
+ struct mipi_dsim_platform_data *pd;
+};
+
+/*
+ * struct mipi_dsim_platform_data - interface to platform data
+ * for mipi-dsi driver.
+ *
+ * @lcd_panel_name: specifies lcd panel name registered to mipi-dsi driver.
+ * lcd panel driver searched would be actived.
+ * @dsim_config: pointer of structure for configuring mipi-dsi controller.
+ * @enabled: indicate whether mipi controller got enabled or not.
+ * @lcd_panel_info: pointer for lcd panel specific structure.
+ * this structure specifies width, height, timing and polarity and so on.
+ * @phy_enable: pointer to a callback controlling D-PHY enable/reset
+ */
+struct mipi_dsim_platform_data {
+ char lcd_panel_name[PANEL_NAME_SIZE];
+
+ struct mipi_dsim_config *dsim_config;
+ unsigned int enabled;
+ void *lcd_panel_info;
+
+ int (*phy_enable)(struct platform_device *pdev, bool on);
+};
+
+/*
+ * struct mipi_dsim_master_ops - callbacks to mipi-dsi operations.
+ *
+ * @cmd_write: transfer command to lcd panel at LP mode.
+ * @cmd_read: read command from rx register.
+ * @get_dsim_frame_done: get the status that all screen data have been
+ * transferred to mipi-dsi.
+ * @clear_dsim_frame_done: clear frame done status.
+ * @get_fb_frame_done: get frame done status of display controller.
+ * @trigger: trigger display controller.
+ * - this one would be used only in case of CPU mode.
+ * @set_early_blank_mode: set framebuffer blank mode.
+ * - this callback should be called prior to fb_blank() by a client driver
+ * only if needing.
+ * @set_blank_mode: set framebuffer blank mode.
+ * - this callback should be called after fb_blank() by a client driver
+ * only if needing.
+ */
+
+struct mipi_dsim_master_ops {
+ int (*cmd_write)(struct mipi_dsim_device *dsim, unsigned int data_id,
+ const unsigned char *data0, unsigned int data1);
+ int (*cmd_read)(struct mipi_dsim_device *dsim, unsigned int data_id,
+ unsigned int data0, unsigned int req_size, u8 *rx_buf);
+ int (*get_dsim_frame_done)(struct mipi_dsim_device *dsim);
+ int (*clear_dsim_frame_done)(struct mipi_dsim_device *dsim);
+
+ int (*get_fb_frame_done)(struct fb_info *info);
+ void (*trigger)(struct fb_info *info);
+ int (*set_early_blank_mode)(struct mipi_dsim_device *dsim, int power);
+ int (*set_blank_mode)(struct mipi_dsim_device *dsim, int power);
+};
+
+/*
+ * device structure for mipi-dsi based lcd panel.
+ *
+ * @name: name of the device to use with this device, or an
+ * alias for that name.
+ * @dev: driver model representation of the device.
+ * @id: id of device to be registered.
+ * @bus_id: bus id for identifing connected bus
+ * and this bus id should be same as id of mipi_dsim_device.
+ * @irq: irq number for signaling when framebuffer transfer of
+ * lcd panel module is completed.
+ * this irq would be used only for MIPI-DSI based CPU mode lcd panel.
+ * @master: pointer to mipi-dsi master device object.
+ * @platform_data: lcd panel specific platform data.
+ */
+struct mipi_dsim_lcd_device {
+ char *name;
+ struct device dev;
+ int id;
+ int bus_id;
+ int irq;
+
+ struct mipi_dsim_device *master;
+ void *platform_data;
+};
+
+/*
+ * driver structure for mipi-dsi based lcd panel.
+ *
+ * this structure should be registered by lcd panel driver.
+ * mipi-dsi driver seeks lcd panel registered through name field
+ * and calls these callback functions in appropriate time.
+ *
+ * @name: name of the driver to use with this device, or an
+ * alias for that name.
+ * @id: id of driver to be registered.
+ * this id would be used for finding device object registered.
+ */
+struct mipi_dsim_lcd_driver {
+ char *name;
+ int id;
+
+ void (*power_on)(struct mipi_dsim_lcd_device *dsim_dev, int enable);
+ void (*set_sequence)(struct mipi_dsim_lcd_device *dsim_dev);
+ int (*probe)(struct mipi_dsim_lcd_device *dsim_dev);
+ int (*remove)(struct mipi_dsim_lcd_device *dsim_dev);
+ void (*shutdown)(struct mipi_dsim_lcd_device *dsim_dev);
+ int (*suspend)(struct mipi_dsim_lcd_device *dsim_dev);
+ int (*resume)(struct mipi_dsim_lcd_device *dsim_dev);
+};
+
+/*
+ * register mipi_dsim_lcd_device to mipi-dsi master.
+ */
+int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device
+ *lcd_dev);
+/**
+ * register mipi_dsim_lcd_driver object defined by lcd panel driver
+ * to mipi-dsi driver.
+ */
+int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver
+ *lcd_drv);
+#endif /* _EXYNOS_MIPI_DSIM_H */
--
1.7.4.1
^ permalink raw reply related
* [PATCH v8 2/2] video: backlight: support s6e8ax0 panel driver based on MIPI DSI
From: Donghwa Lee @ 2012-01-27 9:12 UTC (permalink / raw)
To: linux-arm-kernel
This patch is amoled panel driver based MIPI DSI interface.
S6E8AX0 means it may includes many other ldi controllers, for example,
S6E8AA0, S6E8AB0, and so on.
This patch can be modified depending on each panel properites. For example,
second parameter of panel condition register can be changed depending on
ldi controller or amoled type.
Changes since v7:
- move s6e8ax0 driver to driver/video/exynos directory
Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/video/exynos/Kconfig | 11 +-
drivers/video/exynos/Makefile | 1 +
drivers/video/exynos/s6e8ax0.c | 898 ++++++++++++++++++++++++++++++++++++++++
drivers/video/exynos/s6e8ax0.h | 21 +
4 files changed, 930 insertions(+), 1 deletions(-)
create mode 100644 drivers/video/exynos/s6e8ax0.c
create mode 100644 drivers/video/exynos/s6e8ax0.h
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
index 645b8a5..4fa7b9e 100644
--- a/drivers/video/exynos/Kconfig
+++ b/drivers/video/exynos/Kconfig
@@ -15,8 +15,17 @@ if EXYNOS_VIDEO
config EXYNOS_MIPI_DSI
bool "EXYNOS MIPI DSI driver support."
- depends on (ARCH_S5PV210 || ARCH_EXYNOS)
+ depends on ARCH_S5PV210 || ARCH_EXYNOS
help
This enables support for MIPI-DSI device.
+config EXYNOS_LCD_S6E8AX0
+ bool "S6E8AX0 MIPI AMOLED LCD Driver"
+ depends on (EXYNOS_MIPI_DSI && BACKLIGHT_CLASS_DEVICE &&
+ LCD_CLASS_DEVICE)
+ default n
+ help
+ If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
+ LCD control driver.
+
endif # EXYNOS_VIDEO
diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile
index a1ae82a..b5b1bd2 100644
--- a/drivers/video/exynos/Makefile
+++ b/drivers/video/exynos/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_EXYNOS_MIPI_DSI) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \
exynos_mipi_dsi_lowlevel.o
+obj-$(CONFIG_EXYNOS_LCD_S6E8AX0) += s6e8ax0.o
diff --git a/drivers/video/exynos/s6e8ax0.c b/drivers/video/exynos/s6e8ax0.c
new file mode 100644
index 0000000..6a00730
--- /dev/null
+++ b/drivers/video/exynos/s6e8ax0.c
@@ -0,0 +1,898 @@
+/* linux/drivers/video/exynos/s6e8ax0.c
+ *
+ * MIPI-DSI based s6e8ax0 AMOLED lcd 4.65 inch panel driver.
+ *
+ * Inki Dae, <inki.dae@samsung.com>
+ * Donghwa Lee, <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/lcd.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+#include <video/exynos_mipi_dsim.h>
+
+#define LDI_MTP_LENGTH 24
+#define DSIM_PM_STABLE_TIME 10
+#define MIN_BRIGHTNESS 0
+#define MAX_BRIGHTNESS 24
+#define GAMMA_TABLE_COUNT 26
+
+#define POWER_IS_ON(pwr) ((pwr) = FB_BLANK_UNBLANK)
+#define POWER_IS_OFF(pwr) ((pwr) = FB_BLANK_POWERDOWN)
+#define POWER_IS_NRM(pwr) ((pwr) = FB_BLANK_NORMAL)
+
+#define lcd_to_master(a) (a->dsim_dev->master)
+#define lcd_to_master_ops(a) ((lcd_to_master(a))->master_ops)
+
+enum {
+ DSIM_NONE_STATE = 0,
+ DSIM_RESUME_COMPLETE = 1,
+ DSIM_FRAME_DONE = 2,
+};
+
+struct s6e8ax0 {
+ struct device *dev;
+ unsigned int power;
+ unsigned int id;
+ unsigned int gamma;
+ unsigned int acl_enable;
+ unsigned int cur_acl;
+
+ struct lcd_device *ld;
+ struct backlight_device *bd;
+
+ struct mipi_dsim_lcd_device *dsim_dev;
+ struct lcd_platform_data *ddi_pd;
+ struct mutex lock;
+ bool enabled;
+};
+
+
+static struct regulator_bulk_data supplies[] = {
+ { .supply = "vdd3", },
+ { .supply = "vci", },
+};
+
+static void s6e8ax0_regulator_enable(struct s6e8ax0 *lcd)
+{
+ int ret = 0;
+ struct lcd_platform_data *pd = NULL;
+
+ pd = lcd->ddi_pd;
+ mutex_lock(&lcd->lock);
+ if (!lcd->enabled) {
+ ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
+ if (ret)
+ goto out;
+
+ lcd->enabled = true;
+ }
+ msleep(pd->power_on_delay);
+out:
+ mutex_unlock(&lcd->lock);
+}
+
+static void s6e8ax0_regulator_disable(struct s6e8ax0 *lcd)
+{
+ int ret = 0;
+
+ mutex_lock(&lcd->lock);
+ if (lcd->enabled) {
+ ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
+ if (ret)
+ goto out;
+
+ lcd->enabled = false;
+ }
+out:
+ mutex_unlock(&lcd->lock);
+}
+
+static const unsigned char s6e8ax0_22_gamma_30[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xf5, 0x00, 0xff, 0xad, 0xaf,
+ 0xbA, 0xc3, 0xd8, 0xc5, 0x9f, 0xc6, 0x9e, 0xc1, 0xdc, 0xc0,
+ 0x00, 0x61, 0x00, 0x5a, 0x00, 0x74,
+};
+
+static const unsigned char s6e8ax0_22_gamma_50[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xe8, 0x1f, 0xf7, 0xad, 0xc0,
+ 0xb5, 0xc4, 0xdc, 0xc4, 0x9e, 0xc6, 0x9c, 0xbb, 0xd8, 0xbb,
+ 0x00, 0x70, 0x00, 0x68, 0x00, 0x86,
+};
+
+static const unsigned char s6e8ax0_22_gamma_60[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xde, 0x1f, 0xef, 0xad, 0xc4,
+ 0xb3, 0xc3, 0xdd, 0xc4, 0x9e, 0xc6, 0x9c, 0xbc, 0xd6, 0xba,
+ 0x00, 0x75, 0x00, 0x6e, 0x00, 0x8d,
+};
+
+static const unsigned char s6e8ax0_22_gamma_70[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xd8, 0x1f, 0xe7, 0xaf, 0xc8,
+ 0xb4, 0xc4, 0xdd, 0xc3, 0x9d, 0xc6, 0x9c, 0xbb, 0xd6, 0xb9,
+ 0x00, 0x7a, 0x00, 0x72, 0x00, 0x93,
+};
+
+static const unsigned char s6e8ax0_22_gamma_80[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xc9, 0x1f, 0xde, 0xae, 0xc9,
+ 0xb1, 0xc3, 0xdd, 0xc2, 0x9d, 0xc5, 0x9b, 0xbc, 0xd6, 0xbb,
+ 0x00, 0x7f, 0x00, 0x77, 0x00, 0x99,
+};
+
+static const unsigned char s6e8ax0_22_gamma_90[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xc7, 0x1f, 0xd9, 0xb0, 0xcc,
+ 0xb2, 0xc3, 0xdc, 0xc1, 0x9c, 0xc6, 0x9c, 0xbc, 0xd4, 0xb9,
+ 0x00, 0x83, 0x00, 0x7b, 0x00, 0x9e,
+};
+
+static const unsigned char s6e8ax0_22_gamma_100[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xbd, 0x80, 0xcd, 0xba, 0xce,
+ 0xb3, 0xc4, 0xde, 0xc3, 0x9c, 0xc4, 0x9, 0xb8, 0xd3, 0xb6,
+ 0x00, 0x88, 0x00, 0x80, 0x00, 0xa5,
+};
+
+static const unsigned char s6e8ax0_22_gamma_120[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb9, 0x95, 0xc8, 0xb1, 0xcf,
+ 0xb2, 0xc6, 0xdf, 0xc5, 0x9b, 0xc3, 0x99, 0xb6, 0xd2, 0xb6,
+ 0x00, 0x8f, 0x00, 0x86, 0x00, 0xac,
+};
+
+static const unsigned char s6e8ax0_22_gamma_130[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb7, 0xa0, 0xc7, 0xb1, 0xd0,
+ 0xb2, 0xc4, 0xdd, 0xc3, 0x9a, 0xc3, 0x98, 0xb6, 0xd0, 0xb4,
+ 0x00, 0x92, 0x00, 0x8a, 0x00, 0xb1,
+};
+
+static const unsigned char s6e8ax0_22_gamma_140[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb7, 0xa0, 0xc5, 0xb2, 0xd0,
+ 0xb3, 0xc3, 0xde, 0xc3, 0x9b, 0xc2, 0x98, 0xb6, 0xd0, 0xb4,
+ 0x00, 0x95, 0x00, 0x8d, 0x00, 0xb5,
+};
+
+static const unsigned char s6e8ax0_22_gamma_150[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xa0, 0xc2, 0xb2, 0xd0,
+ 0xb2, 0xc1, 0xdd, 0xc2, 0x9b, 0xc2, 0x98, 0xb4, 0xcf, 0xb1,
+ 0x00, 0x99, 0x00, 0x90, 0x00, 0xba,
+};
+
+static const unsigned char s6e8ax0_22_gamma_160[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xa5, 0xbf, 0xb0, 0xd0,
+ 0xb1, 0xc3, 0xde, 0xc2, 0x99, 0xc1, 0x97, 0xb4, 0xce, 0xb1,
+ 0x00, 0x9c, 0x00, 0x93, 0x00, 0xbe,
+};
+
+static const unsigned char s6e8ax0_22_gamma_170[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb5, 0xbf, 0xb1, 0xd1,
+ 0xb1, 0xc3, 0xde, 0xc3, 0x99, 0xc0, 0x96, 0xb4, 0xce, 0xb1,
+ 0x00, 0x9f, 0x00, 0x96, 0x00, 0xc2,
+};
+
+static const unsigned char s6e8ax0_22_gamma_180[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb7, 0xbe, 0xb3, 0xd2,
+ 0xb3, 0xc3, 0xde, 0xc2, 0x97, 0xbf, 0x95, 0xb4, 0xcd, 0xb1,
+ 0x00, 0xa2, 0x00, 0x99, 0x00, 0xc5,
+};
+
+static const unsigned char s6e8ax0_22_gamma_190[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb9, 0xbe, 0xb2, 0xd2,
+ 0xb2, 0xc3, 0xdd, 0xc3, 0x98, 0xbf, 0x95, 0xb2, 0xcc, 0xaf,
+ 0x00, 0xa5, 0x00, 0x9c, 0x00, 0xc9,
+};
+
+static const unsigned char s6e8ax0_22_gamma_200[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb9, 0xbc, 0xb2, 0xd2,
+ 0xb1, 0xc4, 0xdd, 0xc3, 0x97, 0xbe, 0x95, 0xb1, 0xcb, 0xae,
+ 0x00, 0xa8, 0x00, 0x9f, 0x00, 0xcd,
+};
+
+static const unsigned char s6e8ax0_22_gamma_210[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc1, 0xbd, 0xb1, 0xd1,
+ 0xb1, 0xc2, 0xde, 0xc2, 0x97, 0xbe, 0x94, 0xB0, 0xc9, 0xad,
+ 0x00, 0xae, 0x00, 0xa4, 0x00, 0xd4,
+};
+
+static const unsigned char s6e8ax0_22_gamma_220[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc7, 0xbd, 0xb1, 0xd1,
+ 0xb1, 0xc2, 0xdd, 0xc2, 0x97, 0xbd, 0x94, 0xb0, 0xc9, 0xad,
+ 0x00, 0xad, 0x00, 0xa2, 0x00, 0xd3,
+};
+
+static const unsigned char s6e8ax0_22_gamma_230[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc3, 0xbd, 0xb2, 0xd1,
+ 0xb1, 0xc3, 0xdd, 0xc1, 0x96, 0xbd, 0x94, 0xb0, 0xc9, 0xad,
+ 0x00, 0xb0, 0x00, 0xa7, 0x00, 0xd7,
+};
+
+static const unsigned char s6e8ax0_22_gamma_240[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xcb, 0xbd, 0xb1, 0xd2,
+ 0xb1, 0xc3, 0xdD, 0xc2, 0x95, 0xbd, 0x93, 0xaf, 0xc8, 0xab,
+ 0x00, 0xb3, 0x00, 0xa9, 0x00, 0xdb,
+};
+
+static const unsigned char s6e8ax0_22_gamma_250[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xcc, 0xbe, 0xb0, 0xd2,
+ 0xb0, 0xc3, 0xdD, 0xc2, 0x94, 0xbc, 0x92, 0xae, 0xc8, 0xab,
+ 0x00, 0xb6, 0x00, 0xab, 0x00, 0xde,
+};
+
+static const unsigned char s6e8ax0_22_gamma_260[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xd0, 0xbe, 0xaf, 0xd1,
+ 0xaf, 0xc2, 0xdd, 0xc1, 0x96, 0xbc, 0x93, 0xaf, 0xc8, 0xac,
+ 0x00, 0xb7, 0x00, 0xad, 0x00, 0xe0,
+};
+
+static const unsigned char s6e8ax0_22_gamma_270[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb2, 0xcF, 0xbd, 0xb0, 0xd2,
+ 0xaf, 0xc2, 0xdc, 0xc1, 0x95, 0xbd, 0x93, 0xae, 0xc6, 0xaa,
+ 0x00, 0xba, 0x00, 0xb0, 0x00, 0xe4,
+};
+
+static const unsigned char s6e8ax0_22_gamma_280[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb2, 0xd0, 0xbd, 0xaf, 0xd0,
+ 0xad, 0xc4, 0xdd, 0xc3, 0x95, 0xbd, 0x93, 0xac, 0xc5, 0xa9,
+ 0x00, 0xbd, 0x00, 0xb2, 0x00, 0xe7,
+};
+
+static const unsigned char s6e8ax0_22_gamma_300[] = {
+ 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb5, 0xd3, 0xbd, 0xb1, 0xd2,
+ 0xb0, 0xc0, 0xdc, 0xc0, 0x94, 0xba, 0x91, 0xac, 0xc5, 0xa9,
+ 0x00, 0xc2, 0x00, 0xb7, 0x00, 0xed,
+};
+
+static const unsigned char *s6e8ax0_22_gamma_table[] = {
+ s6e8ax0_22_gamma_30,
+ s6e8ax0_22_gamma_50,
+ s6e8ax0_22_gamma_60,
+ s6e8ax0_22_gamma_70,
+ s6e8ax0_22_gamma_80,
+ s6e8ax0_22_gamma_90,
+ s6e8ax0_22_gamma_100,
+ s6e8ax0_22_gamma_120,
+ s6e8ax0_22_gamma_130,
+ s6e8ax0_22_gamma_140,
+ s6e8ax0_22_gamma_150,
+ s6e8ax0_22_gamma_160,
+ s6e8ax0_22_gamma_170,
+ s6e8ax0_22_gamma_180,
+ s6e8ax0_22_gamma_190,
+ s6e8ax0_22_gamma_200,
+ s6e8ax0_22_gamma_210,
+ s6e8ax0_22_gamma_220,
+ s6e8ax0_22_gamma_230,
+ s6e8ax0_22_gamma_240,
+ s6e8ax0_22_gamma_250,
+ s6e8ax0_22_gamma_260,
+ s6e8ax0_22_gamma_270,
+ s6e8ax0_22_gamma_280,
+ s6e8ax0_22_gamma_300,
+};
+
+static void s6e8ax0_panel_cond(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+
+ static const unsigned char data_to_send[] = {
+ 0xf8, 0x3d, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 0x3c, 0x7d,
+ 0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08,
+ 0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0,
+ 0xc8, 0x08, 0x48, 0xc1, 0x00, 0xc1, 0xff, 0xff, 0xc8
+ };
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_display_cond(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xf2, 0x80, 0x03, 0x0d
+ };
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+/* Gamma 2.2 Setting (200cd, 7500K, 10MPCD) */
+static void s6e8ax0_gamma_cond(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ unsigned int gamma = lcd->bd->props.brightness;
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ s6e8ax0_22_gamma_table[gamma],
+ GAMMA_TABLE_COUNT);
+}
+
+static void s6e8ax0_gamma_update(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xf7, 0x03
+ };
+
+ ops->cmd_write(lcd_to_master(lcd),
+ MIPI_DSI_DCS_SHORT_WRITE_PARAM, data_to_send,
+ ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_etc_cond1(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xd1, 0xfe, 0x80, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x40,
+ 0x0d, 0x00, 0x00
+ };
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_etc_cond2(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xb6, 0x0c, 0x02, 0x03, 0x32, 0xff, 0x44, 0x44, 0xc0,
+ 0x00
+ };
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_etc_cond3(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xe1, 0x10, 0x1c, 0x17, 0x08, 0x1d
+ };
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_etc_cond4(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xe2, 0xed, 0x07, 0xc3, 0x13, 0x0d, 0x03
+ };
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_etc_cond5(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xf4, 0xcf, 0x0a, 0x12, 0x10, 0x19, 0x33, 0x02
+ };
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+static void s6e8ax0_etc_cond6(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xe3, 0x40
+ };
+
+ ops->cmd_write(lcd_to_master(lcd),
+ MIPI_DSI_DCS_SHORT_WRITE_PARAM,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_etc_cond7(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xe4, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00
+ };
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_elvss_set(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xb1, 0x04, 0x00
+ };
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_elvss_nvm_set(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xd9, 0x5c, 0x20, 0x0c, 0x0f, 0x41, 0x00, 0x10, 0x11,
+ 0x12, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcb, 0xed,
+ 0x64, 0xaf
+ };
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_sleep_in(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0x10, 0x00
+ };
+
+ ops->cmd_write(lcd_to_master(lcd),
+ MIPI_DSI_DCS_SHORT_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_sleep_out(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0x11, 0x00
+ };
+
+ ops->cmd_write(lcd_to_master(lcd),
+ MIPI_DSI_DCS_SHORT_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_display_on(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0x29, 0x00
+ };
+
+ ops->cmd_write(lcd_to_master(lcd),
+ MIPI_DSI_DCS_SHORT_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_display_off(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0x28, 0x00
+ };
+
+ ops->cmd_write(lcd_to_master(lcd),
+ MIPI_DSI_DCS_SHORT_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_apply_level2_key(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xf0, 0x5a, 0x5a
+ };
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_acl_on(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xc0, 0x01
+ };
+
+ ops->cmd_write(lcd_to_master(lcd),
+ MIPI_DSI_DCS_SHORT_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+static void s6e8ax0_acl_off(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ static const unsigned char data_to_send[] = {
+ 0xc0, 0x00
+ };
+
+ ops->cmd_write(lcd_to_master(lcd),
+ MIPI_DSI_DCS_SHORT_WRITE,
+ data_to_send, ARRAY_SIZE(data_to_send));
+}
+
+/* Full white 50% reducing setting */
+static void s6e8ax0_acl_ctrl_set(struct s6e8ax0 *lcd)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ /* Full white 50% reducing setting */
+ static const unsigned char cutoff_50[] = {
+ 0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
+ 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2a, 0x31, 0x38,
+ 0x3f, 0x46
+ };
+ /* Full white 45% reducing setting */
+ static const unsigned char cutoff_45[] = {
+ 0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
+ 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x07, 0x0d, 0x13, 0x19, 0x1f, 0x25, 0x2b, 0x31,
+ 0x37, 0x3d
+ };
+ /* Full white 40% reducing setting */
+ static const unsigned char cutoff_40[] = {
+ 0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
+ 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x06, 0x0c, 0x11, 0x16, 0x1c, 0x21, 0x26, 0x2b,
+ 0x31, 0x36
+ };
+
+ if (lcd->acl_enable) {
+ if (lcd->cur_acl = 0) {
+ if (lcd->gamma = 0 || lcd->gamma = 1) {
+ s6e8ax0_acl_off(lcd);
+ dev_dbg(&lcd->ld->dev,
+ "cur_acl=%d\n", lcd->cur_acl);
+ } else
+ s6e8ax0_acl_on(lcd);
+ }
+ switch (lcd->gamma) {
+ case 0: /* 30cd */
+ s6e8ax0_acl_off(lcd);
+ lcd->cur_acl = 0;
+ break;
+ case 1 ... 3: /* 50cd ~ 90cd */
+ ops->cmd_write(lcd_to_master(lcd),
+ MIPI_DSI_DCS_LONG_WRITE,
+ cutoff_40,
+ ARRAY_SIZE(cutoff_40));
+ lcd->cur_acl = 40;
+ break;
+ case 4 ... 7: /* 120cd ~ 210cd */
+ ops->cmd_write(lcd_to_master(lcd),
+ MIPI_DSI_DCS_LONG_WRITE,
+ cutoff_45,
+ ARRAY_SIZE(cutoff_45));
+ lcd->cur_acl = 45;
+ break;
+ case 8 ... 10: /* 220cd ~ 300cd */
+ ops->cmd_write(lcd_to_master(lcd),
+ MIPI_DSI_DCS_LONG_WRITE,
+ cutoff_50,
+ ARRAY_SIZE(cutoff_50));
+ lcd->cur_acl = 50;
+ break;
+ default:
+ break;
+ }
+ } else {
+ s6e8ax0_acl_off(lcd);
+ lcd->cur_acl = 0;
+ dev_dbg(&lcd->ld->dev, "cur_acl = %d\n", lcd->cur_acl);
+ }
+}
+
+static void s6e8ax0_read_id(struct s6e8ax0 *lcd, u8 *mtp_id)
+{
+ unsigned int ret;
+ unsigned int addr = 0xd1; /* MTP ID */
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+
+ ret = ops->cmd_read(lcd_to_master(lcd),
+ MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM,
+ addr, 3, mtp_id);
+}
+
+static int s6e8ax0_panel_init(struct s6e8ax0 *lcd)
+{
+ s6e8ax0_apply_level2_key(lcd);
+ s6e8ax0_sleep_out(lcd);
+ msleep(1);
+ s6e8ax0_panel_cond(lcd);
+ s6e8ax0_display_cond(lcd);
+ s6e8ax0_gamma_cond(lcd);
+ s6e8ax0_gamma_update(lcd);
+
+ s6e8ax0_etc_cond1(lcd);
+ s6e8ax0_etc_cond2(lcd);
+ s6e8ax0_etc_cond3(lcd);
+ s6e8ax0_etc_cond4(lcd);
+ s6e8ax0_etc_cond5(lcd);
+ s6e8ax0_etc_cond6(lcd);
+ s6e8ax0_etc_cond7(lcd);
+
+ s6e8ax0_elvss_nvm_set(lcd);
+ s6e8ax0_elvss_set(lcd);
+
+ s6e8ax0_acl_ctrl_set(lcd);
+ s6e8ax0_acl_on(lcd);
+
+ /* if ID3 value is not 33h, branch private elvss mode */
+ msleep(lcd->ddi_pd->power_on_delay);
+
+ return 0;
+}
+
+static int s6e8ax0_update_gamma_ctrl(struct s6e8ax0 *lcd, int brightness)
+{
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+
+ ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
+ s6e8ax0_22_gamma_table[brightness],
+ ARRAY_SIZE(s6e8ax0_22_gamma_table));
+
+ /* update gamma table. */
+ s6e8ax0_gamma_update(lcd);
+ lcd->gamma = brightness;
+
+ return 0;
+}
+
+static int s6e8ax0_gamma_ctrl(struct s6e8ax0 *lcd, int gamma)
+{
+ s6e8ax0_update_gamma_ctrl(lcd, gamma);
+
+ return 0;
+}
+
+static int s6e8ax0_set_power(struct lcd_device *ld, int power)
+{
+ struct s6e8ax0 *lcd = lcd_get_data(ld);
+ struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
+ int ret = 0;
+
+ if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
+ power != FB_BLANK_NORMAL) {
+ dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
+ return -EINVAL;
+ }
+
+ if ((power = FB_BLANK_UNBLANK) && ops->set_blank_mode) {
+ /* LCD power on */
+ if ((POWER_IS_ON(power) && POWER_IS_OFF(lcd->power))
+ || (POWER_IS_ON(power) && POWER_IS_NRM(lcd->power))) {
+ ret = ops->set_blank_mode(lcd_to_master(lcd), power);
+ if (!ret && lcd->power != power)
+ lcd->power = power;
+ }
+ } else if ((power = FB_BLANK_POWERDOWN) && ops->set_early_blank_mode) {
+ /* LCD power off */
+ if ((POWER_IS_OFF(power) && POWER_IS_ON(lcd->power)) ||
+ (POWER_IS_ON(lcd->power) && POWER_IS_NRM(power))) {
+ ret = ops->set_early_blank_mode(lcd_to_master(lcd),
+ power);
+ if (!ret && lcd->power != power)
+ lcd->power = power;
+ }
+ }
+
+ return ret;
+}
+
+static int s6e8ax0_get_power(struct lcd_device *ld)
+{
+ struct s6e8ax0 *lcd = lcd_get_data(ld);
+
+ return lcd->power;
+}
+
+static int s6e8ax0_get_brightness(struct backlight_device *bd)
+{
+ return bd->props.brightness;
+}
+
+static int s6e8ax0_set_brightness(struct backlight_device *bd)
+{
+ int ret = 0, brightness = bd->props.brightness;
+ struct s6e8ax0 *lcd = bl_get_data(bd);
+
+ if (brightness < MIN_BRIGHTNESS ||
+ brightness > bd->props.max_brightness) {
+ dev_err(lcd->dev, "lcd brightness should be %d to %d.\n",
+ MIN_BRIGHTNESS, MAX_BRIGHTNESS);
+ return -EINVAL;
+ }
+
+ ret = s6e8ax0_gamma_ctrl(lcd, brightness);
+ if (ret) {
+ dev_err(&bd->dev, "lcd brightness setting failed.\n");
+ return -EIO;
+ }
+
+ return ret;
+}
+
+static struct lcd_ops s6e8ax0_lcd_ops = {
+ .set_power = s6e8ax0_set_power,
+ .get_power = s6e8ax0_get_power,
+};
+
+static struct backlight_ops s6e8ax0_backlight_ops = {
+ .get_brightness = s6e8ax0_get_brightness,
+ .update_status = s6e8ax0_set_brightness,
+};
+
+static void s6e8ax0_power_on(struct mipi_dsim_lcd_device *dsim_dev, int power)
+{
+ struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
+
+ msleep(lcd->ddi_pd->power_on_delay);
+
+ /* lcd power on */
+ if (power)
+ s6e8ax0_regulator_enable(lcd);
+ else
+ s6e8ax0_regulator_disable(lcd);
+
+ msleep(lcd->ddi_pd->reset_delay);
+
+ /* lcd reset */
+ if (lcd->ddi_pd->reset)
+ lcd->ddi_pd->reset(lcd->ld);
+ msleep(5);
+}
+
+static void s6e8ax0_set_sequence(struct mipi_dsim_lcd_device *dsim_dev)
+{
+ struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
+
+ s6e8ax0_panel_init(lcd);
+ s6e8ax0_display_on(lcd);
+
+ lcd->power = FB_BLANK_UNBLANK;
+}
+
+static int s6e8ax0_probe(struct mipi_dsim_lcd_device *dsim_dev)
+{
+ struct s6e8ax0 *lcd;
+ int ret;
+ u8 mtp_id[3] = {0, };
+
+ lcd = kzalloc(sizeof(struct s6e8ax0), GFP_KERNEL);
+ if (!lcd) {
+ dev_err(&dsim_dev->dev, "failed to allocate s6e8ax0 structure.\n");
+ return -ENOMEM;
+ }
+
+ lcd->dsim_dev = dsim_dev;
+ lcd->ddi_pd = (struct lcd_platform_data *)dsim_dev->platform_data;
+ lcd->dev = &dsim_dev->dev;
+
+ mutex_init(&lcd->lock);
+
+ ret = regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies);
+ if (ret) {
+ dev_err(lcd->dev, "Failed to get regulators: %d\n", ret);
+ goto err_lcd_register;
+ }
+
+ lcd->ld = lcd_device_register("s6e8ax0", lcd->dev, lcd,
+ &s6e8ax0_lcd_ops);
+ if (IS_ERR(lcd->ld)) {
+ dev_err(lcd->dev, "failed to register lcd ops.\n");
+ ret = PTR_ERR(lcd->ld);
+ goto err_lcd_register;
+ }
+
+ lcd->bd = backlight_device_register("s6e8ax0-bl", lcd->dev, lcd,
+ &s6e8ax0_backlight_ops, NULL);
+ if (IS_ERR(lcd->bd)) {
+ dev_err(lcd->dev, "failed to register backlight ops.\n");
+ ret = PTR_ERR(lcd->bd);
+ goto err_backlight_register;
+ }
+
+ lcd->bd->props.max_brightness = MAX_BRIGHTNESS;
+ lcd->bd->props.brightness = MAX_BRIGHTNESS;
+
+ s6e8ax0_read_id(lcd, mtp_id);
+ if (mtp_id[0] = 0x00)
+ dev_err(lcd->dev, "read id failed\n");
+
+ dev_info(lcd->dev, "Read ID : %x, %x, %x\n",
+ mtp_id[0], mtp_id[1], mtp_id[2]);
+
+ if (mtp_id[2] = 0x33)
+ dev_info(lcd->dev,
+ "ID-3 is 0xff does not support dynamic elvss\n");
+ else
+ dev_info(lcd->dev,
+ "ID-3 is 0x%x support dynamic elvss\n", mtp_id[2]);
+
+ lcd->acl_enable = 1;
+ lcd->cur_acl = 0;
+
+ dev_set_drvdata(&dsim_dev->dev, lcd);
+
+ dev_dbg(lcd->dev, "probed s6e8ax0 panel driver.\n");
+
+ return 0;
+
+err_backlight_register:
+ lcd_device_unregister(lcd->ld);
+
+err_lcd_register:
+ regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
+ kfree(lcd);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int s6e8ax0_suspend(struct mipi_dsim_lcd_device *dsim_dev)
+{
+ struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
+
+ s6e8ax0_sleep_in(lcd);
+ msleep(lcd->ddi_pd->power_off_delay);
+ s6e8ax0_display_off(lcd);
+
+ s6e8ax0_regulator_disable(lcd);
+
+ return 0;
+}
+
+static int s6e8ax0_resume(struct mipi_dsim_lcd_device *dsim_dev)
+{
+ struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
+
+ s6e8ax0_sleep_out(lcd);
+ msleep(lcd->ddi_pd->power_on_delay);
+
+ s6e8ax0_regulator_enable(lcd);
+ s6e8ax0_set_sequence(dsim_dev);
+
+ return 0;
+}
+#else
+#define s6e8ax0_suspend NULL
+#define s6e8ax0_resume NULL
+#endif
+
+static struct mipi_dsim_lcd_driver s6e8ax0_dsim_ddi_driver = {
+ .name = "s6e8ax0",
+ .id = -1,
+
+ .power_on = s6e8ax0_power_on,
+ .set_sequence = s6e8ax0_set_sequence,
+ .probe = s6e8ax0_probe,
+ .suspend = s6e8ax0_suspend,
+ .resume = s6e8ax0_resume,
+};
+
+static int s6e8ax0_init(void)
+{
+ exynos_mipi_dsi_register_lcd_driver(&s6e8ax0_dsim_ddi_driver);
+
+ return 0;
+}
+
+static void s6e8ax0_exit(void)
+{
+ return;
+}
+
+module_init(s6e8ax0_init);
+module_exit(s6e8ax0_exit);
+
+MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
+MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
+MODULE_DESCRIPTION("MIPI-DSI based s6e8ax0 AMOLED LCD Panel Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/s6e8ax0.h b/drivers/video/exynos/s6e8ax0.h
new file mode 100644
index 0000000..1f1b270
--- /dev/null
+++ b/drivers/video/exynos/s6e8ax0.h
@@ -0,0 +1,21 @@
+/* linux/drivers/video/backlight/s6e8ax0.h
+ *
+ * MIPI-DSI based s6e8ax0 AMOLED LCD Panel definitions.
+ *
+ * Copyright (c) 2011 Samsung Electronics
+ *
+ * Inki Dae, <inki.dae@samsung.com>
+ * Donghwa Lee <dh09.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _S6E8AX0_H
+#define _S6E8AX0_H
+
+extern void s6e8ax0_init(void);
+
+#endif
+
--
1.7.4.1
^ permalink raw reply related
* [patch] intelfb: remove some dead code
From: Dan Carpenter @ 2012-01-27 12:45 UTC (permalink / raw)
To: linux-fbdev
The goto on the line before means the return is unreachable. The goto
also returns -ENOMEM so no changes are needed there.
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index c6afa33..02fd226 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -529,7 +529,6 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
ERR_MSG("Could not allocate cmap for intelfb_info.\n");
goto err_out_cmap;
- return -ENODEV;
}
dinfo = info->par;
^ permalink raw reply related
* Re: [patch] intelfb: remove some dead code
From: Dan Carpenter @ 2012-01-27 12:55 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <20120127124536.GA14136@elgon.mountain>
[-- Attachment #1: Type: text/plain, Size: 260 bytes --]
On Fri, Jan 27, 2012 at 03:45:36PM +0300, Dan Carpenter wrote:
> The goto on the line before means the return is unreachable. The goto
> also returns -ENOMEM so no changes are needed there.
I meant ENODEV there. Let me resend this.
regards,
dan carpenter
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* [patch v2] intelfb: remove some dead code
From: Dan Carpenter @ 2012-01-27 12:58 UTC (permalink / raw)
To: linux-fbdev
[-- Attachment #1: Type: text/plain, Size: 702 bytes --]
The goto on the line before means the return is unreachable. The goto
also returns -ENODEV so no changes are needed there.
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
v2: fixed a typo in the commit message
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index c6afa33..02fd226 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -529,7 +529,6 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
ERR_MSG("Could not allocate cmap for intelfb_info.\n");
goto err_out_cmap;
- return -ENODEV;
}
dinfo = info->par;
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply related
* Re: udlfb: remove sysfs framebuffer device with USB .disconnect()
From: Kay Sievers @ 2012-01-27 16:32 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1327090686.1555.2.camel@mop>
On Sat, Jan 21, 2012 at 15:32, Kay Sievers <kay.sievers@vrfy.org> wrote:
> On Sat, 2012-01-21 at 14:13 +0000, Florian Tobias Schandinat wrote:
>> On 01/21/2012 01:57 PM, Kay Sievers wrote:
>
>> > That's true. If one calls the current _unregister() *before* calling
>> > _unlink(), the _unlink() is a NOP. But that's intentional.
>>
>> I don't think you got me right. My complaint was that after your patch
>> do_unregister_framebuffer itself calls unlink_framebuffer _after_ it set
>> registered_fb[i] = NULL;
>> So for any framebuffer that does not call unlink_framebuffer directly the line
>> device_destroy(fb_class, MKDEV(FB_MAJOR, i));
>> will no longer be executed. Do you agree?
>
> Yes, I absolutely agree. :)
Hey Florian,
any updates?
We like to get that into the Fedora kernel, as we promised
out-of-the-box multi-seat hotplug support, but the framebuffer events
are broken at the moment.
It would be nice if it would show up in -next somehow, and gets
testing, so I don't need to convince anybody at the Fedora kernel
side, that this will land upstream ...
Thanks,
Kay
^ permalink raw reply
* Re: [PATCH] atmel_lcdfb: support 16bit BGR:565 mode, remove unsupported 15bit modes
From: Florian Tobias Schandinat @ 2012-01-30 5:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318517570-28459-1-git-send-email-jacmet@sunsite.dk>
On 10/13/2011 02:52 PM, Peter Korsgaard wrote:
> Allow framebuffer to be configured in 16bit mode when panel is wired in
> (the default) BGR configuration, and don't claim to support 15bit input
> modes, which the LCD controller cannot handle.
>
> Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
> drivers/video/atmel_lcdfb.c | 12 +++---------
> 1 files changed, 3 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
> index 7ca3eaf..143f6d9 100644
> --- a/drivers/video/atmel_lcdfb.c
> +++ b/drivers/video/atmel_lcdfb.c
> @@ -418,24 +418,18 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
> var->red.length = var->green.length = var->blue.length
> = var->bits_per_pixel;
> break;
> - case 15:
> case 16:
> if (sinfo->lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB) {
> /* RGB:565 mode */
> var->red.offset = 11;
> var->blue.offset = 0;
> - var->green.length = 6;
> - } else if (sinfo->lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB555) {
> - var->red.offset = 10;
> - var->blue.offset = 0;
> - var->green.length = 5;
> } else {
> - /* BGR:555 mode */
> + /* BGR:565 mode */
> var->red.offset = 0;
> - var->blue.offset = 10;
> - var->green.length = 5;
> + var->blue.offset = 11;
> }
> var->green.offset = 5;
> + var->green.length = 6;
> var->red.length = var->blue.length = 5;
> break;
> case 32:
^ permalink raw reply
* Re: [PATCH v3] video: da8xx-fb: reset LCDC only if functional clock changes with DVFS
From: Florian Tobias Schandinat @ 2012-01-30 5:12 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1325594451-11963-1-git-send-email-prakash.pm@ti.com>
On 01/03/2012 12:40 PM, Manjunathappa, Prakash wrote:
> LCDC functional clock may or may not be derived from CPU/MPU DPLL,
> For example,
> AM335x => Separate independent DPLL for LCDC
> Davinci => Same DPLL as MPU
>
> So, on platforms where LCDC functional clock is not derived from CPU/MPU
> PLL it is not required to reset LCDC module as its functional clock does
> not change with DVFS.
>
> This patch adds check to do reset only if functional clock changes
> between pre and post notifier callbacks with DVFS.
>
> Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
> Since v2:
> Fix, update lcd_fck_rate with current LCD functional clock rate.
> Since v1:
> Fixed the commit message.
>
> drivers/video/da8xx-fb.c | 16 +++++++++++-----
> 1 files changed, 11 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
> index 6b27751..dee1918 100644
> --- a/drivers/video/da8xx-fb.c
> +++ b/drivers/video/da8xx-fb.c
> @@ -163,6 +163,7 @@ struct da8xx_fb_par {
> int vsync_timeout;
> #ifdef CONFIG_CPU_FREQ
> struct notifier_block freq_transition;
> + unsigned int lcd_fck_rate;
> #endif
> void (*panel_power_ctrl)(int);
> };
> @@ -895,11 +896,13 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
> struct da8xx_fb_par *par;
>
> par = container_of(nb, struct da8xx_fb_par, freq_transition);
> - if (val = CPUFREQ_PRECHANGE) {
> - lcd_disable_raster();
> - } else if (val = CPUFREQ_POSTCHANGE) {
> - lcd_calc_clk_divider(par);
> - lcd_enable_raster();
> + if (val = CPUFREQ_POSTCHANGE) {
> + if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) {
> + par->lcd_fck_rate = clk_get_rate(par->lcdc_clk);
> + lcd_disable_raster();
> + lcd_calc_clk_divider(par);
> + lcd_enable_raster();
> + }
> }
>
> return 0;
> @@ -1192,6 +1195,9 @@ static int __devinit fb_probe(struct platform_device *device)
>
> par = da8xx_fb_info->par;
> par->lcdc_clk = fb_clk;
> +#ifdef CONFIG_CPU_FREQ
> + par->lcd_fck_rate = clk_get_rate(fb_clk);
> +#endif
> par->pxl_clk = lcdc_info->pxl_clk;
> if (fb_pdata->panel_power_ctrl) {
> par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
^ permalink raw reply
* Re: [PATCH v2] atmel_lcdfb: fix usage of CONTRAST_CTR in suspend/resume
From: Florian Tobias Schandinat @ 2012-01-30 5:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1326126237-4355-1-git-send-email-nicolas.ferre@atmel.com>
On 01/09/2012 04:23 PM, Nicolas Ferre wrote:
> From: Hubert Feurstein <h.feurstein@gmail.com>
>
> An error was existing in the saving of CONTRAST_CTR register
> across suspend/resume.
>
> Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com>
> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> Cc: stable <stable@vger.kernel.org>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
> drivers/video/atmel_lcdfb.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
> index d7e3712..d99505b 100644
> --- a/drivers/video/atmel_lcdfb.c
> +++ b/drivers/video/atmel_lcdfb.c
> @@ -1102,7 +1102,7 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
> */
> lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
>
> - sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
> + sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR);
> lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
> if (sinfo->atmel_lcdfb_power_control)
> sinfo->atmel_lcdfb_power_control(0);
^ permalink raw reply
* Re: [PATCH] drivers/video: compile fixes for fsl-diu-fb.c
From: Florian Tobias Schandinat @ 2012-01-30 5:14 UTC (permalink / raw)
To: Michael Neuling
Cc: linuxppc-dev@ozlabs.org, linux-fbdev@vger.kernel.org,
Tabi Timur-B04825
In-Reply-To: <21370.1326683320@neuling.org>
On 01/16/2012 03:08 AM, Michael Neuling wrote:
[...]
> From: Michael Neuling <mikey@neuling.org>
>
> [PATCH] drivers/video: compile fixes for fsl-diu-fb.c
>
> Fix a compiler errors introduced in:
> commit ddd3d905436b572ebadc09dcf2d12ca5b37020a0
> Author: Timur Tabi <timur@freescale.com>
> drivers/video: fsl-diu-fb: merge all allocated data into one block
>
> Signed-off-by: Michael Neuling <mikey@neuling.org>
Applied.
Thanks,
Florian Tobias Schandinat
>
> diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
> index acf292b..6af3f16 100644
> --- a/drivers/video/fsl-diu-fb.c
> +++ b/drivers/video/fsl-diu-fb.c
> @@ -1432,7 +1432,7 @@ static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
> struct fsl_diu_data *data;
>
> data = dev_get_drvdata(&ofdev->dev);
> - disable_lcdc(data->fsl_diu_info[0]);
> + disable_lcdc(data->fsl_diu_info);
>
> return 0;
> }
> @@ -1442,7 +1442,7 @@ static int fsl_diu_resume(struct platform_device *ofdev)
> struct fsl_diu_data *data;
>
> data = dev_get_drvdata(&ofdev->dev);
> - enable_lcdc(data->fsl_diu_info[0]);
> + enable_lcdc(data->fsl_diu_info);
>
> return 0;
> }
>
^ permalink raw reply
* Re: [PATCH] video: s3c-fb: Convert to devm style allocation
From: Florian Tobias Schandinat @ 2012-01-30 5:15 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1327151509-10408-1-git-send-email-broonie@opensource.wolfsonmicro.com>
On 01/21/2012 01:11 PM, Mark Brown wrote:
> Saves some code, especially useful as the code saved is mostly in the
> infrequently tested error paths.
>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Acked-by: Jingoo Han <jg1.han@samsung.com>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
>
> devm_request_and_ioremap() is now in Linus' tree.
>
> drivers/video/s3c-fb.c | 32 +++++---------------------------
> 1 files changed, 5 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
> index 0c63b69..7c5158d 100644
> --- a/drivers/video/s3c-fb.c
> +++ b/drivers/video/s3c-fb.c
> @@ -186,7 +186,6 @@ struct s3c_fb_vsync {
> * struct s3c_fb - overall hardware state of the hardware
> * @slock: The spinlock protection for this data sturcture.
> * @dev: The device that we bound to, for printing, etc.
> - * @regs_res: The resource we claimed for the IO registers.
> * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
> * @lcd_clk: The clk (sclk) feeding pixclk.
> * @regs: The mapped hardware registers.
> @@ -202,7 +201,6 @@ struct s3c_fb_vsync {
> struct s3c_fb {
> spinlock_t slock;
> struct device *dev;
> - struct resource *regs_res;
> struct clk *bus_clk;
> struct clk *lcd_clk;
> void __iomem *regs;
> @@ -1361,7 +1359,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
> return -EINVAL;
> }
>
> - sfb = kzalloc(sizeof(struct s3c_fb), GFP_KERNEL);
> + sfb = devm_kzalloc(dev, sizeof(struct s3c_fb), GFP_KERNEL);
> if (!sfb) {
> dev_err(dev, "no memory for framebuffers\n");
> return -ENOMEM;
> @@ -1404,33 +1402,25 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
> goto err_lcd_clk;
> }
>
> - sfb->regs_res = request_mem_region(res->start, resource_size(res),
> - dev_name(dev));
> - if (!sfb->regs_res) {
> - dev_err(dev, "failed to claim register region\n");
> - ret = -ENOENT;
> - goto err_lcd_clk;
> - }
> -
> - sfb->regs = ioremap(res->start, resource_size(res));
> + sfb->regs = devm_request_and_ioremap(dev, res);
> if (!sfb->regs) {
> dev_err(dev, "failed to map registers\n");
> ret = -ENXIO;
> - goto err_req_region;
> + goto err_lcd_clk;
> }
>
> res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> if (!res) {
> dev_err(dev, "failed to acquire irq resource\n");
> ret = -ENOENT;
> - goto err_ioremap;
> + goto err_lcd_clk;
> }
> sfb->irq_no = res->start;
> ret = request_irq(sfb->irq_no, s3c_fb_irq,
> 0, "s3c_fb", sfb);
> if (ret) {
> dev_err(dev, "irq request failed\n");
> - goto err_ioremap;
> + goto err_lcd_clk;
> }
>
> dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
> @@ -1486,12 +1476,6 @@ err_pm_runtime:
> pm_runtime_put_sync(sfb->dev);
> free_irq(sfb->irq_no, sfb);
>
> -err_ioremap:
> - iounmap(sfb->regs);
> -
> -err_req_region:
> - release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
> -
> err_lcd_clk:
> pm_runtime_disable(sfb->dev);
>
> @@ -1505,7 +1489,6 @@ err_bus_clk:
> clk_put(sfb->bus_clk);
>
> err_sfb:
> - kfree(sfb);
> return ret;
> }
>
> @@ -1529,8 +1512,6 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
>
> free_irq(sfb->irq_no, sfb);
>
> - iounmap(sfb->regs);
> -
> if (!sfb->variant.has_clksel) {
> clk_disable(sfb->lcd_clk);
> clk_put(sfb->lcd_clk);
> @@ -1539,12 +1520,9 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
> clk_disable(sfb->bus_clk);
> clk_put(sfb->bus_clk);
>
> - release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
> -
> pm_runtime_put_sync(sfb->dev);
> pm_runtime_disable(sfb->dev);
>
> - kfree(sfb);
> return 0;
> }
>
^ permalink raw reply
* Re: udlfb: remove sysfs framebuffer device with USB .disconnect()
From: Florian Tobias Schandinat @ 2012-01-30 5:16 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1327090686.1555.2.camel@mop>
On 01/21/2012 02:32 PM, Kay Sievers wrote:
[...]
> From: Kay Sievers <kay.sievers@vrfy.org>
> Subject: udlfb: remove sysfs framebuffer device with USB .disconnect()
>
> The USB graphics card driver delays the unregistering of the framebuffer
> device to a workqueue, which breaks the userspace visible remove uevent
> sequence. Recent userspace tools started to support USB graphics card
> hotplug out-of-the-box and rely on proper events sent by the kernel.
>
> The framebuffer device is a direct child of the USB interface which is
> removed immediately after the USB .disconnect() callback. But the fb device
> in /sys stays around until its final cleanup, at a time where all the parent
> devices have been removed already.
>
> To work around that, we remove the sysfs fb device directly in the USB
> .disconnect() callback and leave only the cleanup of the internal fb
> data to the delayed work.
>
> Before:
> add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
> add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
> add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/graphics/fb0 (graphics)
> remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
> remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
> remove /2-1.2:1.0/graphics/fb0 (graphics)
>
> After:
> add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
> add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
> add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/graphics/fb1 (graphics)
> remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/graphics/fb1 (graphics)
> remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
> remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
>
> Cc: stable@vger.kernel.org
> Tested-By: Bernie Thompson <bernie@plugable.com>
> Acked-By: Bernie Thompson <bernie@plugable.com>
> Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
> drivers/video/fbmem.c | 18 +++++++++++++++++-
> drivers/video/udlfb.c | 2 +-
> include/linux/fb.h | 1 +
> 3 files changed, 19 insertions(+), 2 deletions(-)
>
> --- a/drivers/video/fbmem.c
> +++ b/drivers/video/fbmem.c
> @@ -1665,6 +1665,7 @@ static int do_unregister_framebuffer(str
> if (ret)
> return -EINVAL;
>
> + unlink_framebuffer(fb_info);
> if (fb_info->pixmap.addr &&
> (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
> kfree(fb_info->pixmap.addr);
> @@ -1672,7 +1673,6 @@ static int do_unregister_framebuffer(str
> registered_fb[i] = NULL;
> num_registered_fb--;
> fb_cleanup_device(fb_info);
> - device_destroy(fb_class, MKDEV(FB_MAJOR, i));
> event.info = fb_info;
> fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
>
> @@ -1681,6 +1681,22 @@ static int do_unregister_framebuffer(str
> return 0;
> }
>
> +int unlink_framebuffer(struct fb_info *fb_info)
> +{
> + int i;
> +
> + i = fb_info->node;
> + if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
> + return -EINVAL;
> +
> + if (fb_info->dev) {
> + device_destroy(fb_class, MKDEV(FB_MAJOR, i));
> + fb_info->dev = NULL;
> + }
> + return 0;
> +}
> +EXPORT_SYMBOL(unlink_framebuffer);
> +
> void remove_conflicting_framebuffers(struct apertures_struct *a,
> const char *name, bool primary)
> {
> --- a/drivers/video/udlfb.c
> +++ b/drivers/video/udlfb.c
> @@ -1739,7 +1739,7 @@ static void dlfb_usb_disconnect(struct u
> for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
> device_remove_file(info->dev, &fb_device_attrs[i]);
> device_remove_bin_file(info->dev, &edid_attr);
> -
> + unlink_framebuffer(info);
> usb_set_intfdata(interface, NULL);
>
> /* if clients still have us open, will be freed on last close */
> --- a/include/linux/fb.h
> +++ b/include/linux/fb.h
> @@ -1003,6 +1003,7 @@ extern ssize_t fb_sys_write(struct fb_in
> /* drivers/video/fbmem.c */
> extern int register_framebuffer(struct fb_info *fb_info);
> extern int unregister_framebuffer(struct fb_info *fb_info);
> +extern int unlink_framebuffer(struct fb_info *fb_info);
> extern void remove_conflicting_framebuffers(struct apertures_struct *a,
> const char *name, bool primary);
> extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
>
>
>
^ permalink raw reply
* Re: [PATCH 2/4] drivers/video/au*fb.c: use devm_ functions
From: Florian Tobias Schandinat @ 2012-01-30 5:17 UTC (permalink / raw)
To: Julia Lawall; +Cc: Manuel Lauss, kernel-janitors, linux-fbdev, LKML
In-Reply-To: <alpine.DEB.2.02.1201211600580.1939@hadrien>
On 01/21/2012 03:01 PM, Julia Lawall wrote:
> The various devm_ functions allocate memory that is released when a driver
> detaches. This patch uses these functions for data that is allocated in
> the probe function of a platform device and is only freed in the remove
> function.
>
> In au1100fb.c, the probe function now returns -ENODEV on failure.
>
> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
Applied.
Thanks,
Florian Tobias Schandinat
>
> ---
> In the case of au1200fb.c, should the error-handling code under the new
> call to dma_alloc_noncoherent jump to failed, like the other error handling
> code? I was not sure that there was actually anything for failed to do at
> this point in the function.
>
> Added return of -ENODEV.
>
> drivers/video/au1100fb.c | 32 ++++++++++++--------------------
> drivers/video/au1200fb.c | 9 +--------
> 2 files changed, 13 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
> index 04e4479..3e9a773 100644
> --- a/drivers/video/au1200fb.c
> +++ b/drivers/video/au1200fb.c
> @@ -1724,7 +1724,7 @@ static int __devinit au1200fb_drv_probe(struct
> platform_device *dev)
> /* Allocate the framebuffer to the maximum screen size */
> fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp)
> / 8;
>
> - fbdev->fb_mem = dma_alloc_noncoherent(&dev->dev,
> + fbdev->fb_mem = dmam_alloc_noncoherent(&dev->dev, &dev->dev,
> PAGE_ALIGN(fbdev->fb_len),
> &fbdev->fb_phys, GFP_KERNEL);
> if (!fbdev->fb_mem) {
> @@ -1788,9 +1788,6 @@ static int __devinit au1200fb_drv_probe(struct
> platform_device *dev)
>
> failed:
> /* NOTE: This only does the current plane/window that failed;
> others are still active */
> - if (fbdev->fb_mem)
> - dma_free_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len),
> - fbdev->fb_mem, fbdev->fb_phys);
> if (fbi) {
> if (fbi->cmap.len != 0)
> fb_dealloc_cmap(&fbi->cmap);
> @@ -1817,10 +1814,6 @@ static int __devexit au1200fb_drv_remove(struct
> platform_device *dev)
>
> /* Clean up all probe data */
> unregister_framebuffer(fbi);
> - if (fbdev->fb_mem)
> - dma_free_noncoherent(&dev->dev,
> - PAGE_ALIGN(fbdev->fb_len),
> - fbdev->fb_mem, fbdev->fb_phys);
> if (fbi->cmap.len != 0)
> fb_dealloc_cmap(&fbi->cmap);
> kfree(fbi->pseudo_palette);
> diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
> index de9da67..befcbd8 100644
> --- a/drivers/video/au1100fb.c
> +++ b/drivers/video/au1100fb.c
> @@ -477,7 +477,8 @@ static int __devinit au1100fb_drv_probe(struct
> platform_device *dev)
> u32 sys_clksrc;
>
> /* Allocate new device private */
> - fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL);
> + fbdev = devm_kzalloc(&dev->dev, sizeof(struct au1100fb_device),
> + GFP_KERNEL);
> if (!fbdev) {
> print_err("fail to allocate device private record");
> return -ENOMEM;
> @@ -498,8 +499,9 @@ static int __devinit au1100fb_drv_probe(struct
> platform_device *dev)
> au1100fb_fix.mmio_start = regs_res->start;
> au1100fb_fix.mmio_len = resource_size(regs_res);
>
> - if (!request_mem_region(au1100fb_fix.mmio_start,
> au1100fb_fix.mmio_len,
> - DRIVER_NAME)) {
> + if (!devm_request_mem_region(au1100fb_fix.mmio_start,
> + au1100fb_fix.mmio_len,
> + DRIVER_NAME)) {
> print_err("fail to lock memory region at 0x%08lx",
> au1100fb_fix.mmio_start);
> return -EBUSY;
> @@ -514,8 +516,9 @@ static int __devinit au1100fb_drv_probe(struct
> platform_device *dev)
> fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
> (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
>
> - fbdev->fb_mem = dma_alloc_coherent(&dev->dev,
> PAGE_ALIGN(fbdev->fb_len),
> - &fbdev->fb_phys, GFP_KERNEL);
> + fbdev->fb_mem = dmam_alloc_coherent(&dev->dev, &dev->dev,
> + PAGE_ALIGN(fbdev->fb_len),
> + &fbdev->fb_phys, GFP_KERNEL);
> if (!fbdev->fb_mem) {
> print_err("fail to allocate frambuffer (size: %dK))",
> fbdev->fb_len / 1024);
> @@ -557,14 +560,14 @@ static int __devinit au1100fb_drv_probe(struct
> platform_device *dev)
> fbdev->info.fbops = &au1100fb_ops;
> fbdev->info.fix = au1100fb_fix;
>
> - if (!(fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16,
> GFP_KERNEL))) {
> + fbdev->info.pseudo_palette > + devm_kzalloc(&dev->dev, sizeof(u32) * 16, GFP_KERNEL);
> + if (!fbdev->info.pseudo_palette)
> return -ENOMEM;
> - }
>
> if (fb_alloc_cmap(&fbdev->info.cmap,
> AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
> print_err("Fail to allocate colormap (%d entries)",
> AU1100_LCD_NBR_PALETTE_ENTRIES);
> - kfree(fbdev->info.pseudo_palette);
> return -EFAULT;
> }
>
> @@ -582,9 +585,6 @@ static int __devinit au1100fb_drv_probe(struct
> platform_device *dev)
> return 0;
>
> failed:
> - if (fbdev->regs) {
> - release_mem_region(fbdev->regs_phys, fbdev->regs_len);
> - }
> if (fbdev->fb_mem) {
> dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem,
> fbdev->fb_phys);
> @@ -592,10 +592,9 @@ failed:
> if (fbdev->info.cmap.len != 0) {
> fb_dealloc_cmap(&fbdev->info.cmap);
> }
> - kfree(fbdev);
> platform_set_drvdata(dev, NULL);
>
> - return 0;
> + return -ENODEV;
> }
>
> int au1100fb_drv_remove(struct platform_device *dev)
> @@ -615,14 +614,7 @@ int au1100fb_drv_remove(struct platform_device *dev)
> /* Clean up all probe data */
> unregister_framebuffer(&fbdev->info);
>
> - release_mem_region(fbdev->regs_phys, fbdev->regs_len);
> -
> - dma_free_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem,
> - fbdev->fb_phys);
> -
> fb_dealloc_cmap(&fbdev->info.cmap);
> - kfree(fbdev->info.pseudo_palette);
> - kfree((void*)fbdev);
>
> return 0;
> }
>
^ permalink raw reply
* Re: [PATCH] video: use gpio_request_one
From: Florian Tobias Schandinat @ 2012-01-30 5:17 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <000d01ccdc15$d0e2a500$72a7ef00$%han@samsung.com>
On 01/26/2012 10:32 AM, Jingoo Han wrote:
> Using gpio_request_one can make the code simpler because it can
> set the direction and initial value in one shot.
>
> Signed-off-by: Jingoo Han <jg1.han@samsung.com>
> Cc: Michael Hennerich <michael.hennerich@analog.com>
> Cc: Pavel Machek <pavel@ucw.cz>
> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
> drivers/video/bf537-lq035.c | 12 +++---------
> drivers/video/bf54x-lq043fb.c | 4 +---
> drivers/video/bfin-lq035q1-fb.c | 8 ++++----
> drivers/video/bfin_adv7393fb.c | 5 +++--
> drivers/video/msm/mddi_client_nt35399.c | 7 +------
> drivers/video/msm/mddi_client_toshiba.c | 7 +------
> drivers/video/omap/lcd_inn1610.c | 10 ++++------
> drivers/video/omap2/displays/panel-taal.c | 4 +---
> .../video/omap2/displays/panel-tpo-td043mtea1.c | 11 ++---------
> 9 files changed, 20 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/video/bf537-lq035.c b/drivers/video/bf537-lq035.c
> index bea53c1..befbc80 100644
> --- a/drivers/video/bf537-lq035.c
> +++ b/drivers/video/bf537-lq035.c
> @@ -383,23 +383,19 @@ static int __devinit request_ports(void)
> }
>
> #if (defined(UD) && defined(LBR))
> - if (gpio_request(UD, KBUILD_MODNAME)) {
> + if (gpio_request_one(UD, GPIOF_OUT_INIT_LOW, KBUILD_MODNAME)) {
> pr_err("requesting GPIO %d failed\n", UD);
> return -EBUSY;
> }
>
> - if (gpio_request(LBR, KBUILD_MODNAME)) {
> + if (gpio_request_one(LBR, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME)) {
> pr_err("requesting GPIO %d failed\n", LBR);
> gpio_free(UD);
> return -EBUSY;
> }
> -
> - gpio_direction_output(UD, 0);
> - gpio_direction_output(LBR, 1);
> -
> #endif
>
> - if (gpio_request(MOD, KBUILD_MODNAME)) {
> + if (gpio_request_one(MOD, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME)) {
> pr_err("requesting GPIO %d failed\n", MOD);
> #if (defined(UD) && defined(LBR))
> gpio_free(LBR);
> @@ -408,8 +404,6 @@ static int __devinit request_ports(void)
> return -EBUSY;
> }
>
> - gpio_direction_output(MOD, 1);
> -
> SSYNC();
> return 0;
> }
> diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
> index 46b03f5..dc2f004 100644
> --- a/drivers/video/bf54x-lq043fb.c
> +++ b/drivers/video/bf54x-lq043fb.c
> @@ -240,7 +240,7 @@ static int request_ports(struct bfin_bf54xfb_info *fbi)
> u16 eppi_req_18[] = EPPI0_18;
> u16 disp = fbi->mach_info->disp;
>
> - if (gpio_request(disp, DRIVER_NAME)) {
> + if (gpio_request_one(disp, GPIOF_OUT_INIT_HIGH, DRIVER_NAME)) {
> printk(KERN_ERR "Requesting GPIO %d failed\n", disp);
> return -EFAULT;
> }
> @@ -263,8 +263,6 @@ static int request_ports(struct bfin_bf54xfb_info *fbi)
> }
> }
>
> - gpio_direction_output(disp, 1);
> -
> return 0;
> }
>
> diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
> index c633068..86922ac 100644
> --- a/drivers/video/bfin-lq035q1-fb.c
> +++ b/drivers/video/bfin-lq035q1-fb.c
> @@ -365,10 +365,10 @@ static int __devinit bfin_lq035q1_request_ports(struct platform_device *pdev,
> * Drive PPI_FS3 Low
> */
> if (ANOMALY_05000400) {
> - int ret = gpio_request(P_IDENT(P_PPI0_FS3), "PPI_FS3");
> + int ret = gpio_request_one(P_IDENT(P_PPI0_FS3),
> + GPIOF_OUT_INIT_LOW, "PPI_FS3");
> if (ret)
> return ret;
> - gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
> }
>
> if (ppi16)
> @@ -716,14 +716,14 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
> }
>
> if (info->disp_info->use_bl) {
> - ret = gpio_request(info->disp_info->gpio_bl, "LQ035 Backlight");
> + ret = gpio_request_one(info->disp_info->gpio_bl,
> + GPIOF_OUT_INIT_LOW, "LQ035 Backlight");
>
> if (ret) {
> dev_err(&pdev->dev, "failed to request GPIO %d\n",
> info->disp_info->gpio_bl);
> goto out9;
> }
> - gpio_direction_output(info->disp_info->gpio_bl, 0);
> }
>
> ret = register_framebuffer(fbinfo);
> diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c
> index 811dd7f..c992814 100644
> --- a/drivers/video/bfin_adv7393fb.c
> +++ b/drivers/video/bfin_adv7393fb.c
> @@ -411,12 +411,13 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
>
> /* Workaround "PPI Does Not Start Properly In Specific Mode" */
> if (ANOMALY_05000400) {
> - if (gpio_request(P_IDENT(P_PPI0_FS3), "PPI0_FS3")) {
> + ret = gpio_request_one(P_IDENT(P_PPI0_FS3), GPIOF_OUT_INIT_LOW,
> + "PPI0_FS3")
> + if (ret) {
> dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n");
> ret = -EBUSY;
> goto out_8;
> }
> - gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
> }
>
> if (peripheral_request_list(ppi_pins, DRIVER_NAME)) {
> diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c
> index f239f4a..7fcd67e 100644
> --- a/drivers/video/msm/mddi_client_nt35399.c
> +++ b/drivers/video/msm/mddi_client_nt35399.c
> @@ -155,14 +155,10 @@ static int setup_vsync(struct panel_info *panel, int init)
> ret = 0;
> goto uninit;
> }
> - ret = gpio_request(gpio, "vsync");
> + ret = gpio_request_one(gpio, GPIOF_IN, "vsync");
> if (ret)
> goto err_request_gpio_failed;
>
> - ret = gpio_direction_input(gpio);
> - if (ret)
> - goto err_gpio_direction_input_failed;
> -
> ret = irq = gpio_to_irq(gpio);
> if (ret < 0)
> goto err_get_irq_num_failed;
> @@ -180,7 +176,6 @@ uninit:
> free_irq(gpio_to_irq(gpio), panel->client_data);
> err_request_irq_failed:
> err_get_irq_num_failed:
> -err_gpio_direction_input_failed:
> gpio_free(gpio);
> err_request_gpio_failed:
> return ret;
> diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/msm/mddi_client_toshiba.c
> index f9bc932..053eb68 100644
> --- a/drivers/video/msm/mddi_client_toshiba.c
> +++ b/drivers/video/msm/mddi_client_toshiba.c
> @@ -186,14 +186,10 @@ static int setup_vsync(struct panel_info *panel,
> ret = 0;
> goto uninit;
> }
> - ret = gpio_request(gpio, "vsync");
> + ret = gpio_request_one(gpio, GPIOF_IN, "vsync");
> if (ret)
> goto err_request_gpio_failed;
>
> - ret = gpio_direction_input(gpio);
> - if (ret)
> - goto err_gpio_direction_input_failed;
> -
> ret = irq = gpio_to_irq(gpio);
> if (ret < 0)
> goto err_get_irq_num_failed;
> @@ -210,7 +206,6 @@ uninit:
> free_irq(gpio_to_irq(gpio), panel);
> err_request_irq_failed:
> err_get_irq_num_failed:
> -err_gpio_direction_input_failed:
> gpio_free(gpio);
> err_request_gpio_failed:
> return ret;
> diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
> index 7e8bd8e..e3d3d13 100644
> --- a/drivers/video/omap/lcd_inn1610.c
> +++ b/drivers/video/omap/lcd_inn1610.c
> @@ -22,7 +22,7 @@
> #include <linux/module.h>
> #include <linux/platform_device.h>
>
> -#include <asm/gpio.h>
> +#include <linux/gpio.h>
> #include "omapfb.h"
>
> #define MODULE_NAME "omapfb-lcd_h3"
> @@ -32,20 +32,18 @@ static int innovator1610_panel_init(struct lcd_panel *panel,
> {
> int r = 0;
>
> - if (gpio_request(14, "lcd_en0")) {
> + /* configure GPIO(14, 15) as outputs */
> + if (gpio_request_one(14, GPIOF_OUT_INIT_LOW, "lcd_en0")) {
> pr_err(MODULE_NAME ": can't request GPIO 14\n");
> r = -1;
> goto exit;
> }
> - if (gpio_request(15, "lcd_en1")) {
> + if (gpio_request_one(15, GPIOF_OUT_INIT_LOW, "lcd_en1")) {
> pr_err(MODULE_NAME ": can't request GPIO 15\n");
> gpio_free(14);
> r = -1;
> goto exit;
> }
> - /* configure GPIO(14, 15) as outputs */
> - gpio_direction_output(14, 0);
> - gpio_direction_output(15, 0);
> exit:
> return r;
> }
> diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
> index 00c5c61..0f21fa5 100644
> --- a/drivers/video/omap2/displays/panel-taal.c
> +++ b/drivers/video/omap2/displays/panel-taal.c
> @@ -1019,14 +1019,12 @@ static int taal_probe(struct omap_dss_device *dssdev)
> if (panel_data->use_ext_te) {
> int gpio = panel_data->ext_te_gpio;
>
> - r = gpio_request(gpio, "taal irq");
> + r = gpio_request_one(gpio, GPIOF_IN, "taal irq");
> if (r) {
> dev_err(&dssdev->dev, "GPIO request failed\n");
> goto err_gpio;
> }
>
> - gpio_direction_input(gpio);
> -
> r = request_irq(gpio_to_irq(gpio), taal_te_isr,
> IRQF_TRIGGER_RISING,
> "taal vsync", dssdev);
> diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
> index e6649aa..880c313 100644
> --- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
> +++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
> @@ -408,17 +408,12 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
> }
>
> if (gpio_is_valid(nreset_gpio)) {
> - ret = gpio_request(nreset_gpio, "lcd reset");
> + ret = gpio_request_one(nreset_gpio, GPIOF_OUT_INIT_LOW,
> + "lcd reset");
> if (ret < 0) {
> dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
> goto fail_gpio_req;
> }
> -
> - ret = gpio_direction_output(nreset_gpio, 0);
> - if (ret < 0) {
> - dev_err(&dssdev->dev, "couldn't set GPIO direction\n");
> - goto fail_gpio_direction;
> - }
> }
>
> ret = sysfs_create_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
> @@ -427,8 +422,6 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
>
> return 0;
>
> -fail_gpio_direction:
> - gpio_free(nreset_gpio);
> fail_gpio_req:
> regulator_put(tpo_td043->vcc_reg);
> fail_regulator:
^ permalink raw reply
* Re: [PATCH] video: s3c-fb: fix checkpatch error
From: Florian Tobias Schandinat @ 2012-01-30 5:18 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1301642247-20926-1-git-send-email-jg1.han@samsung.com>
On 01/26/2012 10:38 AM, Jingoo Han wrote:
> This patch fixes the checkpatch error listed below:
>
> ERROR: trailing statements should be on next line
>
> Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
> drivers/video/s3c-fb.c | 3 ++-
> 1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
> index 7c5158d..389189a 100644
> --- a/drivers/video/s3c-fb.c
> +++ b/drivers/video/s3c-fb.c
> @@ -48,7 +48,8 @@
> #undef writel
> #define writel(v, r) do { \
> printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \
> - __raw_writel(v, r); } while (0)
> + __raw_writel(v, r); \
> +} while (0)
> #endif /* FB_S3C_DEBUG_REGWRITE */
>
> /* irq_flags bits */
^ permalink raw reply
* Re: [GIT PULL] OMAP DSS fixes for 3.3-rc
From: Florian Tobias Schandinat @ 2012-01-30 5:22 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: linux-fbdev@vger.kernel.org, linux-omap mailing list
In-Reply-To: <1327579651.1895.34.camel@deskari>
Hi Tomi,
On 01/26/2012 12:07 PM, Tomi Valkeinen wrote:
> Hi Florian,
>
> Here are two major fixes for OMAP DSS driver.
>
> The first (OMAPDSS: use sync versions...) fixes problem with system
> suspend, which causes omapdss power management to give WARNs and
> generally malfunction on system suspend/resume.
>
> The second (the rest of the patches) implements a workaround for HW bug,
> which causes physical damage to the board if the HDMI cable is
> disconnected at a "wrong" time. The actual fix is in the last patch, but
> the board files needed some cleanups and a new GPIO, which is what the
> smaller patches do.
>
> The branch is based on fbdev/fbdev-next. Is that ok?
Yes, that worked well, as I didn't start to collect 3.4 material there. Merged.
Thanks,
Florian Tobias Schandinat
>
> Tomi
>
>
> The following changes since commit f787f32e67e00b072f46b2ae3c454d2c0a1fcdb7:
>
> module_param: make bool parameters really bool (drivers/video/i810) (2012-01-12 23:28:59 +0000)
>
> are available in the git repository at:
> git://gitorious.org/linux-omap-dss2/linux.git for-3.3-rc
>
> Tomi Valkeinen (7):
> OMAPDSS: use sync versions of pm_runtime_put
> OMAP: 4430SDP/Panda: use gpio_free_array to free HDMI gpios
> OMAP: 4430SDP/Panda: rename HPD GPIO to CT_CP_HPD
> OMAPDSS: remove wrong HDMI HPD muxing
> OMAP: 4430SDP/Panda: setup HDMI GPIO muxes
> OMAP: 4430SDP/Panda: add HDMI HPD gpio
> OMAPDSS: HDMI: PHY burnout fix
>
> arch/arm/mach-omap2/board-4430sdp.c | 18 ++++++--
> arch/arm/mach-omap2/board-omap4panda.c | 18 ++++++--
> arch/arm/mach-omap2/display.c | 4 --
> drivers/video/omap2/dss/dispc.c | 2 +-
> drivers/video/omap2/dss/dsi.c | 2 +-
> drivers/video/omap2/dss/dss.c | 2 +-
> drivers/video/omap2/dss/hdmi.c | 5 ++-
> drivers/video/omap2/dss/rfbi.c | 2 +-
> drivers/video/omap2/dss/ti_hdmi.h | 4 ++
> drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 68 +++++++++++++++++++++++++++--
> drivers/video/omap2/dss/venc.c | 2 +-
> include/video/omapdss.h | 5 ++
> 12 files changed, 110 insertions(+), 22 deletions(-)
>
^ 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