Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* RE: [PATCH v2 3/3] ARM: Samsung: Rework platform data of s3c-fb driver
From: Jingoo Han @ 2012-03-15  0:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4F60E5C8.3040804@gmail.com>

> -----Original Message-----
> From: Darius Augulis [mailto:augulis.darius@gmail.com]
> Sent: Thursday, March 15, 2012 3:39 AM
> To: Jingoo Han
> Cc: 'Thomas Abraham'; linux-fbdev@vger.kernel.org; FlorianSchandinat@gmx.de; linux-arm-
> kernel@lists.infradead.org; linux-samsung-soc@vger.kernel.org; kgene.kim@samsung.com; ben-
> linux@fluff.org; patches@linaro.org; 'Kyungmin Park'; 'JeongHyeon Kim'; 'Heiko Stuebner'; 'Kwangwoo Lee';
> 'Mark Brown'; 'Peter Korsgaard'; 'Maurus Cuelenaere'
> Subject: Re: [PATCH v2 3/3] ARM: Samsung: Rework platform data of s3c-fb driver
> 
> On 03/14/2012 03:51 AM, Jingoo Han wrote:
> >> -----Original Message-----
> >> From: Thomas Abraham [mailto:thomas.abraham@linaro.org]
> >> Sent: Tuesday, March 13, 2012 7:11 PM
> >> To: Jingoo Han
> >> Cc: linux-fbdev@vger.kernel.org; FlorianSchandinat@gmx.de; linux-arm-kernel@lists.infradead.org;
> linux-
> >> samsung-soc@vger.kernel.org; kgene.kim@samsung.com; ben-linux@fluff.org; patches@linaro.org; Kyungmin
> >> Park; JeongHyeon Kim; Heiko Stuebner; Kwangwoo Lee; Mark Brown; Peter Korsgaard; Darius Augulis;
> Maurus
> >> Cuelenaere
> >> Subject: Re: [PATCH v2 3/3] ARM: Samsung: Rework platform data of s3c-fb driver
> >>
> >> On 13 March 2012 15:17, Jingoo Han<jg1.han@samsung.com>  wrote:
> >>>> -----Original Message-----
> >>>> From: Thomas Abraham [mailto:thomas.abraham@linaro.org]
> >>>> Sent: Tuesday, March 13, 2012 6:00 AM
> >>>> To: linux-fbdev@vger.kernel.org
> >>>> Cc: FlorianSchandinat@gmx.de; linux-arm-kernel@lists.infradead.org; linux-samsung-
> soc@vger.kernel.org;
> >>>> kgene.kim@samsung.com; jg1.han@samsung.com; ben-linux@fluff.org; patches@linaro.org; Kyungmin Park;
> >>>> JeongHyeon Kim; Heiko Stuebner; Kwangwoo Lee; Mark Brown; Peter Korsgaard; Darius Augulis; Maurus
> >>>> Cuelenaere
> >>>> Subject: [PATCH v2 3/3] ARM: Samsung: Rework platform data of s3c-fb driver
> >>>>
> >>>> For all the Samsung SoC based boards which have the platform data for
> >>>> s3c-fb driver, the 'default_win' element in the platform data is removed
> >>>> and the lcd panel video timing values are moved out of individual window
> >>>> configuration data.
> >>>>
> >>>> Cc: Jingoo Han<jg1.han@samsung.com>
> >>>> Cc: Kyungmin Park<kyungmin.park@samsung.com>
> >>>> Cc: JeongHyeon Kim<jhkim@insignal.co.kr>
> >>>> Cc: Kukjin Kim<kgene.kim@samsung.com>
> >>>> Cc: Heiko Stuebner<heiko@sntech.de>
> >>>> Cc: Ben Dooks<ben-linux@fluff.org>
> >>>> Cc: Kwangwoo Lee<kwangwoo.lee@gmail.com>
> >>>> Cc: Mark Brown<broonie@opensource.wolfsonmicro.com>
> >>>> Cc: Peter Korsgaard<jacmet@sunsite.dk>
> >>>> Cc: Darius Augulis<augulis.darius@gmail.com>
> >>>> Cc: Maurus Cuelenaere<mcuelenaere@gmail.com>
> >>>> Signed-off-by: Thomas Abraham<thomas.abraham@linaro.org>
> >>>> ---
> >>>>   arch/arm/mach-exynos/mach-nuri.c           |   26 ++++++++++-------
> >>>>   arch/arm/mach-exynos/mach-origen.c         |   24 ++++++++++-------
> >>>>   arch/arm/mach-exynos/mach-smdkv310.c       |   28 +++++++++++--------
> >>>>   arch/arm/mach-exynos/mach-universal_c210.c |   26 ++++++++++-------
> >>>>   arch/arm/mach-s3c24xx/mach-smdk2416.c      |   27 ++++++++++--------
> >>>>   arch/arm/mach-s3c64xx/mach-anw6410.c       |   25 ++++++++++-------
> >>>>   arch/arm/mach-s3c64xx/mach-crag6410.c      |   25 ++++++++++-------
> >>>>   arch/arm/mach-s3c64xx/mach-hmt.c           |   24 ++++++++++-------
> >>>>   arch/arm/mach-s3c64xx/mach-mini6410.c      |   40 ++++++++++++---------------
> >>>>   arch/arm/mach-s3c64xx/mach-real6410.c      |   40 ++++++++++++---------------
> >>>>   arch/arm/mach-s3c64xx/mach-smartq5.c       |   26 ++++++++++-------
> >>>>   arch/arm/mach-s3c64xx/mach-smartq7.c       |   26 ++++++++++-------
> >>>>   arch/arm/mach-s3c64xx/mach-smdk6410.c      |   25 ++++++++++-------
> >>>>   arch/arm/mach-s5p64x0/mach-smdk6440.c      |   24 ++++++++++-------
> >>>>   arch/arm/mach-s5p64x0/mach-smdk6450.c      |   24 ++++++++++-------
> >>>>   arch/arm/mach-s5pc100/mach-smdkc100.c      |   27 ++++++++++--------
> >>>>   arch/arm/mach-s5pv210/mach-aquila.c        |   36 +++++++++++--------------
> >>>>   arch/arm/mach-s5pv210/mach-goni.c          |   26 ++++++++++-------
> >>>>   arch/arm/mach-s5pv210/mach-smdkv210.c      |   24 ++++++++++-------
> >>>>   19 files changed, 285 insertions(+), 238 deletions(-)
> >>>>
> >>> [.....]
> >>>
> >>>> diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
> >>>> index c34c2ab..24dcdc9 100644
> >>>> --- a/arch/arm/mach-s3c64xx/mach-mini6410.c
> >>>> +++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
> >>>> @@ -153,36 +153,32 @@ static struct s3c2410_platform_nand mini6410_nand_info = {
> >>>>
> >>>>   static struct s3c_fb_pd_win mini6410_fb_win[] = {
> >>>>        {
> >>>> -             .win_mode       = {     /* 4.3" 480x272 */
> >>>> -                     .left_margin    = 3,
> >>>> -                     .right_margin   = 2,
> >>>> -                     .upper_margin   = 1,
> >>>> -                     .lower_margin   = 1,
> >>>> -                     .hsync_len      = 40,
> >>>> -                     .vsync_len      = 1,
> >>>> -                     .xres           = 480,
> >>>> -                     .yres           = 272,
> >>>> -             },
> >>>>                .max_bpp        = 32,
> >>>>                .default_bpp    = 16,
> >>>> +             .xres           = 480,
> >>>> +             .yres           = 272,
> >>>>        }, {
> >>>> -             .win_mode       = {     /* 7.0" 800x480 */
> >>>> -                     .left_margin    = 8,
> >>>> -                     .right_margin   = 13,
> >>>> -                     .upper_margin   = 7,
> >>>> -                     .lower_margin   = 5,
> >>>> -                     .hsync_len      = 3,
> >>>> -                     .vsync_len      = 1,
> >>>> -                     .xres           = 800,
> >>>> -                     .yres           = 480,
> >>>> -             },
> >>>>                .max_bpp        = 32,
> >>>>                .default_bpp    = 16,
> >>>> +             .xres           = 800,
> >>>> +             .yres           = 480,
> >>>>        },
> >>>>   };
> >>>>
> >>>> +static struct fb_videomode mini6410_lcd_timing = {
> >>>> +     .left_margin    = 8,
> >>>> +     .right_margin   = 13,
> >>>> +     .upper_margin   = 7,
> >>>> +     .lower_margin   = 5,
> >>>> +     .hsync_len      = 3,
> >>>> +     .vsync_len      = 1,
> >>>> +     .xres           = 800,
> >>>> +     .yres           = 480,
> >>>> +};
> >>>> +
> >>>>   static struct s3c_fb_platdata mini6410_lcd_pdata __initdata = {
> >>>>        .setup_gpio     = s3c64xx_fb_gpio_setup_24bpp,
> >>>> +     .vtiming        =&mini6410_lcd_timing,
> >>>>        .win[0]         =&mini6410_fb_win[0],
> >>>>        .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
> >>>>        .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
> >>>> @@ -310,8 +306,8 @@ static void __init mini6410_machine_init(void)
> >>>>        mini6410_lcd_pdata.win[0] =&mini6410_fb_win[features.lcd_index];
> >>>>
> >>>>        printk(KERN_INFO "MINI6410: selected LCD display is %dx%d\n",
> >>>> -             mini6410_lcd_pdata.win[0]->win_mode.xres,
> >>>> -             mini6410_lcd_pdata.win[0]->win_mode.yres);
> >>>> +             mini6410_lcd_pdata.win[0]->xres,
> >>>> +             mini6410_lcd_pdata.win[0]->yres);
> >>>>
> >>>>        s3c_nand_set_platdata(&mini6410_nand_info);
> >>>>        s3c_fb_set_platdata(&mini6410_lcd_pdata);
> >>>> diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
> >>>> index be2a9a2..41e4f74 100644
> >>>> --- a/arch/arm/mach-s3c64xx/mach-real6410.c
> >>>> +++ b/arch/arm/mach-s3c64xx/mach-real6410.c
> >>>> @@ -119,36 +119,32 @@ static struct platform_device real6410_device_eth = {
> >>>>
> >>>>   static struct s3c_fb_pd_win real6410_fb_win[] = {
> >>>>        {
> >>>> -             .win_mode       = {     /* 4.3" 480x272 */
> >>>> -                     .left_margin    = 3,
> >>>> -                     .right_margin   = 2,
> >>>> -                     .upper_margin   = 1,
> >>>> -                     .lower_margin   = 1,
> >>>> -                     .hsync_len      = 40,
> >>>> -                     .vsync_len      = 1,
> >>>> -                     .xres           = 480,
> >>>> -                     .yres           = 272,
> >>>> -             },
> >>>>                .max_bpp        = 32,
> >>>>                .default_bpp    = 16,
> >>>> +             .xres           = 480,
> >>>> +             .yres           = 272,
> >>>>        }, {
> >>>> -             .win_mode       = {     /* 7.0" 800x480 */
> >>>> -                     .left_margin    = 8,
> >>>> -                     .right_margin   = 13,
> >>>> -                     .upper_margin   = 7,
> >>>> -                     .lower_margin   = 5,
> >>>> -                     .hsync_len      = 3,
> >>>> -                     .vsync_len      = 1,
> >>>> -                     .xres           = 800,
> >>>> -                     .yres           = 480,
> >>>> -             },
> >>>>                .max_bpp        = 32,
> >>>>                .default_bpp    = 16,
> >>>> +             .xres           = 800,
> >>>> +             .yres           = 480,
> >>>>        },
> >>>>   };
> >>>>
> >>>> +static struct fb_videomode real6410_lcd_timing = {
> >>>> +     .left_margin    = 3,
> >>>> +     .right_margin   = 2,
> >>>> +     .upper_margin   = 1,
> >>>> +     .lower_margin   = 1,
> >>>> +     .hsync_len      = 40,
> >>>> +     .vsync_len      = 1,
> >>>> +     .xres           = 800,
> >>>> +     .yres           = 480,
> >>>> +};
> >>>
> >>> What is the difference between mini6410_lcd_timing and real6410_lcd_timing?
> >>> In my opinion, it would be good as follows:
> >>>
> >>> +static struct fb_videomode real6410_lcd_timing = {
> >>> +       .left_margin    = 8,
> >>> +       .right_margin   = 13,
> >>> +       .upper_margin   = 7,
> >>> +       .lower_margin   = 5,
> >>> +       .hsync_len      = 3,
> >>> +       .vsync_len      = 1,
> >>> +       .xres           = 800,
> >>> +       .yres           = 480,
> >>> +};
> >>>
> >>>
> >> Before this patch series, both real6410 and mini6410 had 'default_win'
> >> = 0 in the platform data. And, the s3c-fb driver selected the video
> >> timing from the window selected by the default_win parameter in s3c-fb
> >> platform data, i.e window 0 for both mini6440 and real6410. So, in
> >> this patch, while moving the timing values out of window data, the
> >> timing values for window 0 was selected.
> >>
> >> The timing value for window 1 was never used on mini6410 and real6410.
> >> So I would suggest to use timing value of window 0 in this patch.
> > OK, I see.
> > Then, as you mentioned above, the timing value of mini6410 and real6410 should be same.
> > Also, the mini6410 should use the timing value for window 0 as below.
> >
> > Also, this timing value is used for 4.3" 480x272 LCD.
> > So, xres and yres would be 480 and 272, respectively, instead of 800 and 480.
> >
> > The mini6410 seems to use 4.3" 480x272 LCD as default LCD.
> > Please refer to 'http://www.friendlyarm.net/products/mini6410'.
> >
> > Also, real6410 seems to use 4.3" 480x272 LCD as default LCD.
> > http://s3c6410kits.googlecode.com/files/overview_Real6410.pdf
> >
> > Therefore, given this, the timing value of mini6410 and real6410 would be as follows.
> >
> > +static struct fb_videomode mini6410_lcd_timing = {
> > +	.left_margin	= 8,
> > +	.right_margin	= 13,
> > +	.upper_margin	= 7,
> > +	.lower_margin	= 5,
> > +	.hsync_len	= 3,
> > +	.vsync_len	= 1,
> > +	.xres		= 480,
> > +	.yres		= 272,
> > +};
> >
> > +static struct fb_videomode real6410_lcd_timing = {
> > +	.left_margin	= 8,
> > +	.right_margin	= 13,
> > +	.upper_margin	= 7,
> > +	.lower_margin	= 5,
> > +	.hsync_len	= 3,
> > +	.vsync_len	= 1,
> > +	.xres		= 480,
> > +	.yres		= 272,
> > +};
> >
> > Darius Augulis, can you confirm it?
> > (Darius Augulis is a maintainer for real6410 and mini6410 boards.)
> 
> Are you going to leave only single LCD resolution for every of two
> boards? If so, then my answer is no.

Yes, only single LCD resolution will be left.

> I have mini6410 with both 4.3" and 7" LCDs and real6410 with 7" LCD. Now
> we have possibility to choose LCD size dynamically - leave it there.
> What you mean "default" 4.3" size LCD? The 7" size LCD is also provided
> by board sellers - I've bought it.

OK, I see.
Both mini6410 and real6410 provide both 4.3" and 7" LCDs,
so you needs to select both LCDs.

Um, usually, single LCD is provided on the single board.
Also, the daughter board with another kind LCD can be connected to the board.

However, .win_mode is used not for LCD, but for windows of FIMD IP.
Actually, our current framework does not support to choose multi LCD,
so, I understand that you use .win_mode[1] as second LCD.
However, that's not accurate way to select multi LCD.

Thomas, can you consider Augulis's opinion?
I think that the method to select multi LCDs is necessary.

Ideal process is such as:
  1. add the patch to support to select multi LCDs
  2. apply above patch to make the mini6410 and real6410 to select multi LCDs.
  3. apply Thomas's patchset to remove timing value from .win_mode variable.

Best regards,
Jingoo Han

> 
> regards,
> Darius Augulis
> 
> >
> > Best regards,
> > Jingoo Han
> >
> >> Thanks for your comments.
> >>
> >> Regards,
> >> Thomas.
> >


^ permalink raw reply

* Re: [PATCH v2 3/3] ARM: Samsung: Rework platform data of s3c-fb driver
From: Darius Augulis @ 2012-03-15  7:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <001501cd0241$6bb53560$431fa020$%han@samsung.com>

Hi,

>
> Yes, only single LCD resolution will be left.
>
>> I have mini6410 with both 4.3" and 7" LCDs and real6410 with 7" LCD. Now
>> we have possibility to choose LCD size dynamically - leave it there.
>> What you mean "default" 4.3" size LCD? The 7" size LCD is also provided
>> by board sellers - I've bought it.
>
> OK, I see.
> Both mini6410 and real6410 provide both 4.3" and 7" LCDs,
> so you needs to select both LCDs.
>
> Um, usually, single LCD is provided on the single board.
> Also, the daughter board with another kind LCD can be connected to the board.

There is single board - mini6410 (or real6410) and it's name doesn't
depend on connected LCD size.
We know, that this board is available with different sizes of LCD and
currently we have in kernel support for both sizes.
It might be so, that it's implemented not in perfect way, but it was
accepted and at least it's working.
If you want to rework s3c-fb platform data and driver framework, you
should not drop any functionality created by other people.

>
> However, .win_mode is used not for LCD, but for windows of FIMD IP.
> Actually, our current framework does not support to choose multi LCD,
> so, I understand that you use .win_mode[1] as second LCD.
> However, that's not accurate way to select multi LCD.
>
> Thomas, can you consider Augulis's opinion?
> I think that the method to select multi LCDs is necessary.
>
> Ideal process is such as:
>  1. add the patch to support to select multi LCDs
>  2. apply above patch to make the mini6410 and real6410 to select multi LCDs.
>  3. apply Thomas's patchset to remove timing value from .win_mode variable.

Yes, this would be the right way to go.

regards,
Darius A.

^ permalink raw reply

* Re: [PATCH] Added backlight driver for Acer Aspire 4736
From: joeyli @ 2012-03-15  8:05 UTC (permalink / raw)
  To: Pradeep Subrahmanion
  Cc: Matthew Garrett, rpurdie, FlorianSchandinat, akpm, linux-fbdev,
	linux-kernel
In-Reply-To: <CABNxG=D3y2GQqS1XN=+B0QRScXpufBkPQtP5-SSNEjSavhtW7g@mail.gmail.com>

Hi Pradeep, 

於 三,2012-03-14 於 11:47 +0530,Pradeep Subrahmanion 提到:
> On Wed, Mar 14, 2012 at 11:21 AM, joeyli <jlee@suse.com> wrote:
> > 於 三,2012-03-14 於 08:13 +0530,Pradeep Subrahmanion 提到:
> >> Hi Joey ,
> >>
> >> > Per my understood, EC firmware should change brightness but didn't do
> >> > that, another
> >> > way is touch i915 register in _BCM.
> >>
> >>   how do we do this ? you mean change the _BCM implementation ?
> >
> > "BIOS guy" should do something like this:
> >
> >  Method (AINT, 2, NotSerialized)
> > {
> > ...
> >        If (LEqual (Arg0, One))
> >        {
> >            Store (Divide (Multiply (Arg1, 0xFF), 0x64, ), BCLP)
> >            Or (BCLP, 0x80000000, BCLP)         <== touch BCLP register
> >            Store (0x02, ASLC)
> >        }
> >
> >    Method (_BCM, 1, NotSerialized)
> >    {
> >        If (LAnd (LGreaterEqual (Arg0, Zero), LLessEqual (Arg0, 0x64)))
> >        {
> >            AINT (One, Arg0)     <== call AINT method
> >            Store (Arg0, BRTL)
> >        }
> >    }
> >
> >
> > Just for reference, they should do that when EC didn't wire to
> > backlight.
> >
> >> >
> >> > Acer machine provide a broken _BCM implementation and they didn't test
> >> > it.
> >> >
> >> > > > > By ' ACPI interface' , I mean 'acpi_video0' inside the
> >> > > > > /sys/class/backlight. I havn't tried the /sys/class/backlight interface
> >> > > > > directly . I will try that also.
> >> > > >
> >> > > > So writing values into /sys/class/backlight/acpi_video0/brightness does
> >> > > > nothing?
> >> > >
> >> > >
> >> > > No change in value when writing
> >> > > to /sys/class/backlight/acpi_video0/brightness.
> >> > >
> >> > > Another thing is that when i did boot with acpi_backlight = 'acer_wmi' ,
> >> > > in new kernel (3.3.0-rc7) , it shows following messages ,
> >> > >
> >> > > [    8.350825] wmi: Mapper loaded
> >> > > [   10.363975] acer_wmi: Acer Laptop ACPI-WMI Extras
> >> > > [   10.396186] acer_wmi: Function bitmap for Communication Device: 0x91
> >> > > [   10.396385] acer_wmi: Brightness must be controlled by generic video
> >> > > driver
> >> > >
> >> > > Also there was no interface inside /sys/class/backlight for acer_wmi.
> >> > >
> >> >
> >> > Yes, acer_wmi support backlight control with AMW0 interface, your
> >> > machine didn't have AMW0 interface.
> >> >
> >> > Normally, backlight should control by standard acpi interface.
> >> >
> >> > > I also tried writing directly to Embedded controller register .But no
> >> > > change.
> >> >
> >> > The machine has broken _BCM method, because EC should do something after
> >> > _BCM changed EC register.
> >>
> >> Thanks ,
> >>
> >> Pradeep Subrahmanion
> >
> > Why they didn't find _BCM not work?
> >
> > My guess is:
> >
> > Because the backlight control is through WDDM driver on Windows platform
> > but not through standard ACPI method _BCM. They only test Windows
> > platform, so, they didn't find _BCM broken.
> >
> > And, they also didn't really follow Microsoft WDDM spec:
> >
> >  http://msdn.microsoft.com/en-us/windows/hardware/gg487382.aspx
> >
> > Per spec,
> > ODM should keep _BCM works fine for any other OS didn't support WDDM
> > driver, but they didn't.
> >
> > At last year, I told Acer PM one time for this issue, they said will
> > check but finally didn't response me.
> >
> 
> >
> > Thanks
> > Joey Lee
> >
> 
> So touching the PCI LBB register is the only feasible solution now
> (even though it may not be a clean  method) ?
> 
> Thanks,
> Pradeep Subrahmanion

That will be better leave LBB register only touched by i915 driver.

If 'acpi_backlight=vendor' works to you, maybe we can add a quirk to
video_detect.c. 
You can try the following patch.


Thanks a lot!
Joey Lee


From 038bd3c4e53b7195f34e9d46c999b8dcb279da5e Mon Sep 17 00:00:00 2001
From: "Lee, Chun-Yi" <jlee@suse.com>
Date: Thu, 15 Mar 2012 16:03:45 +0800
Subject: [PATCH] acer-wmi: Add quirk table for video backlight vendor mode

Add quirk table for video backlight vendor mode

Signed-off-by: "Lee, Chun-Yi" <jlee@suse.com>
---
 drivers/acpi/video_detect.c |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index f3f0fe7..acb15d6 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -132,6 +132,32 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
 	return AE_OK;
 }
 
+static int video_set_backlight_vendor(const struct dmi_system_id *d)
+{
+	acpi_video_support |= ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
+	return 0;
+}
+
+static const struct dmi_system_id video_vendor_dmi_table[] = {
+	{
+	 .callback = video_set_backlight_vendor,
+	 .ident = "Acer Aspire 4736",
+	 .matches = {
+		DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 4736"),
+		},
+	},
+	{
+	 .callback = video_set_backlight_vendor,
+	 .ident = "Acer TravelMate 4750",
+	 .matches = {
+		DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"),
+		},
+	},
+	{}
+};
+
 /*
  * Returns the video capabilities of a specific ACPI graphics device
  *
@@ -164,6 +190,7 @@ long acpi_video_get_capabilities(acpi_handle graphics_handle)
 		 *		ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
 		 *}
 		 */
+		dmi_check_system(video_vendor_dmi_table);
 	} else {
 		status = acpi_bus_get_device(graphics_handle, &tmp_dev);
 		if (ACPI_FAILURE(status)) {
-- 
1.7.7




^ permalink raw reply related

* RE: [PATCH v2 3/3] ARM: Samsung: Rework platform data of s3c-fb driver
From: Jingoo Han @ 2012-03-15  8:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAEYLNCp5e=86rpRi2C-5OJptTyEeXAn8JHhbWw_BqGzSaDD9wQ@mail.gmail.com>



> -----Original Message-----
> From: Darius Augulis [mailto:augulis.darius@gmail.com]
> Sent: Thursday, March 15, 2012 4:42 PM
> To: Jingoo Han
> Cc: Thomas Abraham; linux-fbdev@vger.kernel.org; FlorianSchandinat@gmx.de; linux-arm-
> kernel@lists.infradead.org; linux-samsung-soc@vger.kernel.org; kgene.kim@samsung.com; ben-
> linux@fluff.org; patches@linaro.org; Kyungmin Park; JeongHyeon Kim; Heiko Stuebner; Kwangwoo Lee; Mark
> Brown; Peter Korsgaard; Maurus Cuelenaere
> Subject: Re: [PATCH v2 3/3] ARM: Samsung: Rework platform data of s3c-fb driver
> 
> Hi,
> 
> >
> > Yes, only single LCD resolution will be left.
> >
> >> I have mini6410 with both 4.3" and 7" LCDs and real6410 with 7" LCD. Now
> >> we have possibility to choose LCD size dynamically - leave it there.
> >> What you mean "default" 4.3" size LCD? The 7" size LCD is also provided
> >> by board sellers - I've bought it.
> >
> > OK, I see.
> > Both mini6410 and real6410 provide both 4.3" and 7" LCDs,
> > so you needs to select both LCDs.
> >
> > Um, usually, single LCD is provided on the single board.
> > Also, the daughter board with another kind LCD can be connected to the board.
> 
> There is single board - mini6410 (or real6410) and it's name doesn't
> depend on connected LCD size.
> We know, that this board is available with different sizes of LCD and
> currently we have in kernel support for both sizes.
> It might be so, that it's implemented not in perfect way, but it was
> accepted and at least it's working.


I don't think so.
You argues that the wrong code should not be removed because it was accepted and at least it's working.
It is just wrong usage, which can just work.
Moreover, your code will make the problem, when 2~5 windows of FIMD IP are used.
So, your code can be removed.


> If you want to rework s3c-fb platform data and driver framework, you
> should not drop any functionality created by other people.

Augulis, Thomas Abraham wants to rework s3c-fb platform data and driver framework, not me. :)
I am just reviewing the Thomas's patchset.

> 
> >
> > However, .win_mode is used not for LCD, but for windows of FIMD IP.
> > Actually, our current framework does not support to choose multi LCD,
> > so, I understand that you use .win_mode[1] as second LCD.
> > However, that's not accurate way to select multi LCD.
> >
> > Thomas, can you consider Augulis's opinion?
> > I think that the method to select multi LCDs is necessary.
> >
> > Ideal process is such as:
> >  1. add the patch to support to select multi LCDs
> >  2. apply above patch to make the mini6410 and real6410 to select multi LCDs.
> >  3. apply Thomas's patchset to remove timing value from .win_mode variable.
> 
> Yes, this would be the right way to go.

However, skipping step 1 & 2 is also available, because your code is wrong.
As I'm mentioned above, your code will make the problem when 2~5 windows of FIMD IP are used.


> 
> regards,
> Darius A.


^ permalink raw reply

* Re: [PATCH v2] OMAPDSS: provide default timings functions for panels
From: Tomi Valkeinen @ 2012-03-15  8:12 UTC (permalink / raw)
  To: Grazvydas Ignotas; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <CANOLnOMAg-gdGPCuR1eR39GzNcK0rqFpfx6hiC2ULgPQ5v4qbA@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1945 bytes --]

On Wed, 2012-03-14 at 18:33 +0200, Grazvydas Ignotas wrote:
> On Wed, Mar 14, 2012 at 1:22 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> > Hi,
> >
> > On Mon, 2012-03-12 at 13:27 +0200, Grazvydas Ignotas wrote:
> >> With this we can eliminate some duplicate code in panel drivers.
> >> Also lgphilips-lb035q02, nec-nl8048hl11-01b, picodlp and
> >> tpo-td043mtea1 gain support of timings control over sysfs.
> >
> > I don't like this patch.
> >
> > Panels usually have a single, fixed timing configuration that should be
> > used, like the ones you mention above. There's no need to alter the
> > timings.
> 
> But they often have a range of timings they can tolerate, and that can
> be used to alter refresh rate, for example. We do that on pandora to
> match graphics drawing rate (or multiples of it) to create a feeling
> smoothness.

True. And it's a valid operation anyway, so I guess there's no reason
why not to allow changing of the timings there.

> > But it's true that there's some duplicate code currently in the panel
> > drivers. However, adding just simple funcs like you did in this patch
> > doesn't work quite properly. There should be locking (for example to
> > prevent disabling the panel while timings are being set), and currently
> > the locking is panel driver specific.

Oh, and one more problem with the patch is that currently the panel
informs its inability to change timings by leaving set_timings and
check_timings as NULL, and this tells omapfb etc that the timings cannot
be changed, and the patch changes that behavior.

> ok, what about a version of this with .get_timings only then?
> This should not need a lock unless panel has a set function, but in
> that case panel will be expected to provide safe version of .get and
> .set itself.

I guess there's no harm in having default for get_timings(). It should
be present on all panel drivers anyway.

 Tomi


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH v2 3/3] ARM: Samsung: Rework platform data of s3c-fb driver
From: Darius Augulis @ 2012-03-15  8:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <002a01cd0283$1f61b200$5e251600$%han@samsung.com>

On Thu, Mar 15, 2012 at 10:10 AM, Jingoo Han <jg1.han@samsung.com> wrote:

>> There is single board - mini6410 (or real6410) and it's name doesn't
>> depend on connected LCD size.
>> We know, that this board is available with different sizes of LCD and
>> currently we have in kernel support for both sizes.
>> It might be so, that it's implemented not in perfect way, but it was
>> accepted and at least it's working.
>
>
> I don't think so.
> You argues that the wrong code should not be removed because it was accepted and at least it's working.
> It is just wrong usage, which can just work.
> Moreover, your code will make the problem, when 2~5 windows of FIMD IP are used.

Could please explain that? How does LCD feature selection for mini6410
and real6410 break that?
Timing for different sizes of LCD is located in two statically
allocated structures which are used at board init time depending on
kernel param line.
Data from one of these structures is copied to s3c-fb platform data
dynamically by board init code. Why it's a problem? What changes if
platform data isn't rewritten dynamically?

> So, your code can be removed.

I don't think so. It does not break anything yet. One who make
changes, should ensure backwards compatibility, at least talking about
functionality and hardware (LCD) support, which was added few months
ago. Remember, we talk about kernel parameters line - now it lets
bootloader to select correct LCD size. After your changes, board with
7" LCD wont show anything.

Darius A.

^ permalink raw reply

* RE: [PATCH v2 3/3] ARM: Samsung: Rework platform data of s3c-fb driver
From: Jingoo Han @ 2012-03-15  8:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAEYLNCrprPE60ZS=_OWuck0JCJMhCxzVErZwuwGpEDYkQq-hXg@mail.gmail.com>



> -----Original Message-----
> From: Darius Augulis [mailto:augulis.darius@gmail.com]
> Sent: Thursday, March 15, 2012 5:27 PM
> To: Jingoo Han
> Cc: Thomas Abraham; linux-fbdev@vger.kernel.org; FlorianSchandinat@gmx.de; linux-arm-
> kernel@lists.infradead.org; linux-samsung-soc@vger.kernel.org; kgene.kim@samsung.com; ben-
> linux@fluff.org; patches@linaro.org; Kyungmin Park; JeongHyeon Kim; Heiko Stuebner; Kwangwoo Lee; Mark
> Brown; Peter Korsgaard; Maurus Cuelenaere
> Subject: Re: [PATCH v2 3/3] ARM: Samsung: Rework platform data of s3c-fb driver
> 
> On Thu, Mar 15, 2012 at 10:10 AM, Jingoo Han <jg1.han@samsung.com> wrote:
> 
> >> There is single board - mini6410 (or real6410) and it's name doesn't
> >> depend on connected LCD size.
> >> We know, that this board is available with different sizes of LCD and
> >> currently we have in kernel support for both sizes.
> >> It might be so, that it's implemented not in perfect way, but it was
> >> accepted and at least it's working.
> >
> >
> > I don't think so.
> > You argues that the wrong code should not be removed because it was accepted and at least it's working.
> > It is just wrong usage, which can just work.
> > Moreover, your code will make the problem, when 2~5 windows of FIMD IP are used.
> 
> Could please explain that? How does LCD feature selection for mini6410
> and real6410 break that?
> Timing for different sizes of LCD is located in two statically
> allocated structures which are used at board init time depending on
> kernel param line.
> Data from one of these structures is copied to s3c-fb platform data
> dynamically by board init code. Why it's a problem? What changes if
> platform data isn't rewritten dynamically?
> 
> > So, your code can be removed.
> 
> I don't think so. It does not break anything yet. One who make
> changes, should ensure backwards compatibility, at least talking about
> functionality and hardware (LCD) support, which was added few months
> ago. Remember, we talk about kernel parameters line - now it lets
> bootloader to select correct LCD size. After your changes, board with
> 7" LCD wont show anything.

OK, your code work, although the usage is wrong.

Thomas, can you keep backwards compatibility?


> 
> Darius A.


^ permalink raw reply

* [PATCH] fbdev: bfin_adv7393fb: Drop needless include
From: Jean Delvare @ 2012-03-15  9:14 UTC (permalink / raw)
  To: linux-fbdev

Kernel drivers don't need <linux/i2c-dev.h>.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Michael Hennerich <michael.hennerich@analog.com>
Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
 drivers/video/bfin_adv7393fb.c |    2 --
 1 file changed, 2 deletions(-)

--- linux-3.3-rc7.orig/drivers/video/bfin_adv7393fb.c	2012-01-06 11:21:14.000000000 +0100
+++ linux-3.3-rc7/drivers/video/bfin_adv7393fb.c	2012-03-15 10:09:32.345820005 +0100
@@ -36,9 +36,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/proc_fs.h>
 #include <linux/platform_device.h>
-
 #include <linux/i2c.h>
-#include <linux/i2c-dev.h>
 
 #include "bfin_adv7393fb.h"
 


-- 
Jean Delvare

^ permalink raw reply

* Re: [PATCH] [#7001] framebuffer: old image of last app would retain for a while after starting new app
From: Wu, Aaron @ 2012-03-15  9:23 UTC (permalink / raw)
  To: Wu, Aaron,
	linux-fbdev-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org,
	uclinux-dist-devel-ZG0+EudsQA8dtHy/vicBwGD2FQJk+8+b@public.gmane.org
  Cc: Zhang, Sonic
In-Reply-To: <1331628439-12719-1-git-send-email-Aaron.Wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>



-----Original Message-----
From: Aaron Wu [mailto:Aaron.Wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org]
Sent: Tuesday, March 13, 2012 4:47 PM
To: linux-fbdev-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org; uclinux-dist-devel-ZG0+EudsQA8dtHy/vicBwGD2FQJk+8+b@public.gmane.org; Wu, Aaron
Cc: Wu, Aaron
Subject: [PATCH] [#7001] framebuffer: old image of last app would retain for a while after starting new app

Old image of last application would retain for a while when starting a new application, this patch
clear the frambuffer before displaying every time the fb is opened.

Signed-off-by: Aaron Wu <Aaron.Wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
 drivers/video/bfin-lq035q1-fb.c  |    1 +
 drivers/video/bfin-t350mcqb-fb.c |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
index c633068..676aa4e 100644
--- a/drivers/video/bfin-lq035q1-fb.c
+++ b/drivers/video/bfin-lq035q1-fb.c
@@ -399,6 +399,7 @@ static int bfin_lq035q1_fb_open(struct fb_info *info, int user)
                bfin_lq035q1_config_dma(fbi);
                bfin_lq035q1_config_ppi(fbi);
                bfin_lq035q1_init_timers(fbi);
+               memset(fbi->fb_buffer, 0, info->fix.smem_len);

                /* start dma */
                enable_dma(CH_PPI);
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index d5e1267..37f2df1 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -216,6 +216,7 @@ static int bfin_t350mcqb_fb_open(struct fb_info *info, int user)
                bfin_t350mcqb_config_dma(fbi);
                bfin_t350mcqb_config_ppi(fbi);
                bfin_t350mcqb_init_timers();
+               memset(fbi->fb_buffer, 0, info->fix.smem_len);

                /* start dma */
                enable_dma(CH_PPI);
--
1.7.0.4

^ permalink raw reply related

* [PATCH 0/2] OMAPDSS: DISPC: Enable predecimation for DMA and VRFB
From: Chandrabhanu Mahapatra @ 2012-03-15 11:49 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-omap, linux-fbdev, Chandrabhanu Mahapatra

Hi everyone,
the following patch set directs to enable predecimation for DMA and VRFB
which consists of two pacthes.

The first patch is based on code written by Lajos Molnar <lajos@ti.com> in
Android Kernel, which updates the code with predecimation logic thereby
increasing the downscaling ability of the DISPC module.

The second patch is based on code written by Ville Syrjälä
<ville.syrjala@nokia.com> which aims to avoid synclost errors occurring
in OMAP3 due to some undocumented horizontal position and timing related
limitations which I faced during testing of the previous patch.

I have tested these patches successfully on OMAP2, OMAP3 AND OMAP4 on the
mainline kernel v3.3-rc5. Horizontal and vertical predecimation worked fine
but skewed images along with underflow errors were seen on OMAP2 and OMAP3
during horizontal predecimation which will be addressed in the future patches.

All your comments and suggestions are welcome.

Regards,
Chandrabhanu

Chandrabhanu Mahapatra (2):
  OMAPDSS: DISPC: Enable predecimation
  OMAPDSS: DISPC: Handle synclost errors in OMAP3

 drivers/video/omap2/dss/dispc.c |  323 +++++++++++++++++++++++++++++----------
 1 files changed, 242 insertions(+), 81 deletions(-)


^ permalink raw reply

* [PATCH 1/2] OMAPDSS: DISPC: Enable predecimation
From: Chandrabhanu Mahapatra @ 2012-03-15 11:49 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-omap, linux-fbdev, Chandrabhanu Mahapatra

In OMAP3 and OMAP4, the DISPC Scaler can downscale an image up to 4 times, and
up to 2 times in OMAP2. However, with predecimation, the image can be reduced
to 16 times by fetching only the necessary pixels in memory. Then this
predecimated image can be downscaled further by the DISPC scaler.

Based on the downscaling required, a prior calculation of predecimation values
for width and height of an image is done. Since, Predecimation reduces quality
of an image higher priorty is given to DISPC Scaler for downscaling.

This code was successfully tested on OMAP2, OMAP3 and OMAP4. Horizontal and
vertical predecimation worked fine except for some synclost errors due to
undocumented errata in OMAP3 which are fixed later and skewed images were seen
on OMAP2 and OMAP3 during horizontal predecimation which will be addressed in
the future patches.

This code is based on code written by Lajos Molnar <lajos@ti.com> who had added
predecimation support for NV12/YUV/rotated/SDMA buffers.

Signed-off-by: Chandrabhanu Mahapatra <cmahapatra@ti.com>
---
 drivers/video/omap2/dss/dispc.c |  262 +++++++++++++++++++++++++++------------
 1 files changed, 181 insertions(+), 81 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index e1626a1..5a1963e 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1389,7 +1389,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
 		enum omap_color_mode color_mode, bool fieldmode,
 		unsigned int field_offset,
 		unsigned *offset0, unsigned *offset1,
-		s32 *row_inc, s32 *pix_inc)
+		s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
 {
 	u8 ps;
 
@@ -1435,10 +1435,10 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
 		else
 			*offset0 = 0;
 
-		*row_inc = pixinc(1 + (screen_width - width) +
-				(fieldmode ? screen_width : 0),
-				ps);
-		*pix_inc = pixinc(1, ps);
+		*row_inc = pixinc(1 +
+			(y_predecim * screen_width - x_predecim * width) +
+			(fieldmode ? screen_width : 0), ps);
+		*pix_inc = pixinc(x_predecim, ps);
 		break;
 
 	case OMAP_DSS_ROT_0 + 4:
@@ -1456,10 +1456,10 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
 			*offset0 = field_offset * screen_width * ps;
 		else
 			*offset0 = 0;
-		*row_inc = pixinc(1 - (screen_width + width) -
-				(fieldmode ? screen_width : 0),
-				ps);
-		*pix_inc = pixinc(1, ps);
+		*row_inc = pixinc(1 -
+			(y_predecim * screen_width + x_predecim * width) -
+			(fieldmode ? screen_width : 0), ps);
+		*pix_inc = pixinc(x_predecim, ps);
 		break;
 
 	default:
@@ -1473,7 +1473,7 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
 		enum omap_color_mode color_mode, bool fieldmode,
 		unsigned int field_offset,
 		unsigned *offset0, unsigned *offset1,
-		s32 *row_inc, s32 *pix_inc)
+		s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
 {
 	u8 ps;
 	u16 fbw, fbh;
@@ -1515,10 +1515,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
 			*offset0 = *offset1 + field_offset * screen_width * ps;
 		else
 			*offset0 = *offset1;
-		*row_inc = pixinc(1 + (screen_width - fbw) +
-				(fieldmode ? screen_width : 0),
-				ps);
-		*pix_inc = pixinc(1, ps);
+		*row_inc = pixinc(1 +
+			(y_predecim * screen_width - fbw * x_predecim) +
+			(fieldmode ? screen_width : 0),	ps);
+		if (color_mode = OMAP_DSS_COLOR_YUV2 ||
+			color_mode = OMAP_DSS_COLOR_UYVY)
+			*pix_inc = pixinc(x_predecim, 2 * ps);
+		else
+			*pix_inc = pixinc(x_predecim, ps);
 		break;
 	case OMAP_DSS_ROT_90:
 		*offset1 = screen_width * (fbh - 1) * ps;
@@ -1526,9 +1530,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
 			*offset0 = *offset1 + field_offset * ps;
 		else
 			*offset0 = *offset1;
-		*row_inc = pixinc(screen_width * (fbh - 1) + 1 +
-				(fieldmode ? 1 : 0), ps);
-		*pix_inc = pixinc(-screen_width, ps);
+		*row_inc = pixinc(screen_width * (fbh * x_predecim - 1) +
+				y_predecim + (fieldmode ? 1 : 0), ps);
+		*pix_inc = pixinc(-x_predecim * screen_width, ps);
 		break;
 	case OMAP_DSS_ROT_180:
 		*offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
@@ -1537,10 +1541,13 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
 		else
 			*offset0 = *offset1;
 		*row_inc = pixinc(-1 -
-				(screen_width - fbw) -
-				(fieldmode ? screen_width : 0),
-				ps);
-		*pix_inc = pixinc(-1, ps);
+			(y_predecim * screen_width - fbw * x_predecim) -
+			(fieldmode ? screen_width : 0),	ps);
+		if (color_mode = OMAP_DSS_COLOR_YUV2 ||
+			color_mode = OMAP_DSS_COLOR_UYVY)
+			*pix_inc = pixinc(-x_predecim, 2 * ps);
+		else
+			*pix_inc = pixinc(-x_predecim, ps);
 		break;
 	case OMAP_DSS_ROT_270:
 		*offset1 = (fbw - 1) * ps;
@@ -1548,9 +1555,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
 			*offset0 = *offset1 - field_offset * ps;
 		else
 			*offset0 = *offset1;
-		*row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
-				(fieldmode ? 1 : 0), ps);
-		*pix_inc = pixinc(screen_width, ps);
+		*row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) -
+				y_predecim - (fieldmode ? 1 : 0), ps);
+		*pix_inc = pixinc(x_predecim * screen_width, ps);
 		break;
 
 	/* mirroring */
@@ -1560,10 +1567,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
 			*offset0 = *offset1 + field_offset * screen_width * ps;
 		else
 			*offset0 = *offset1;
-		*row_inc = pixinc(screen_width * 2 - 1 +
+		*row_inc = pixinc(y_predecim * screen_width * 2 - 1 +
 				(fieldmode ? screen_width : 0),
 				ps);
-		*pix_inc = pixinc(-1, ps);
+		if (color_mode = OMAP_DSS_COLOR_YUV2 ||
+			color_mode = OMAP_DSS_COLOR_UYVY)
+			*pix_inc = pixinc(-x_predecim, 2 * ps);
+		else
+			*pix_inc = pixinc(-x_predecim, ps);
 		break;
 
 	case OMAP_DSS_ROT_90 + 4:
@@ -1572,10 +1583,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
 			*offset0 = *offset1 + field_offset * ps;
 		else
 			*offset0 = *offset1;
-		*row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
-				(fieldmode ? 1 : 0),
+		*row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) +
+				y_predecim + (fieldmode ? 1 : 0),
 				ps);
-		*pix_inc = pixinc(screen_width, ps);
+		*pix_inc = pixinc(x_predecim * screen_width, ps);
 		break;
 
 	case OMAP_DSS_ROT_180 + 4:
@@ -1584,10 +1595,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
 			*offset0 = *offset1 - field_offset * screen_width * ps;
 		else
 			*offset0 = *offset1;
-		*row_inc = pixinc(1 - screen_width * 2 -
+		*row_inc = pixinc(1 - y_predecim * screen_width * 2 -
 				(fieldmode ? screen_width : 0),
 				ps);
-		*pix_inc = pixinc(1, ps);
+		if (color_mode = OMAP_DSS_COLOR_YUV2 ||
+			color_mode = OMAP_DSS_COLOR_UYVY)
+			*pix_inc = pixinc(x_predecim, 2 * ps);
+		else
+			*pix_inc = pixinc(x_predecim, ps);
 		break;
 
 	case OMAP_DSS_ROT_270 + 4:
@@ -1596,10 +1611,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
 			*offset0 = *offset1 - field_offset * ps;
 		else
 			*offset0 = *offset1;
-		*row_inc = pixinc(screen_width * (fbh - 1) - 1 -
-				(fieldmode ? 1 : 0),
+		*row_inc = pixinc(screen_width * (fbh * x_predecim - 1) -
+				y_predecim - (fieldmode ? 1 : 0),
 				ps);
-		*pix_inc = pixinc(-screen_width, ps);
+		*pix_inc = pixinc(-x_predecim * screen_width, ps);
 		break;
 
 	default:
@@ -1686,13 +1701,17 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
 static int dispc_ovl_calc_scaling(enum omap_plane plane,
 		enum omap_channel channel, u16 width, u16 height,
 		u16 out_width, u16 out_height,
-		enum omap_color_mode color_mode, bool *five_taps)
+		enum omap_color_mode color_mode, bool *five_taps,
+		int *x_predecim, int *y_predecim)
 {
 	struct omap_overlay *ovl = omap_dss_get_overlay(plane);
 	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
 	const int maxsinglelinewidth  				dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+	const int max_decim_limit = 16;
 	unsigned long fclk = 0;
+	int decim_x, decim_y, error, min_factor;
+	u16 in_width, in_height, in_width_max = 0;
 
 	if (width = out_width && height = out_height)
 		return 0;
@@ -1700,45 +1719,117 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
 	if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) = 0)
 		return -EINVAL;
 
-	if (out_width < width / maxdownscale ||
-			out_width > width * 8)
+	*x_predecim = max_decim_limit;
+	*y_predecim = max_decim_limit;
+
+	if (color_mode = OMAP_DSS_COLOR_CLUT1 ||
+	    color_mode = OMAP_DSS_COLOR_CLUT2 ||
+	    color_mode = OMAP_DSS_COLOR_CLUT4 ||
+	    color_mode = OMAP_DSS_COLOR_CLUT8) {
+		*x_predecim = 1;
+		*y_predecim = 1;
+		*five_taps = false;
+		return 0;
+	}
+
+	decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
+	decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
+
+	min_factor = min(decim_x, decim_y);
+
+	if (decim_x > *x_predecim || out_width > width * 8)
 		return -EINVAL;
 
-	if (out_height < height / maxdownscale ||
-			out_height > height * 8)
+	if (decim_y > *y_predecim || out_height > height * 8)
 		return -EINVAL;
 
 	if (cpu_is_omap24xx()) {
-		if (width > maxsinglelinewidth)
-			DSSERR("Cannot scale max input width exceeded");
 		*five_taps = false;
-		fclk = calc_fclk(channel, width, height, out_width,
-								out_height);
+
+		do {
+			in_height = DIV_ROUND_UP(height, decim_y);
+			in_width = DIV_ROUND_UP(width, decim_x);
+			fclk = calc_fclk(channel, in_width, in_height,
+					out_width, out_height);
+			error = (in_width > maxsinglelinewidth || !fclk ||
+				fclk > dispc_fclk_rate());
+			if (error) {
+				if (decim_x = decim_y) {
+					decim_x = min_factor;
+					decim_y++;
+				} else {
+					swap(decim_x, decim_y);
+					if (decim_x < decim_y)
+						decim_x++;
+				}
+			}
+		} while (decim_x <= *x_predecim && decim_y <= *y_predecim &&
+				error);
+
+		if (in_width > maxsinglelinewidth) {
+			DSSERR("Cannot scale max input width exceeded");
+			return -EINVAL;
+		}
 	} else if (cpu_is_omap34xx()) {
-		if (width > (maxsinglelinewidth * 2)) {
+
+		do {
+			in_height = DIV_ROUND_UP(height, decim_y);
+			in_width = DIV_ROUND_UP(width, decim_x);
+			fclk = calc_fclk_five_taps(channel, in_width, in_height,
+				out_width, out_height, color_mode);
+
+			if (in_width > maxsinglelinewidth)
+				if (in_height > out_height &&
+					in_height < out_height * 2)
+					*five_taps = false;
+			if (!*five_taps)
+				fclk = calc_fclk(channel, in_width, in_height,
+					out_width, out_height);
+			error = (in_width > maxsinglelinewidth * 2 ||
+				(in_width > maxsinglelinewidth && *five_taps) ||
+				!fclk || fclk > dispc_fclk_rate());
+			if (error) {
+				if (decim_x = decim_y) {
+					decim_x = min_factor;
+					decim_y++;
+				} else {
+					swap(decim_x, decim_y);
+					if (decim_x < decim_y)
+						decim_x++;
+				}
+			}
+		} while (decim_x <= *x_predecim && decim_y <= *y_predecim
+			&& error);
+
+		if (in_width > (maxsinglelinewidth * 2)) {
 			DSSERR("Cannot setup scaling");
 			DSSERR("width exceeds maximum width possible");
 			return -EINVAL;
 		}
-		fclk = calc_fclk_five_taps(channel, width, height, out_width,
-						out_height, color_mode);
-		if (width > maxsinglelinewidth) {
-			if (height > out_height && height < out_height * 2)
-				*five_taps = false;
-			else {
-				DSSERR("cannot setup scaling with five taps");
-				return -EINVAL;
-			}
+
+		if (in_width > maxsinglelinewidth && *five_taps) {
+			DSSERR("cannot setup scaling with five taps");
+			return -EINVAL;
 		}
-		if (!*five_taps)
-			fclk = calc_fclk(channel, width, height, out_width,
-					out_height);
 	} else {
-		if (width > maxsinglelinewidth) {
+		in_height = DIV_ROUND_UP(height, decim_y);
+		in_width_max = dispc_fclk_rate() /
+				DIV_ROUND_UP(dispc_mgr_pclk_rate(channel),
+						out_width);
+		decim_x = DIV_ROUND_UP(width, in_width_max);
+		if (decim_x > *x_predecim)
+			return -EINVAL;
+		do {
+			in_width = DIV_ROUND_UP(width, decim_x);
+		} while (decim_x <= *x_predecim &&
+				in_width > maxsinglelinewidth && decim_x++);
+
+		if (in_width > maxsinglelinewidth) {
 			DSSERR("Cannot scale width exceeds max line width");
 			return -EINVAL;
 		}
-		fclk = calc_fclk(channel, width, height, out_width,
+
+		fclk = calc_fclk(channel, in_width, in_height, out_width,
 				out_height);
 	}
 
@@ -1753,6 +1844,8 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
 		return -EINVAL;
 	}
 
+	*x_predecim = decim_x;
+	*y_predecim = decim_y;
 	return 0;
 }
 
@@ -1768,8 +1861,11 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
 	s32 pix_inc;
 	u16 frame_height = oi->height;
 	unsigned int field_offset = 0;
-	u16 outw, outh;
+	u16 in_height = oi->height;
+	u16 in_width = oi->width;
+	u16 out_width, out_height;
 	enum omap_channel channel;
+	int x_predecim = 1, y_predecim = 1;
 
 	channel = dispc_ovl_get_channel_out(plane);
 
@@ -1783,32 +1879,35 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
 	if (oi->paddr = 0)
 		return -EINVAL;
 
-	outw = oi->out_width = 0 ? oi->width : oi->out_width;
-	outh = oi->out_height = 0 ? oi->height : oi->out_height;
+	out_width = oi->out_width = 0 ? oi->width : oi->out_width;
+	out_height = oi->out_height = 0 ? oi->height : oi->out_height;
 
-	if (ilace && oi->height = outh)
+	if (ilace && oi->height = out_height)
 		fieldmode = 1;
 
 	if (ilace) {
 		if (fieldmode)
-			oi->height /= 2;
+			in_height /= 2;
 		oi->pos_y /= 2;
-		outh /= 2;
+		out_height /= 2;
 
 		DSSDBG("adjusting for ilace: height %d, pos_y %d, "
 				"out_height %d\n",
-				oi->height, oi->pos_y, outh);
+				in_height, oi->pos_y, out_height);
 	}
 
 	if (!dss_feat_color_mode_supported(plane, oi->color_mode))
 		return -EINVAL;
 
-	r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height,
-			outw, outh, oi->color_mode,
-			&five_taps);
+	r = dispc_ovl_calc_scaling(plane, channel, in_width, in_height,
+			out_width, out_height, oi->color_mode, &five_taps,
+			&x_predecim, &y_predecim);
 	if (r)
 		return r;
 
+	in_width = DIV_ROUND_UP(in_width, x_predecim);
+	in_height = DIV_ROUND_UP(in_height, y_predecim);
+
 	if (oi->color_mode = OMAP_DSS_COLOR_YUV2 ||
 			oi->color_mode = OMAP_DSS_COLOR_UYVY ||
 			oi->color_mode = OMAP_DSS_COLOR_NV12)
@@ -1822,10 +1921,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
 		 * so the integer part must be added to the base address of the
 		 * bottom field.
 		 */
-		if (!oi->height || oi->height = outh)
+		if (!in_height || in_height = out_height)
 			field_offset = 0;
 		else
-			field_offset = oi->height / outh / 2;
+			field_offset = in_height / out_height / 2;
 	}
 
 	/* Fields are independent but interleaved in memory. */
@@ -1834,14 +1933,16 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
 
 	if (oi->rotation_type = OMAP_DSS_ROT_DMA)
 		calc_dma_rotation_offset(oi->rotation, oi->mirror,
-				oi->screen_width, oi->width, frame_height,
+				oi->screen_width, in_width, frame_height,
 				oi->color_mode, fieldmode, field_offset,
-				&offset0, &offset1, &row_inc, &pix_inc);
+				&offset0, &offset1, &row_inc, &pix_inc,
+				x_predecim, y_predecim);
 	else
 		calc_vrfb_rotation_offset(oi->rotation, oi->mirror,
-				oi->screen_width, oi->width, frame_height,
+				oi->screen_width, in_width, frame_height,
 				oi->color_mode, fieldmode, field_offset,
-				&offset0, &offset1, &row_inc, &pix_inc);
+				&offset0, &offset1, &row_inc, &pix_inc,
+				x_predecim, y_predecim);
 
 	DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
 			offset0, offset1, row_inc, pix_inc);
@@ -1860,19 +1961,18 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
 	dispc_ovl_set_row_inc(plane, row_inc);
 	dispc_ovl_set_pix_inc(plane, pix_inc);
 
-	DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width,
-			oi->height, outw, outh);
+	DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width,
+			in_height, out_width, out_height);
 
 	dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
 
-	dispc_ovl_set_pic_size(plane, oi->width, oi->height);
+	dispc_ovl_set_pic_size(plane, in_width, in_height);
 
 	if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
-		dispc_ovl_set_scaling(plane, oi->width, oi->height,
-				   outw, outh,
-				   ilace, five_taps, fieldmode,
+		dispc_ovl_set_scaling(plane, in_width, in_height, out_width,
+				   out_height, ilace, five_taps, fieldmode,
 				   oi->color_mode, oi->rotation);
-		dispc_ovl_set_vid_size(plane, outw, outh);
+		dispc_ovl_set_vid_size(plane, out_width, out_height);
 		dispc_ovl_set_vid_color_conv(plane, cconv);
 	}
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 2/2] OMAPDSS: DISPC: Handle synclost errors in OMAP3
From: Chandrabhanu Mahapatra @ 2012-03-15 11:49 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-omap, linux-fbdev, Chandrabhanu Mahapatra

In OMAP3 DISPC video overlays suffer from some undocumented horizontal position
and timing related limitations leading to SYNCLOST errors. Whenever the image
window is moved towards the right of the screen SYNCLOST errors become
frequent. Checks have been implemented to see that DISPC driver rejects
configuration exceeding above limitations.

This code was successfully tested on OMAP3. This code is written based on code
written by Ville Syrj채l채 <ville.syrjala@nokia.com> in Linux OMAP kernel. Ville
Syrj채l채 <ville.syrjala@nokia.com> had added checks for video overlay horizontal
timing and DISPC horizontal blanking length limitations.

Signed-off-by: Chandrabhanu Mahapatra <cmahapatra@ti.com>
---
 drivers/video/omap2/dss/dispc.c |   67 +++++++++++++++++++++++++++++++++++++--
 1 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 5a1963e..ebfa613 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1622,6 +1622,58 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
 	}
 }
 
+static int check_horiz_timing(enum omap_channel channel, u16 pos_x,
+		u16 width, u16 height, u16 out_width, u16 out_height)
+{
+	int DS = DIV_ROUND_UP(height, out_height);
+	struct omap_dss_device *dssdev = dispc_mgr_get_device(channel);
+	struct omap_video_timings t = dssdev->panel.timings;
+	int pcd = REG_GET(DISPC_DIVISORo(channel), 7, 0);
+	unsigned long nonactive, val, blank;
+	static const u8 limits[3] = { 8, 10, 20 };
+	int i;
+
+	nonactive = t.x_res + t.hfp + t.hsw + t.hbp - out_width;
+
+	/*
+	 * Atleast DS-2 lines must have already been fetched
+	 * before the display active video period starts.
+	 */
+	val = (nonactive - pos_x) * pcd;
+	DSSDBG("(nonactive - pos_x) * pcd = %lu,"
+		" max(0, DS - 2) * width = %d\n",
+		val, max(0, DS - 2) * width);
+	if (val < max(0, DS - 2) * width)
+		return -EINVAL;
+
+	/*
+	 * Only one line can be fetched during the overlay active
+	 * period, the rest have to be fetched during the inactive
+	 * period.
+	 */
+	val = nonactive * pcd;
+	DSSDBG("nonactive * pcd  = %lu, max(0, DS - 1) * width = %d\n",
+		val, max(0, DS - 1) * width);
+	if (val < max(0, DS - 1) * width)
+		return -EINVAL;
+
+	/*
+	 * Atleast Ceil(DS) lines should have been loaded during
+	 * PPL (screen width) + blanking period.
+	 */
+	i = 0;
+	if (out_height < height)
+		i++;
+	if (out_width < width)
+		i++;
+	blank = (t.hbp + t.hsw + t.hfp) * pcd;
+	DSSDBG("blanking period + ppl = %lu (limit = %u)\n", blank, limits[i]);
+	if (blank <= limits[i])
+		return -EINVAL;
+
+	return 0;
+}
+
 static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
 		u16 height, u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode)
@@ -1702,7 +1754,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
 		enum omap_channel channel, u16 width, u16 height,
 		u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode, bool *five_taps,
-		int *x_predecim, int *y_predecim)
+		int *x_predecim, int *y_predecim, u16 pos_x)
 {
 	struct omap_overlay *ovl = omap_dss_get_overlay(plane);
 	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
@@ -1778,6 +1830,9 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
 			fclk = calc_fclk_five_taps(channel, in_width, in_height,
 				out_width, out_height, color_mode);
 
+			error = check_horiz_timing(channel, pos_x, in_width,
+				in_height, out_width, out_height);
+
 			if (in_width > maxsinglelinewidth)
 				if (in_height > out_height &&
 					in_height < out_height * 2)
@@ -1785,7 +1840,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
 			if (!*five_taps)
 				fclk = calc_fclk(channel, in_width, in_height,
 					out_width, out_height);
-			error = (in_width > maxsinglelinewidth * 2 ||
+			error = (error || in_width > maxsinglelinewidth * 2 ||
 				(in_width > maxsinglelinewidth && *five_taps) ||
 				!fclk || fclk > dispc_fclk_rate());
 			if (error) {
@@ -1801,6 +1856,12 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
 		} while (decim_x <= *x_predecim && decim_y <= *y_predecim
 			&& error);
 
+		if (check_horiz_timing(channel, pos_x, width, height,
+			out_width, out_height)){
+				DSSERR("horizontal timing too tight\n");
+				return -EINVAL;
+		}
+
 		if (in_width > (maxsinglelinewidth * 2)) {
 			DSSERR("Cannot setup scaling");
 			DSSERR("width exceeds maximum width possible");
@@ -1901,7 +1962,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
 
 	r = dispc_ovl_calc_scaling(plane, channel, in_width, in_height,
 			out_width, out_height, oi->color_mode, &five_taps,
-			&x_predecim, &y_predecim);
+			&x_predecim, &y_predecim, oi->pos_x);
 	if (r)
 		return r;
 
-- 
1.7.1

--
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 related

* [PATCH] gma500: Fix mmap frambuffer
From: Yoichi Yuasa @ 2012-03-15 12:28 UTC (permalink / raw)
  To: alan; +Cc: yuasa, linux-kernel, linux-fbdev


It cannot map correctly if page fault begins from a intermediate address.

Signed-off-by: Yoichi Yuasa <yuasa@linux-mips.org>
---
 drivers/gpu/drm/gma500/framebuffer.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index be61673..5154493 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -158,7 +158,7 @@ static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
 
 	page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-	address = (unsigned long)vmf->virtual_address;
+	address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT);
 
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
-- 
1.7.0.4

^ permalink raw reply related

* Re: [PATCH] gma500: Fix mmap frambuffer
From: Alan Cox @ 2012-03-15 14:47 UTC (permalink / raw)
  To: Yoichi Yuasa; +Cc: linux-kernel, linux-fbdev
In-Reply-To: <20120315212816.475b0b18.yuasa@linux-mips.org>

On Thu, 15 Mar 2012 21:28:16 +0900
Yoichi Yuasa <yuasa@linux-mips.org> wrote:

> 
> It cannot map correctly if page fault begins from a intermediate
> address.

Thanks, that explains one very strange bug I've been seeing !

^ permalink raw reply

* [RFC/PATCH 0/6] SH Mobile LCDC MERAM-based frame buffer backing store
From: Laurent Pinchart @ 2012-03-15 17:43 UTC (permalink / raw)
  To: linux-fbdev

Hi everybody,

This patch set implements support for storing the frame buffer contents in the
on-chip SRAM (MERAM). This will allow keeping the display on while putting
system memory in a low-power mode (assuming the CPU is idle). The main use case
is to reduce power consumption on mobile platforms when the user doesn't
interact with the device and lets it lock itself automatically after a short
timeout.

This is a first implementation and improvements are possible (such as copying
the frame buffer content using DMA, possibly through the VEU to handle format
conversion). I've tested it on a Mackerel board.

Laurent Pinchart (6):
  sh_mobile_meram: Rename operations to cache_[alloc|free|update]
  sh_mobile_meram: Use direct function calls for the public API
  sh_mobile_meram: Add direct MERAM allocation API
  fbdev: sh_mobile_lcdc: Fix pan offset computation in YUV mode
  fbdev: sh_mobile_lcdc: Destroy mutex at remove time
  fbdev: sh_mobile_lcdc: Added MERAM-backed frame buffer support

 drivers/video/sh_mobile_lcdcfb.c |  254 +++++++++++++++++++++++++++----------
 drivers/video/sh_mobile_lcdcfb.h |   10 ++-
 drivers/video/sh_mobile_meram.c  |  227 +++++++++++++++++++---------------
 include/video/sh_mobile_lcdc.h   |    1 +
 include/video/sh_mobile_meram.h  |   71 ++++++++---
 5 files changed, 370 insertions(+), 193 deletions(-)

-- 
Regards,

Laurent Pinchart


^ permalink raw reply

* [RFC/PATCH 1/6] sh_mobile_meram: Rename operations to cache_[alloc|free|update]
From: Laurent Pinchart @ 2012-03-15 17:43 UTC (permalink / raw)
  To: linux-fbdev

The MERAM operations meram_register, meram_unregister and meram_update
handle LCDC cache. In preparation for "raw" MERAM allocation, rename
them to more appropriate names.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/sh_mobile_lcdcfb.c |   32 +++----
 drivers/video/sh_mobile_lcdcfb.h |    2 +-
 drivers/video/sh_mobile_meram.c  |  176 ++++++++++++++++++-------------------
 include/video/sh_mobile_meram.h  |   21 ++---
 4 files changed, 110 insertions(+), 121 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 7a0b301..1efc65e 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -839,7 +839,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 	/* Compute frame buffer base address and pitch for each channel. */
 	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
 		int pixelformat;
-		void *meram;
+		void *cache;
 
 		ch = &priv->ch[k];
 		if (!ch->enabled)
@@ -853,12 +853,10 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 		    ch->cfg->meram_cfg = NULL)
 			continue;
 
-		/* we need to de-init configured ICBs before we can
-		 * re-initialize them.
-		 */
-		if (ch->meram) {
-			mdev->ops->meram_unregister(mdev, ch->meram);
-			ch->meram = NULL;
+		/* Free the allocated MERAM cache. */
+		if (ch->cache) {
+			mdev->ops->cache_free(mdev, ch->cache);
+			ch->cache = NULL;
 		}
 
 		switch (ch->format->fourcc) {
@@ -880,14 +878,14 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 			break;
 		}
 
-		meram = mdev->ops->meram_register(mdev, ch->cfg->meram_cfg,
+		cache = mdev->ops->cache_alloc(mdev, ch->cfg->meram_cfg,
 					ch->pitch, ch->yres, pixelformat,
 					&ch->pitch);
-		if (!IS_ERR(meram)) {
-			mdev->ops->meram_update(mdev, meram,
+		if (!IS_ERR(cache)) {
+			mdev->ops->cache_update(mdev, cache,
 					ch->base_addr_y, ch->base_addr_c,
 					&ch->base_addr_y, &ch->base_addr_c);
-			ch->meram = meram;
+			ch->cache = cache;
 		}
 	}
 
@@ -952,12 +950,12 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
 
 		sh_mobile_lcdc_display_off(ch);
 
-		/* disable the meram */
-		if (ch->meram) {
+		/* Free the MERAM cache. */
+		if (ch->cache) {
 			struct sh_mobile_meram_info *mdev;
 			mdev = priv->meram_dev;
-			mdev->ops->meram_unregister(mdev, ch->meram);
-			ch->meram = 0;
+			mdev->ops->cache_free(mdev, ch->cache);
+			ch->cache = 0;
 		}
 
 	}
@@ -1070,11 +1068,11 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 			base_addr_c += var->xoffset;
 	}
 
-	if (ch->meram) {
+	if (ch->cache) {
 		struct sh_mobile_meram_info *mdev;
 
 		mdev = priv->meram_dev;
-		mdev->ops->meram_update(mdev, ch->meram,
+		mdev->ops->cache_update(mdev, ch->cache,
 					base_addr_y, base_addr_c,
 					&base_addr_y, &base_addr_c);
 	}
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index da1c26e..698fb20 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -59,7 +59,7 @@ struct sh_mobile_lcdc_chan {
 	unsigned long *reg_offs;
 	unsigned long ldmt1r_value;
 	unsigned long enabled; /* ME and SE in LDCNT2R */
-	void *meram;
+	void *cache;
 
 	struct mutex open_lock;		/* protects the use counter */
 	int use_count;
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index 82ba830..4aa3fcb 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -194,13 +194,13 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
 }
 
 /* -----------------------------------------------------------------------------
- * Allocation
+ * LCDC cache planes allocation, init, cleanup and free
  */
 
 /* Allocate ICBs and MERAM for a plane. */
-static int __meram_alloc(struct sh_mobile_meram_priv *priv,
-			 struct sh_mobile_meram_fb_plane *plane,
-			 size_t size)
+static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
+			     struct sh_mobile_meram_fb_plane *plane,
+			     size_t size)
 {
 	unsigned long mem;
 	unsigned long idx;
@@ -229,8 +229,8 @@ static int __meram_alloc(struct sh_mobile_meram_priv *priv,
 }
 
 /* Free ICBs and MERAM for a plane. */
-static void __meram_free(struct sh_mobile_meram_priv *priv,
-			 struct sh_mobile_meram_fb_plane *plane)
+static void meram_plane_free(struct sh_mobile_meram_priv *priv,
+			     struct sh_mobile_meram_fb_plane *plane)
 {
 	gen_pool_free(priv->pool, priv->meram + plane->marker->offset,
 		      plane->marker->size * 1024);
@@ -248,62 +248,6 @@ static int is_nvcolor(int cspace)
 	return 0;
 }
 
-/* Allocate memory for the ICBs and mark them as used. */
-static struct sh_mobile_meram_fb_cache *
-meram_alloc(struct sh_mobile_meram_priv *priv,
-	    const struct sh_mobile_meram_cfg *cfg,
-	    int pixelformat)
-{
-	struct sh_mobile_meram_fb_cache *cache;
-	unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
-	int ret;
-
-	if (cfg->icb[0].meram_size = 0)
-		return ERR_PTR(-EINVAL);
-
-	if (nplanes = 2 && cfg->icb[1].meram_size = 0)
-		return ERR_PTR(-EINVAL);
-
-	cache = kzalloc(sizeof(*cache), GFP_KERNEL);
-	if (cache = NULL)
-		return ERR_PTR(-ENOMEM);
-
-	cache->nplanes = nplanes;
-
-	ret = __meram_alloc(priv, &cache->planes[0], cfg->icb[0].meram_size);
-	if (ret < 0)
-		goto error;
-
-	cache->planes[0].marker->current_reg = 1;
-	cache->planes[0].marker->pixelformat = pixelformat;
-
-	if (cache->nplanes = 1)
-		return cache;
-
-	ret = __meram_alloc(priv, &cache->planes[1], cfg->icb[1].meram_size);
-	if (ret < 0) {
-		__meram_free(priv, &cache->planes[0]);
-		goto error;
-	}
-
-	return cache;
-
-error:
-	kfree(cache);
-	return ERR_PTR(-ENOMEM);
-}
-
-/* Unmark the specified ICB as used. */
-static void meram_free(struct sh_mobile_meram_priv *priv,
-		       struct sh_mobile_meram_fb_cache *cache)
-{
-	__meram_free(priv, &cache->planes[0]);
-	if (cache->nplanes = 2)
-		__meram_free(priv, &cache->planes[1]);
-
-	kfree(cache);
-}
-
 /* Set the next address to fetch. */
 static void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
 				struct sh_mobile_meram_fb_cache *cache,
@@ -355,10 +299,10 @@ meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
 	(((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
 
 /* Initialize MERAM. */
-static int meram_init(struct sh_mobile_meram_priv *priv,
-		      struct sh_mobile_meram_fb_plane *plane,
-		      unsigned int xres, unsigned int yres,
-		      unsigned int *out_pitch)
+static int meram_plane_init(struct sh_mobile_meram_priv *priv,
+			    struct sh_mobile_meram_fb_plane *plane,
+			    unsigned int xres, unsigned int yres,
+			    unsigned int *out_pitch)
 {
 	struct sh_mobile_meram_icb *marker = plane->marker;
 	unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
@@ -427,8 +371,8 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
 	return 0;
 }
 
-static void meram_deinit(struct sh_mobile_meram_priv *priv,
-			 struct sh_mobile_meram_fb_plane *plane)
+static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv,
+				struct sh_mobile_meram_fb_plane *plane)
 {
 	/* disable ICB */
 	meram_write_icb(priv->base, plane->cache->index,  MExxCTL,
@@ -441,18 +385,60 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv,
 }
 
 /* -----------------------------------------------------------------------------
- * Registration/unregistration
+ * LCDC cache operations
  */
 
-static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
-				      const struct sh_mobile_meram_cfg *cfg,
-				      unsigned int xres, unsigned int yres,
-				      unsigned int pixelformat,
-				      unsigned int *pitch)
+/* Allocate memory for the ICBs and mark them as used. */
+static struct sh_mobile_meram_fb_cache *
+meram_cache_alloc(struct sh_mobile_meram_priv *priv,
+		  const struct sh_mobile_meram_cfg *cfg,
+		  int pixelformat)
+{
+	unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
+	struct sh_mobile_meram_fb_cache *cache;
+	int ret;
+
+	cache = kzalloc(sizeof(*cache), GFP_KERNEL);
+	if (cache = NULL)
+		return ERR_PTR(-ENOMEM);
+
+	cache->nplanes = nplanes;
+
+	ret = meram_plane_alloc(priv, &cache->planes[0],
+				cfg->icb[0].meram_size);
+	if (ret < 0)
+		goto error;
+
+	cache->planes[0].marker->current_reg = 1;
+	cache->planes[0].marker->pixelformat = pixelformat;
+
+	if (cache->nplanes = 1)
+		return cache;
+
+	ret = meram_plane_alloc(priv, &cache->planes[1],
+				cfg->icb[1].meram_size);
+	if (ret < 0) {
+		meram_plane_free(priv, &cache->planes[0]);
+		goto error;
+	}
+
+	return cache;
+
+error:
+	kfree(cache);
+	return ERR_PTR(-ENOMEM);
+}
+
+static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata,
+				   const struct sh_mobile_meram_cfg *cfg,
+				   unsigned int xres, unsigned int yres,
+				   unsigned int pixelformat,
+				   unsigned int *pitch)
 {
 	struct sh_mobile_meram_fb_cache *cache;
 	struct sh_mobile_meram_priv *priv = pdata->priv;
 	struct platform_device *pdev = pdata->pdev;
+	unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
 	unsigned int out_pitch;
 
 	if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
@@ -469,10 +455,16 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
 		return ERR_PTR(-EINVAL);
 	}
 
+	if (cfg->icb[0].meram_size = 0)
+		return ERR_PTR(-EINVAL);
+
+	if (nplanes = 2 && cfg->icb[1].meram_size = 0)
+		return ERR_PTR(-EINVAL);
+
 	mutex_lock(&priv->lock);
 
 	/* We now register the ICBs and allocate the MERAM regions. */
-	cache = meram_alloc(priv, cfg, pixelformat);
+	cache = meram_cache_alloc(priv, cfg, pixelformat);
 	if (IS_ERR(cache)) {
 		dev_err(&pdev->dev, "MERAM allocation failed (%ld).",
 			PTR_ERR(cache));
@@ -480,14 +472,14 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
 	}
 
 	/* initialize MERAM */
-	meram_init(priv, &cache->planes[0], xres, yres, &out_pitch);
+	meram_plane_init(priv, &cache->planes[0], xres, yres, &out_pitch);
 	*pitch = out_pitch;
 	if (pixelformat = SH_MOBILE_MERAM_PF_NV)
-		meram_init(priv, &cache->planes[1], xres, (yres + 1) / 2,
-			&out_pitch);
+		meram_plane_init(priv, &cache->planes[1],
+				 xres, (yres + 1) / 2, &out_pitch);
 	else if (pixelformat = SH_MOBILE_MERAM_PF_NV24)
-		meram_init(priv, &cache->planes[1], 2 * xres, (yres + 1) / 2,
-			&out_pitch);
+		meram_plane_init(priv, &cache->planes[1],
+				 2 * xres, (yres + 1) / 2, &out_pitch);
 
 err:
 	mutex_unlock(&priv->lock);
@@ -495,25 +487,29 @@ err:
 }
 
 static void
-sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata, void *data)
+sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data)
 {
 	struct sh_mobile_meram_fb_cache *cache = data;
 	struct sh_mobile_meram_priv *priv = pdata->priv;
 
 	mutex_lock(&priv->lock);
 
-	/* deinit & free */
-	meram_deinit(priv, &cache->planes[0]);
-	if (cache->nplanes = 2)
-		meram_deinit(priv, &cache->planes[1]);
+	/* Cleanup and free. */
+	meram_plane_cleanup(priv, &cache->planes[0]);
+	meram_plane_free(priv, &cache->planes[0]);
 
-	meram_free(priv, cache);
+	if (cache->nplanes = 2) {
+		meram_plane_cleanup(priv, &cache->planes[1]);
+		meram_plane_free(priv, &cache->planes[1]);
+	}
+
+	kfree(cache);
 
 	mutex_unlock(&priv->lock);
 }
 
 static void
-sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
+sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data,
 		       unsigned long base_addr_y, unsigned long base_addr_c,
 		       unsigned long *icb_addr_y, unsigned long *icb_addr_c)
 {
@@ -530,9 +526,9 @@ sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
 
 static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
 	.module			= THIS_MODULE,
-	.meram_register		= sh_mobile_meram_register,
-	.meram_unregister	= sh_mobile_meram_unregister,
-	.meram_update		= sh_mobile_meram_update,
+	.cache_alloc		= sh_mobile_cache_alloc,
+	.cache_free		= sh_mobile_cache_free,
+	.cache_update		= sh_mobile_cache_update,
 };
 
 /* -----------------------------------------------------------------------------
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
index 29b2fd3..8a5afaf 100644
--- a/include/video/sh_mobile_meram.h
+++ b/include/video/sh_mobile_meram.h
@@ -41,19 +41,14 @@ struct sh_mobile_meram_cfg {
 struct module;
 struct sh_mobile_meram_ops {
 	struct module	*module;
-	/* register usage of meram */
-	void *(*meram_register)(struct sh_mobile_meram_info *meram_dev,
-				const struct sh_mobile_meram_cfg *cfg,
-				unsigned int xres, unsigned int yres,
-				unsigned int pixelformat,
-				unsigned int *pitch);
-
-	/* unregister usage of meram */
-	void (*meram_unregister)(struct sh_mobile_meram_info *meram_dev,
-				 void *data);
-
-	/* update meram settings */
-	void (*meram_update)(struct sh_mobile_meram_info *meram_dev, void *data,
+
+	/* LCDC cache management */
+	void *(*cache_alloc)(struct sh_mobile_meram_info *meram_dev,
+			     const struct sh_mobile_meram_cfg *cfg,
+			     unsigned int xres, unsigned int yres,
+			     unsigned int pixelformat, unsigned int *pitch);
+	void (*cache_free)(struct sh_mobile_meram_info *meram_dev, void *data);
+	void (*cache_update)(struct sh_mobile_meram_info *meram_dev, void *data,
 			     unsigned long base_addr_y,
 			     unsigned long base_addr_c,
 			     unsigned long *icb_addr_y,
-- 
1.7.3.4


^ permalink raw reply related

* [RFC/PATCH 2/6] sh_mobile_meram: Use direct function calls for the public API
From: Laurent Pinchart @ 2012-03-15 17:43 UTC (permalink / raw)
  To: linux-fbdev

There's no reason to use abstract operation pointers to implement the
MERAM API. Replace them by direct function calls.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/sh_mobile_lcdcfb.c |   27 +++++++-------------
 drivers/video/sh_mobile_meram.c  |   34 +++++++++++--------------
 include/video/sh_mobile_meram.h  |   50 ++++++++++++++++++++++++++-----------
 3 files changed, 60 insertions(+), 51 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 1efc65e..cf80194 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -849,13 +849,12 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 		ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual;
 
 		/* Enable MERAM if possible. */
-		if (mdev = NULL || mdev->ops = NULL ||
-		    ch->cfg->meram_cfg = NULL)
+		if (mdev = NULL || ch->cfg->meram_cfg = NULL)
 			continue;
 
 		/* Free the allocated MERAM cache. */
 		if (ch->cache) {
-			mdev->ops->cache_free(mdev, ch->cache);
+			sh_mobile_meram_cache_free(mdev, ch->cache);
 			ch->cache = NULL;
 		}
 
@@ -878,11 +877,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 			break;
 		}
 
-		cache = mdev->ops->cache_alloc(mdev, ch->cfg->meram_cfg,
+		cache = sh_mobile_meram_cache_alloc(mdev, ch->cfg->meram_cfg,
 					ch->pitch, ch->yres, pixelformat,
 					&ch->pitch);
 		if (!IS_ERR(cache)) {
-			mdev->ops->cache_update(mdev, cache,
+			sh_mobile_meram_cache_update(mdev, cache,
 					ch->base_addr_y, ch->base_addr_c,
 					&ch->base_addr_y, &ch->base_addr_c);
 			ch->cache = cache;
@@ -952,9 +951,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
 
 		/* Free the MERAM cache. */
 		if (ch->cache) {
-			struct sh_mobile_meram_info *mdev;
-			mdev = priv->meram_dev;
-			mdev->ops->cache_free(mdev, ch->cache);
+			sh_mobile_meram_cache_free(priv->meram_dev, ch->cache);
 			ch->cache = 0;
 		}
 
@@ -1039,7 +1036,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
 	unsigned long ldrcntr;
 	unsigned long new_pan_offset;
-	unsigned long base_addr_y, base_addr_c;
+	unsigned long base_addr_y, base_addr_c = 0;
 	unsigned long c_offset;
 
 	if (!ch->format->yuv)
@@ -1068,14 +1065,10 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 			base_addr_c += var->xoffset;
 	}
 
-	if (ch->cache) {
-		struct sh_mobile_meram_info *mdev;
-
-		mdev = priv->meram_dev;
-		mdev->ops->cache_update(mdev, ch->cache,
-					base_addr_y, base_addr_c,
-					&base_addr_y, &base_addr_c);
-	}
+	if (ch->cache)
+		sh_mobile_meram_cache_update(priv->meram_dev, ch->cache,
+					     base_addr_y, base_addr_c,
+					     &base_addr_y, &base_addr_c);
 
 	ch->base_addr_y = base_addr_y;
 	ch->base_addr_c = base_addr_c;
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index 4aa3fcb..843fb29 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -429,11 +429,10 @@ error:
 	return ERR_PTR(-ENOMEM);
 }
 
-static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata,
-				   const struct sh_mobile_meram_cfg *cfg,
-				   unsigned int xres, unsigned int yres,
-				   unsigned int pixelformat,
-				   unsigned int *pitch)
+void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *pdata,
+				  const struct sh_mobile_meram_cfg *cfg,
+				  unsigned int xres, unsigned int yres,
+				  unsigned int pixelformat, unsigned int *pitch)
 {
 	struct sh_mobile_meram_fb_cache *cache;
 	struct sh_mobile_meram_priv *priv = pdata->priv;
@@ -441,6 +440,9 @@ static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata,
 	unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
 	unsigned int out_pitch;
 
+	if (priv = NULL)
+		return ERR_PTR(-ENODEV);
+
 	if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
 	    pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
 	    pixelformat != SH_MOBILE_MERAM_PF_RGB)
@@ -486,8 +488,8 @@ err:
 	return cache;
 }
 
-static void
-sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data)
+void
+sh_mobile_meram_cache_free(struct sh_mobile_meram_info *pdata, void *data)
 {
 	struct sh_mobile_meram_fb_cache *cache = data;
 	struct sh_mobile_meram_priv *priv = pdata->priv;
@@ -508,10 +510,12 @@ sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data)
 	mutex_unlock(&priv->lock);
 }
 
-static void
-sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data,
-		       unsigned long base_addr_y, unsigned long base_addr_c,
-		       unsigned long *icb_addr_y, unsigned long *icb_addr_c)
+void
+sh_mobile_meram_cache_update(struct sh_mobile_meram_info *pdata, void *data,
+			     unsigned long base_addr_y,
+			     unsigned long base_addr_c,
+			     unsigned long *icb_addr_y,
+			     unsigned long *icb_addr_c)
 {
 	struct sh_mobile_meram_fb_cache *cache = data;
 	struct sh_mobile_meram_priv *priv = pdata->priv;
@@ -524,13 +528,6 @@ sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data,
 	mutex_unlock(&priv->lock);
 }
 
-static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
-	.module			= THIS_MODULE,
-	.cache_alloc		= sh_mobile_cache_alloc,
-	.cache_free		= sh_mobile_cache_free,
-	.cache_update		= sh_mobile_cache_update,
-};
-
 /* -----------------------------------------------------------------------------
  * Power management
  */
@@ -620,7 +617,6 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
 	for (i = 0; i < MERAM_ICB_NUM; ++i)
 		priv->icbs[i].index = i;
 
-	pdata->ops = &sh_mobile_meram_ops;
 	pdata->priv = priv;
 	pdata->pdev = pdev;
 
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
index 8a5afaf..1134837 100644
--- a/include/video/sh_mobile_meram.h
+++ b/include/video/sh_mobile_meram.h
@@ -15,7 +15,6 @@ enum {
 
 
 struct sh_mobile_meram_priv;
-struct sh_mobile_meram_ops;
 
 /*
  * struct sh_mobile_meram_info - MERAM platform data
@@ -24,7 +23,6 @@ struct sh_mobile_meram_ops;
 struct sh_mobile_meram_info {
 	int				addr_mode;
 	u32				reserved_icbs;
-	struct sh_mobile_meram_ops	*ops;
 	struct sh_mobile_meram_priv	*priv;
 	struct platform_device		*pdev;
 };
@@ -38,21 +36,43 @@ struct sh_mobile_meram_cfg {
 	struct sh_mobile_meram_icb_cfg icb[2];
 };
 
-struct module;
-struct sh_mobile_meram_ops {
-	struct module	*module;
-
-	/* LCDC cache management */
-	void *(*cache_alloc)(struct sh_mobile_meram_info *meram_dev,
-			     const struct sh_mobile_meram_cfg *cfg,
-			     unsigned int xres, unsigned int yres,
-			     unsigned int pixelformat, unsigned int *pitch);
-	void (*cache_free)(struct sh_mobile_meram_info *meram_dev, void *data);
-	void (*cache_update)(struct sh_mobile_meram_info *meram_dev, void *data,
+#if defined(CONFIG_FB_SH_MOBILE_MERAM) || \
+    defined(CONFIG_FB_SH_MOBILE_MERAM_MODULE)
+void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
+				  const struct sh_mobile_meram_cfg *cfg,
+				  unsigned int xres, unsigned int yres,
+				  unsigned int pixelformat,
+				  unsigned int *pitch);
+void sh_mobile_meram_cache_free(struct sh_mobile_meram_info *dev, void *data);
+void sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data,
+				  unsigned long base_addr_y,
+				  unsigned long base_addr_c,
+				  unsigned long *icb_addr_y,
+				  unsigned long *icb_addr_c);
+#else
+static inline void *
+sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
+			    const struct sh_mobile_meram_cfg *cfg,
+			    unsigned int xres, unsigned int yres,
+			    unsigned int pixelformat,
+			    unsigned int *pitch)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline void
+sh_mobile_meram_cache_free(struct sh_mobile_meram_info *dev, void *data)
+{
+}
+
+static inline void
+sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data,
 			     unsigned long base_addr_y,
 			     unsigned long base_addr_c,
 			     unsigned long *icb_addr_y,
-			     unsigned long *icb_addr_c);
-};
+			     unsigned long *icb_addr_c)
+{
+}
+#endif
 
 #endif /* __VIDEO_SH_MOBILE_MERAM_H__  */
-- 
1.7.3.4


^ permalink raw reply related

* [RFC/PATCH 3/6] sh_mobile_meram: Add direct MERAM allocation API
From: Laurent Pinchart @ 2012-03-15 17:43 UTC (permalink / raw)
  To: linux-fbdev

The API can be used to allocate and free MERAM blocks directly, without
going through ICBs.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/sh_mobile_meram.c |   39 +++++++++++++++++++++++++++++++++++----
 include/video/sh_mobile_meram.h |   16 ++++++++++++++++
 2 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index 843fb29..ae9dc3b 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -194,6 +194,21 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
 }
 
 /* -----------------------------------------------------------------------------
+ * MERAM allocation and free
+ */
+
+static unsigned long meram_alloc(struct sh_mobile_meram_priv *priv, size_t size)
+{
+	return gen_pool_alloc(priv->pool, size);
+}
+
+static void meram_free(struct sh_mobile_meram_priv *priv, unsigned long mem,
+		       size_t size)
+{
+	gen_pool_free(priv->pool, mem, size);
+}
+
+/* -----------------------------------------------------------------------------
  * LCDC cache planes allocation, init, cleanup and free
  */
 
@@ -215,7 +230,7 @@ static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
 		return -ENOMEM;
 	plane->marker = &priv->icbs[idx];
 
-	mem = gen_pool_alloc(priv->pool, size * 1024);
+	mem = meram_alloc(priv, size * 1024);
 	if (mem = 0)
 		return -ENOMEM;
 
@@ -232,8 +247,8 @@ static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
 static void meram_plane_free(struct sh_mobile_meram_priv *priv,
 			     struct sh_mobile_meram_fb_plane *plane)
 {
-	gen_pool_free(priv->pool, priv->meram + plane->marker->offset,
-		      plane->marker->size * 1024);
+	meram_free(priv, priv->meram + plane->marker->offset,
+		   plane->marker->size * 1024);
 
 	__clear_bit(plane->marker->index, &priv->used_icb);
 	__clear_bit(plane->cache->index, &priv->used_icb);
@@ -385,9 +400,25 @@ static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv,
 }
 
 /* -----------------------------------------------------------------------------
- * LCDC cache operations
+ * MERAM operations
  */
 
+unsigned long sh_mobile_meram_alloc(struct sh_mobile_meram_info *pdata,
+				    size_t size)
+{
+	struct sh_mobile_meram_priv *priv = pdata->priv;
+
+	return meram_alloc(priv, size);
+}
+
+void sh_mobile_meram_free(struct sh_mobile_meram_info *pdata, unsigned long mem,
+			  size_t size)
+{
+	struct sh_mobile_meram_priv *priv = pdata->priv;
+
+	meram_free(priv, mem, size);
+}
+
 /* Allocate memory for the ICBs and mark them as used. */
 static struct sh_mobile_meram_fb_cache *
 meram_cache_alloc(struct sh_mobile_meram_priv *priv,
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
index 1134837..062e6e7 100644
--- a/include/video/sh_mobile_meram.h
+++ b/include/video/sh_mobile_meram.h
@@ -38,6 +38,10 @@ struct sh_mobile_meram_cfg {
 
 #if defined(CONFIG_FB_SH_MOBILE_MERAM) || \
     defined(CONFIG_FB_SH_MOBILE_MERAM_MODULE)
+unsigned long sh_mobile_meram_alloc(struct sh_mobile_meram_info *meram_dev,
+				    size_t size);
+void sh_mobile_meram_free(struct sh_mobile_meram_info *meram_dev,
+			  unsigned long mem, size_t size);
 void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
 				  const struct sh_mobile_meram_cfg *cfg,
 				  unsigned int xres, unsigned int yres,
@@ -50,6 +54,18 @@ void sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data,
 				  unsigned long *icb_addr_y,
 				  unsigned long *icb_addr_c);
 #else
+static inline unsigned long
+sh_mobile_meram_alloc(struct sh_mobile_meram_info *meram_dev, size_t size)
+{
+	return 0;
+}
+
+static inline void
+sh_mobile_meram_free(struct sh_mobile_meram_info *meram_dev,
+		     unsigned long mem, size_t size)
+{
+}
+
 static inline void *
 sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
 			    const struct sh_mobile_meram_cfg *cfg,
-- 
1.7.3.4


^ permalink raw reply related

* [RFC/PATCH 4/6] fbdev: sh_mobile_lcdc: Fix pan offset computation in YUV mode
From: Laurent Pinchart @ 2012-03-15 17:43 UTC (permalink / raw)
  To: linux-fbdev

The chroma plane offset in memory is equal to the luma plane maximum
size. Fix offset computations.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/sh_mobile_lcdcfb.c |   57 ++++++++++++++++++--------------------
 drivers/video/sh_mobile_lcdcfb.h |    5 ++-
 2 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index cf80194..2009432 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -846,7 +846,8 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 			continue;
 
 		ch->base_addr_y = ch->dma_handle;
-		ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual;
+		ch->base_addr_c = ch->dma_handle
+				+ ch->xres_virtual * ch->yres_virtual;
 
 		/* Enable MERAM if possible. */
 		if (mdev = NULL || ch->cfg->meram_cfg = NULL)
@@ -1035,35 +1036,30 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 	struct sh_mobile_lcdc_chan *ch = info->par;
 	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
 	unsigned long ldrcntr;
-	unsigned long new_pan_offset;
 	unsigned long base_addr_y, base_addr_c = 0;
+	unsigned long y_offset;
 	unsigned long c_offset;
 
-	if (!ch->format->yuv)
-		new_pan_offset = var->yoffset * ch->pitch
-			       + var->xoffset * (ch->format->bpp / 8);
-	else
-		new_pan_offset = var->yoffset * ch->pitch + var->xoffset;
-
-	if (new_pan_offset = ch->pan_offset)
-		return 0;	/* No change, do nothing */
+	if (!ch->format->yuv) {
+		y_offset = (var->yoffset * ch->xres_virtual + var->xoffset)
+			 * ch->format->bpp / 8;
+		c_offset = 0;
+	} else {
+		y_offset = var->yoffset * ch->xres_virtual + var->xoffset;
+		c_offset = (var->yoffset * ch->xres_virtual + var->xoffset)
+			 * (ch->format->bpp - 8) / 8;
+	}
 
-	ldrcntr = lcdc_read(priv, _LDRCNTR);
+	/* If the Y offset hasn't changed, the C offset hasn't either. There's
+	 * nothing to do in that case.
+	 */
+	if (y_offset = ch->pan_y_offset)
+		return 0;
 
 	/* Set the source address for the next refresh */
-	base_addr_y = ch->dma_handle + new_pan_offset;
-	if (ch->format->yuv) {
-		/* Set y offset */
-		c_offset = var->yoffset * ch->pitch
-			 * (ch->format->bpp - 8) / 8;
-		base_addr_c = ch->dma_handle + ch->xres * ch->yres_virtual
-			    + c_offset;
-		/* Set x offset */
-		if (ch->format->fourcc = V4L2_PIX_FMT_NV24)
-			base_addr_c += 2 * var->xoffset;
-		else
-			base_addr_c += var->xoffset;
-	}
+	base_addr_y = ch->dma_handle + y_offset;
+	base_addr_c = ch->dma_handle + ch->xres_virtual * ch->yres_virtual
+		    + c_offset;
 
 	if (ch->cache)
 		sh_mobile_meram_cache_update(priv->meram_dev, ch->cache,
@@ -1072,17 +1068,19 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 
 	ch->base_addr_y = base_addr_y;
 	ch->base_addr_c = base_addr_c;
+	ch->pan_y_offset = y_offset;
+	ch->pan_c_offset = c_offset;
 
 	lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
 	if (ch->format->yuv)
 		lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
 
+	ldrcntr = lcdc_read(priv, _LDRCNTR);
 	if (lcdc_chan_is_sublcd(ch))
 		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
 	else
 		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
 
-	ch->pan_offset = new_pan_offset;
 
 	sh_mobile_lcdc_deferred_io_touch(info);
 
@@ -1319,9 +1317,9 @@ static int sh_mobile_set_par(struct fb_info *info)
 	ch->yres_virtual = info->var.yres_virtual;
 
 	if (ch->format->yuv)
-		ch->pitch = info->var.xres;
+		ch->pitch = info->var.xres_virtual;
 	else
-		ch->pitch = info->var.xres * ch->format->bpp / 8;
+		ch->pitch = info->var.xres_virtual * ch->format->bpp / 8;
 
 	ret = sh_mobile_lcdc_start(ch->lcdc);
 	if (ret < 0)
@@ -1853,10 +1851,10 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
 
 	if (!format->yuv) {
 		ch->colorspace = V4L2_COLORSPACE_SRGB;
-		ch->pitch = ch->xres * format->bpp / 8;
+		ch->pitch = ch->xres_virtual * format->bpp / 8;
 	} else {
 		ch->colorspace = V4L2_COLORSPACE_REC709;
-		ch->pitch = ch->xres;
+		ch->pitch = ch->xres_virtual;
 	}
 
 	ch->display.width = cfg->panel_cfg.width;
@@ -1942,7 +1940,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 		}
 		init_waitqueue_head(&ch->frame_end_wait);
 		init_completion(&ch->vsync_completion);
-		ch->pan_offset = 0;
 
 		/* probe the backlight is there is one defined */
 		if (ch->cfg->bl_info.max_brightness)
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index 698fb20..5320ad4 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -47,6 +47,8 @@ struct sh_mobile_lcdc_entity {
 /*
  * struct sh_mobile_lcdc_chan - LCDC display channel
  *
+ * @pan_y_offset: Panning linear offset in bytes (luma component)
+ * @pan_c_offset: Panning linear offset in bytes (chroma component)
  * @base_addr_y: Frame buffer viewport base address (luma component)
  * @base_addr_c: Frame buffer viewport base address (chroma component)
  * @pitch: Frame buffer line pitch
@@ -68,7 +70,8 @@ struct sh_mobile_lcdc_chan {
 	unsigned long fb_size;
 
 	dma_addr_t dma_handle;
-	unsigned long pan_offset;
+	unsigned long pan_y_offset;
+	unsigned long pan_c_offset;
 
 	unsigned long frame_end;
 	wait_queue_head_t frame_end_wait;
-- 
1.7.3.4


^ permalink raw reply related

* [RFC/PATCH 5/6] fbdev: sh_mobile_lcdc: Destroy mutex at remove time
From: Laurent Pinchart @ 2012-03-15 17:43 UTC (permalink / raw)
  To: linux-fbdev

Add a missing mutex_destroy() call when the driver is unbound from the
device.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/sh_mobile_lcdcfb.c |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 2009432..23d0446 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -1725,8 +1725,11 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
 	}
 
 	for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
-		if (priv->ch[i].bl)
-			sh_mobile_lcdc_bl_remove(priv->ch[i].bl);
+		struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
+
+		if (ch->bl)
+			sh_mobile_lcdc_bl_remove(ch->bl);
+		mutex_destroy(&ch->open_lock);
 	}
 
 	if (priv->dot_clk) {
-- 
1.7.3.4


^ permalink raw reply related

* [RFC/PATCH 6/6] fbdev: sh_mobile_lcdc: Added MERAM-backed frame buffer support
From: Laurent Pinchart @ 2012-03-15 17:43 UTC (permalink / raw)
  To: linux-fbdev

Storing the frame buffer in the MERAM allows system memory to be put to
a low power state (assuming the CPU is idle). However, the MERAM size
doesn't allow for double-buffering of large frame buffers in a high bit
per pixel format. The frame buffer can't thus be permanently stored in
MERAM.

The optional frame buffer MERAM backing store allows switching between
system memory and MERAM at runtime. The backing store is selected by
userspace through the backingstore sysfs property. When switching to
MERAM to frame buffer contents are copied to the allocated MERAM backing
store. This freezes the display until switching back to system memory,
or panning which triggers a display update.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/sh_mobile_lcdcfb.c |  145 +++++++++++++++++++++++++++++++++++---
 drivers/video/sh_mobile_lcdcfb.h |    3 +
 include/video/sh_mobile_lcdc.h   |    1 +
 3 files changed, 139 insertions(+), 10 deletions(-)

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 23d0446..a443592 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -971,6 +971,117 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
 }
 
 /* -----------------------------------------------------------------------------
+ * MERAM backing store
+ */
+
+static void sh_mobile_lcdc_set_fb_addr(struct sh_mobile_lcdc_chan *ch,
+				       unsigned long addr_y,
+				       unsigned long addr_c)
+{
+	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
+	unsigned long ldrcntr;
+
+	lcdc_write_chan_mirror(ch, LDSA1R, addr_y);
+	if (ch->format->yuv)
+		lcdc_write_chan_mirror(ch, LDSA2R, addr_c);
+
+	ldrcntr = lcdc_read(priv, _LDRCNTR);
+	if (lcdc_chan_is_sublcd(ch))
+		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
+	else
+		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
+}
+
+/*
+ * sh_mobile_lcdc_copy_fb_memory - Copy frame buffer from system memory to MERAM
+ *
+ * Copy the visible frame buffer content (taking pan offsets into account) from
+ * system memory to a contiguous memory block in MERAM.
+ */
+static void sh_mobile_lcdc_copy_fb_memory(struct sh_mobile_lcdc_chan *ch)
+{
+	void *fb_mem = ch->fb_mem;
+	void __iomem *mem;
+	size_t size;
+
+	if (ch->fb_meram = 0)
+		return;
+
+	size = ch->xres * ch->yres * ch->format->bpp / 8;
+	mem = ioremap_wc(ch->fb_meram, size);
+	if (mem = NULL)
+		return;
+
+	memcpy_toio(mem, fb_mem + ch->pan_y_offset, size);
+	if (ch->format->yuv) {
+		fb_mem = ch->fb_mem + ch->xres_virtual * ch->yres_virtual;
+		memcpy_toio(mem + ch->xres * ch->yres,
+			    fb_mem + ch->pan_c_offset,
+			    size - ch->xres * ch->yres);
+	}
+
+	iounmap(mem);
+}
+
+static ssize_t lcdc_backing_store_show(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct sh_mobile_lcdc_chan *ch = info->par;
+
+	return scnprintf(buf, PAGE_SIZE, "%s\n",
+			 ch->fb_in_meram ? "meram" : "system");
+}
+
+static ssize_t lcdc_backing_store_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct sh_mobile_lcdc_chan *ch = info->par;
+	bool fb_in_meram;
+
+	if (strncmp(buf, "system", 6) = 0)
+		fb_in_meram = false;
+	else if (strncmp(buf, "meram", 5) = 0)
+		fb_in_meram = true;
+	else
+		return -EINVAL;
+
+	mutex_lock(&ch->meram_lock);
+
+	printk(KERN_INFO "%s: fb_in_meram is %s, wants %s\n", __func__,
+		ch->fb_in_meram ? "true" : "false",
+		fb_in_meram ? "true" : "false");
+	if (ch->fb_in_meram = fb_in_meram)
+		goto done;
+
+	if (fb_in_meram) {
+		unsigned long base_addr_y;
+		unsigned long base_addr_c;
+
+		base_addr_y = ch->fb_meram;
+		base_addr_c = ch->fb_meram + ch->xres * ch->yres;
+
+		sh_mobile_lcdc_copy_fb_memory(ch);
+		sh_mobile_lcdc_set_fb_addr(ch, base_addr_y, base_addr_c);
+	} else {
+		sh_mobile_lcdc_set_fb_addr(ch, ch->base_addr_y,
+					   ch->base_addr_c);
+	}
+
+	ch->fb_in_meram = fb_in_meram;
+
+done:
+	mutex_unlock(&ch->meram_lock);
+	return count;
+}
+
+static const struct device_attribute lcdc_backing_store_attr +	__ATTR(backingstore, S_IRUGO|S_IWUSR,
+	       lcdc_backing_store_show, lcdc_backing_store_store);
+
+/* -----------------------------------------------------------------------------
  * Frame buffer operations
  */
 
@@ -1035,7 +1146,6 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 {
 	struct sh_mobile_lcdc_chan *ch = info->par;
 	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
-	unsigned long ldrcntr;
 	unsigned long base_addr_y, base_addr_c = 0;
 	unsigned long y_offset;
 	unsigned long c_offset;
@@ -1071,16 +1181,16 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 	ch->pan_y_offset = y_offset;
 	ch->pan_c_offset = c_offset;
 
-	lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
-	if (ch->format->yuv)
-		lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
+	sh_mobile_lcdc_set_fb_addr(ch, base_addr_y, base_addr_c);
 
-	ldrcntr = lcdc_read(priv, _LDRCNTR);
-	if (lcdc_chan_is_sublcd(ch))
-		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
-	else
-		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
+	if (ch->fb_in_meram) {
+		sh_mobile_wait_for_vsync(ch);
+		sh_mobile_lcdc_copy_fb_memory(ch);
 
+		base_addr_y = ch->fb_meram;
+		base_addr_c = ch->fb_meram + ch->xres * ch->yres;
+		sh_mobile_lcdc_set_fb_addr(ch, base_addr_y, base_addr_c);
+	}
 
 	sh_mobile_lcdc_deferred_io_touch(info);
 
@@ -1431,11 +1541,17 @@ sh_mobile_lcdc_channel_fb_register(struct sh_mobile_lcdc_chan *ch)
 		 "mainlcd" : "sublcd", info->var.xres, info->var.yres,
 		 info->var.bits_per_pixel);
 
+	if (ch->fb_meram) {
+		ret = device_create_file(info->dev, &lcdc_backing_store_attr);
+		if (ret < 0)
+			return ret;
+	}
+
 	/* deferred io mode: disable clock to save power */
 	if (info->fbdefio || info->state = FBINFO_STATE_SUSPENDED)
 		sh_mobile_lcdc_clk_off(ch->lcdc);
 
-	return ret;
+	return 0;
 }
 
 static void
@@ -1722,6 +1838,9 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
 		if (ch->fb_mem)
 			dma_free_coherent(&pdev->dev, ch->fb_size,
 					  ch->fb_mem, ch->dma_handle);
+		if (ch->fb_meram)
+			sh_mobile_meram_free(priv->meram_dev, ch->fb_meram,
+					     ch->fb_size / 2);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
@@ -1730,6 +1849,7 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
 		if (ch->bl)
 			sh_mobile_lcdc_bl_remove(ch->bl);
 		mutex_destroy(&ch->open_lock);
+		mutex_destroy(&ch->meram_lock);
 	}
 
 	if (priv->dot_clk) {
@@ -1799,6 +1919,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
 	unsigned int i;
 
 	mutex_init(&ch->open_lock);
+	mutex_init(&ch->meram_lock);
 	ch->notify = sh_mobile_lcdc_display_notify;
 
 	/* Validate the format. */
@@ -1873,6 +1994,10 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
 		return -ENOMEM;
 	}
 
+	if (cfg->meram_backing_store)
+		ch->fb_meram = sh_mobile_meram_alloc(priv->meram_dev,
+						     ch->fb_size / 2);
+
 	/* Initialize the transmitter device if present. */
 	if (cfg->tx_dev) {
 		if (!cfg->tx_dev->dev.driver ||
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index 5320ad4..9796740 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -68,6 +68,9 @@ struct sh_mobile_lcdc_chan {
 
 	void *fb_mem;
 	unsigned long fb_size;
+	unsigned long fb_meram;
+	bool fb_in_meram;
+	struct mutex meram_lock;	/* protects fb_in_meram */
 
 	dma_addr_t dma_handle;
 	unsigned long pan_y_offset;
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index 7571b27..3ceb221 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -179,6 +179,7 @@ struct sh_mobile_lcdc_chan_cfg {
 	struct sh_mobile_lcdc_bl_info bl_info;
 	struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */
 	const struct sh_mobile_meram_cfg *meram_cfg;
+	bool meram_backing_store;
 
 	struct platform_device *tx_dev;	/* HDMI/DSI transmitter device */
 };
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH 1/2] OMAPDSS: provide default get_timings function for panels
From: Grazvydas Ignotas @ 2012-03-15 18:00 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-omap, Tomi Valkeinen, Grazvydas Ignotas

With this we can eliminate some duplicate code in panel drivers.
Also lgphilips-lb035q02, nec-nl8048hl11-01b, picodlp and
tpo-td043mtea1 gain support of reading timings over sysfs.

Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
---
 drivers/video/omap2/displays/panel-acx565akm.c   |    7 -------
 drivers/video/omap2/displays/panel-generic-dpi.c |    7 -------
 drivers/video/omap2/displays/panel-n8x0.c        |    8 --------
 drivers/video/omap2/displays/panel-taal.c        |    8 --------
 drivers/video/omap2/dss/core.c                   |    2 ++
 drivers/video/omap2/dss/display.c                |    7 +++++++
 drivers/video/omap2/dss/venc.c                   |    7 -------
 include/video/omapdss.h                          |    2 ++
 8 files changed, 11 insertions(+), 37 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index dbd59b8..d82f09b 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -738,12 +738,6 @@ static void acx_panel_set_timings(struct omap_dss_device *dssdev,
 	}
 }
 
-static void acx_panel_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	*timings = dssdev->panel.timings;
-}
-
 static int acx_panel_check_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
@@ -761,7 +755,6 @@ static struct omap_dss_driver acx_panel_driver = {
 	.resume		= acx_panel_resume,
 
 	.set_timings	= acx_panel_set_timings,
-	.get_timings	= acx_panel_get_timings,
 	.check_timings	= acx_panel_check_timings,
 
 	.get_recommended_bpp = acx_get_recommended_bpp,
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 519c47d..445ea2d 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -460,12 +460,6 @@ static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
 	dpi_set_timings(dssdev, timings);
 }
 
-static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	*timings = dssdev->panel.timings;
-}
-
 static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
@@ -482,7 +476,6 @@ static struct omap_dss_driver dpi_driver = {
 	.resume		= generic_dpi_panel_resume,
 
 	.set_timings	= generic_dpi_panel_set_timings,
-	.get_timings	= generic_dpi_panel_get_timings,
 	.check_timings	= generic_dpi_panel_check_timings,
 
 	.driver         = {
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index 150e8ba..eba98a0 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -610,12 +610,6 @@ static int n8x0_panel_resume(struct omap_dss_device *dssdev)
 	return 0;
 }
 
-static void n8x0_panel_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
-{
-	*timings = dssdev->panel.timings;
-}
-
 static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
 		u16 *xres, u16 *yres)
 {
@@ -678,8 +672,6 @@ static struct omap_dss_driver n8x0_panel_driver = {
 	.get_resolution	= n8x0_panel_get_resolution,
 	.get_recommended_bpp = omapdss_default_get_recommended_bpp,
 
-	.get_timings	= n8x0_panel_get_timings,
-
 	.driver         = {
 		.name   = "n8x0_panel",
 		.owner  = THIS_MODULE,
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 80c3f6a..174c004 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -583,12 +583,6 @@ static const struct backlight_ops taal_bl_ops = {
 	.update_status  = taal_bl_update_status,
 };
 
-static void taal_get_timings(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings)
-{
-	*timings = dssdev->panel.timings;
-}
-
 static void taal_get_resolution(struct omap_dss_device *dssdev,
 		u16 *xres, u16 *yres)
 {
@@ -1899,8 +1893,6 @@ static struct omap_dss_driver taal_driver = {
 	.run_test	= taal_run_test,
 	.memory_read	= taal_memory_read,
 
-	.get_timings	= taal_get_timings,
-
 	.driver         = {
 		.name   = "taal",
 		.owner  = THIS_MODULE,
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 86ec12e..767e132 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -434,6 +434,8 @@ int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
 	if (dssdriver->get_recommended_bpp = NULL)
 		dssdriver->get_recommended_bpp  			omapdss_default_get_recommended_bpp;
+	if (dssdriver->get_timings = NULL)
+		dssdriver->get_timings = omapdss_default_get_timings;
 
 	return driver_register(&dssdriver->driver);
 }
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index be331dc..0878e0a 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -318,6 +318,13 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
 }
 EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
 
+void omapdss_default_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	*timings = dssdev->panel.timings;
+}
+EXPORT_SYMBOL(omapdss_default_get_timings);
+
 /* Checks if replication logic should be used. Only use for active matrix,
  * when overlay is in RGB12U or RGB16 mode, and LCD interface is
  * 18bpp or 24bpp */
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 7bb6219..dee2ec4 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -557,12 +557,6 @@ static int venc_panel_resume(struct omap_dss_device *dssdev)
 	return venc_panel_enable(dssdev);
 }
 
-static void venc_get_timings(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings)
-{
-	*timings = dssdev->panel.timings;
-}
-
 static void venc_set_timings(struct omap_dss_device *dssdev,
 			struct omap_video_timings *timings)
 {
@@ -641,7 +635,6 @@ static struct omap_dss_driver venc_driver = {
 	.get_resolution	= omapdss_default_get_resolution,
 	.get_recommended_bpp = omapdss_default_get_recommended_bpp,
 
-	.get_timings	= venc_get_timings,
 	.set_timings	= venc_set_timings,
 	.check_timings	= venc_check_timings,
 
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 378c7ed..0a0c038 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -646,6 +646,8 @@ struct omap_overlay *omap_dss_get_overlay(int num);
 void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
 		u16 *xres, u16 *yres);
 int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev);
+void omapdss_default_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings);
 
 typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/2] OMAPDSS: TPO-TD03MTEA1: add set/check timing functions
From: Grazvydas Ignotas @ 2012-03-15 18:00 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-omap, Tomi Valkeinen, Grazvydas Ignotas
In-Reply-To: <1331834424-485-1-git-send-email-notasas@gmail.com>

On pandora we use .set_timings to alter refresh rate,
so add .check_timings/.set_timings functions.

Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
---
 .../video/omap2/displays/panel-tpo-td043mtea1.c    |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index bb3da0b..be89801 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -477,6 +477,18 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev)
 		gpio_free(nreset_gpio);
 }
 
+static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	dpi_set_timings(dssdev, timings);
+}
+
+static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	return dpi_check_timings(dssdev, timings);
+}
+
 static struct omap_dss_driver tpo_td043_driver = {
 	.probe		= tpo_td043_probe,
 	.remove		= tpo_td043_remove,
@@ -488,6 +500,9 @@ static struct omap_dss_driver tpo_td043_driver = {
 	.set_mirror	= tpo_td043_set_hmirror,
 	.get_mirror	= tpo_td043_get_hmirror,
 
+	.set_timings	= tpo_td043_set_timings,
+	.check_timings	= tpo_td043_check_timings,
+
 	.driver         = {
 		.name	= "tpo_td043mtea1_panel",
 		.owner  = THIS_MODULE,
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH] video: pxafb: add clk_prepare/clk_unprepare calls
From: Philipp Zabel @ 2012-03-15 18:12 UTC (permalink / raw)
  To: linux-fbdev

This patch adds clk_prepare/clk_unprepare calls to the pxafb
driver by using the helper functions clk_prepare_enable and
clk_disable_unprepare.

Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
Cc: Haojian Zhuang <haojian.zhuang@marvell.com>
Cc: Eric Miao <eric.y.miao@gmail.com>
Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
 drivers/video/pxafb.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 1d1e4f1..904f839 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1431,7 +1431,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
 	pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
 
 	/* enable LCD controller clock */
-	clk_enable(fbi->clk);
+	clk_prepare_enable(fbi->clk);
 
 	if (fbi->lccr0 & LCCR0_LCDT)
 		return;
@@ -1471,7 +1471,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
 	wait_for_completion_timeout(&fbi->disable_done, 200 * HZ / 1000);
 
 	/* disable LCD controller clock */
-	clk_disable(fbi->clk);
+	clk_disable_unprepare(fbi->clk);
 }
 
 /*
-- 
1.7.9.1



^ permalink raw reply related

* Re: [Linux-fbdev-devel] [uclinux-dist-devel] [PATCH] [#7001] framebuffer: old image of last app woul
From: Mike Frysinger @ 2012-03-15 19:08 UTC (permalink / raw)
  To: linux-fbdev


[-- Attachment #1.1: Type: Text/Plain, Size: 513 bytes --]

On Thursday 15 March 2012 05:23:50 Wu, Aaron wrote:
> Old image of last application would retain for a while when starting a new
> application, this patch clear the frambuffer before displaying every time
> the fb is opened.

i'm not sure the behavior you describe is wrong.  in fact, i'm pretty sure it 
sounds correct.  if an app writes an image to the framebuffer and then quits, 
that image should stay there indefinitely until something else opens the 
framebuffer and draws their own image.
-mike

[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 191 bytes --]

------------------------------------------------------------------------------
This SF email is sponsosred by:
Try Windows Azure free for 90 days Click Here 
http://p.sf.net/sfu/sfd2d-msazure

[-- Attachment #3: Type: text/plain, Size: 182 bytes --]

_______________________________________________
Linux-fbdev-devel mailing list
Linux-fbdev-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox