* Re: [PATCH v2 3/3] ARM: Samsung: Rework platform data of s3c-fb driver
From: Darius Augulis @ 2012-03-16 7:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <001d01cd0315$935cc720$ba165560$%han@samsung.com>
On Fri, Mar 16, 2012 at 3:39 AM, Jingoo Han <jg1.han@samsung.com> wrote:
>> > 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.
>
> [CC'ed Tushar Behera]
>
> Yes, your code is working. However, your code is bug.
it's not a bug, because it's working like it was intended to. it was
reviewed and accepted by maintainers before merging to main line.
you do not have rights to drop it because you don't like it.
You are doing changes - please do it correctly and do not break
existing functionality.
btw, you still not answered my question: why these two s3c_fb_pd_win
structures in mach-mini6410.c is a problem? They are declared on the
stack, but platform data uses only single one. mini6410 rewrites its
s3c-fb platform data with data from one of these two structures
dynamically. Why it's a bug? You want to remove this dynamic selection
which could be leaved there with reworked framework too.
> 'struct s3c_fb_pd_win' is used not for LCD, but for windows of FIMD IP. So, 'struct s3c_fb_pd_win' should not be used to select LCD.
> The mach-aquila.c uses two 'struct s3c_fb_pd_win' like you, however 'struct s3c_fb_pd_win' don't make problem with Thomas's
> patchset. It is because mach-aquila.c use 'struct s3c_fb_pd_win' for only windows of FIMD IP.
> We don't have to responsibility to keep wrong code. If you have kept the rule, Thomas's patch would not make the compatibility
> problem with your code. Why we should keep aberration such as your code? If you want to select two LCDs, please find other way.
>
>
>>
>> Darius A.
>
^ permalink raw reply
* Re: [PATCH] [#7001] framebuffer: old image of last app would retain for a while after starting new app
From: Mike Frysinger @ 2012-03-16 5:21 UTC (permalink / raw)
To: Zhang, Sonic; +Cc: uclinux-dist-devel, Wu, Aaron, linux-fbdev-devel
In-Reply-To: <DB904C5425BA6F4E8424B3B51A1414D16F24304D64@NWD2CMBX1.ad.analog.com>
[-- Attachment #1.1: Type: Text/Plain, Size: 2145 bytes --]
On Friday 16 March 2012 01:05:10 Zhang, Sonic wrote:
> From: Mike Frysinger [mailto:vapier@gentoo.org]
>> On Thursday 15 March 2012 23:34:08 Zhang, Sonic wrote:
>>> From: Mike Frysinger [mailto:vapier@gentoo.org]
>>>> 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.
>>>
>>> Before the second application draws its own image, the image of last
>>> application has already been displayed on the LCD when the second
>>> application opens the FB device(PPI is enabled when it is opened).
>>> This is not a correct behavior.
>>
>> sure it is. if the app wants to clear the screen, it can do so. generally
>> it's going to anyways by drawing an entire frame. having the frame buffer
>> driver always clear the screen introduces wasted memory overhead as it
>> does the memset(), and user-visible jank as the device transitions from an
>> initial splash screen to the main userspace app.
>>
>> this is a policy decision that doesn't really belong in kernel space. and
>> if it did, it should be agreed upon by all frame buffer users and not just
>> changing a few drivers.
>
> How can the application clean the screen before it opens the FB device?
why does it need to be before open ? if the kernel does the memset or
userspace does the memset, the frame still gets cleared.
in looking at the blackfin framebuffer drivers, i'm not sure they're correct. i
don't think the PPI/DMA should be shutdown when the last user space client
closes it. fb_release is for releasing all resources when tearing down the
driver, and fb_blank is runtime management (turning off vsync/hsync and
powering down the screen).
-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
* Re: [PATCH] [#7001] framebuffer: old image of last app would retain for a while after starting new app
From: Zhang, Sonic @ 2012-03-16 5:05 UTC (permalink / raw)
To: Mike Frysinger
Cc: uclinux-dist-devel-ZG0+EudsQA8dtHy/vicBwGD2FQJk+8+b@public.gmane.org,
Wu, Aaron,
linux-fbdev-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
In-Reply-To: <201203152354.33365.vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
-----Original Message-----
From: Mike Frysinger [mailto:vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org]
Sent: Friday, March 16, 2012 11:55 AM
To: Zhang, Sonic
Cc: uclinux-dist-devel-ZG0+EudsQA8dtHy/vicBwGD2FQJk+8+b@public.gmane.org; Wu, Aaron; linux-fbdev-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
Subject: Re: [PATCH] [#7001] framebuffer: old image of last app would retain for a while after starting new app
On Thursday 15 March 2012 23:34:08 Zhang, Sonic wrote:
> From: Mike Frysinger [mailto:vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org]
>> 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.
>
> Before the second application draws its own image, the image of last
> application has already been displayed on the LCD when the second
> application opens the FB device(PPI is enabled when it is opened).
> This is not a correct behavior.
sure it is. if the app wants to clear the screen, it can do so. generally it's going to anyways by drawing an entire frame. having the frame buffer driver always clear the screen introduces wasted memory overhead as it does the memset(), and user-visible jank as the device transitions from an initial splash screen to the main userspace app.
this is a policy decision that doesn't really belong in kernel space. and if it did, it should be agreed upon by all frame buffer users and not just changing a few drivers.
-mike
How can the application clean the screen before it opens the FB device?
Sonic
^ permalink raw reply
* Re: [PATCH] [#7001] framebuffer: old image of last app would retain for a while after starting new app
From: Mike Frysinger @ 2012-03-16 3:54 UTC (permalink / raw)
To: Zhang, Sonic; +Cc: uclinux-dist-devel, Wu, Aaron, linux-fbdev-devel
In-Reply-To: <DB904C5425BA6F4E8424B3B51A1414D16F24304D28@NWD2CMBX1.ad.analog.com>
[-- Attachment #1.1: Type: Text/Plain, Size: 1432 bytes --]
On Thursday 15 March 2012 23:34:08 Zhang, Sonic wrote:
> From: Mike Frysinger [mailto:vapier@gentoo.org]
>> 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.
>
> Before the second application draws its own image, the image of last
> application has already been displayed on the LCD when the second
> application opens the FB device(PPI is enabled when it is opened). This is
> not a correct behavior.
sure it is. if the app wants to clear the screen, it can do so. generally
it's going to anyways by drawing an entire frame. having the frame buffer
driver always clear the screen introduces wasted memory overhead as it does
the memset(), and user-visible jank as the device transitions from an initial
splash screen to the main userspace app.
this is a policy decision that doesn't really belong in kernel space. and if
it did, it should be agreed upon by all frame buffer users and not just
changing a few drivers.
-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
* Re: [PATCH] [#7001] framebuffer: old image of last app would retain for a while after starting new app
From: Zhang, Sonic @ 2012-03-16 3:34 UTC (permalink / raw)
To: Mike Frysinger,
uclinux-dist-devel-ZG0+EudsQA8dtHy/vicBwGD2FQJk+8+b@public.gmane.org
Cc: Wu, Aaron,
linux-fbdev-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
In-Reply-To: <201203151508.04564.vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
-----Original Message-----
From: Mike Frysinger [mailto:vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org]
Sent: Friday, March 16, 2012 3:08 AM
To: uclinux-dist-devel-ZG0+EudsQA8dtHy/vicBwGD2FQJk+8+b@public.gmane.org
Cc: Wu, Aaron; linux-fbdev-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org; Zhang, Sonic
Subject: Re: [uclinux-dist-devel] [PATCH] [#7001] framebuffer: old image of last app would retain for a while after starting new app
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
Before the second application draws its own image, the image of last application has already been displayed on the LCD when the second application opens the FB device(PPI is enabled when it is opened). This is not a correct behavior.
Sonic
^ permalink raw reply
* RE: [PATCH v2 3/3] ARM: Samsung: Rework platform data of s3c-fb driver
From: Jingoo Han @ 2012-03-16 1: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.
[CC'ed Tushar Behera]
Yes, your code is working. However, your code is bug.
'struct s3c_fb_pd_win' is used not for LCD, but for windows of FIMD IP. So, 'struct s3c_fb_pd_win' should not be used to select LCD.
The mach-aquila.c uses two 'struct s3c_fb_pd_win' like you, however 'struct s3c_fb_pd_win' don't make problem with Thomas's
patchset. It is because mach-aquila.c use 'struct s3c_fb_pd_win' for only windows of FIMD IP.
We don't have to responsibility to keep wrong code. If you have kept the rule, Thomas's patch would not make the compatibility
problem with your code. Why we should keep aberration such as your code? If you want to select two LCDs, please find other way.
>
> Darius A.
^ permalink raw reply
* Re: [PATCH] x86: export 'pcibios_enabled'
From: Wang YanQing @ 2012-03-16 0:41 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Randy Dunlap, Stephen Rothwell, linux-next, LKML,
Michal Januszewski, Florian Tobias Schandinat, linux-fbdev, x86,
Andrew Morton
In-Reply-To: <4F5FE9AD.7000204@zytor.com>
On Tue, Mar 13, 2012 at 05:43:25PM -0700, H. Peter Anvin wrote:
> On 03/13/2012 01:30 PM, Randy Dunlap wrote:
> > From: Randy Dunlap <rdunlap@xenotime.net>
> >
> > Export 'pcibios_enabled' so that when uvesafb is built as a
> > loadable module (on X86_32), the build will succeed.
> >
> > ERROR: "pcibios_enabled" [drivers/video/uvesafb.ko] undefined!
> >
> > Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
> > Cc: Michal Januszewski <spock@gentoo.org>
> > Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
> > Cc: linux-fbdev@vger.kernel.org
> > Cc: x86@kernel.org
> > ---
> > Applies to mainline; found in linux-next.
> >
> > arch/x86/pci/pcbios.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > --- linux-next-20120313.orig/arch/x86/pci/pcbios.c
> > +++ linux-next-20120313/arch/x86/pci/pcbios.c
> > @@ -27,6 +27,7 @@
> > #define PCIBIOS_HW_TYPE2_SPEC 0x20
> >
> > int pcibios_enabled;
> > +EXPORT_SYMBOL(pcibios_enabled);
> >
> > /* According to the BIOS specification at:
> > * http://members.datafast.net.au/dft0802/specs/bios21.pdf, we could
>
> I would think this should be EXPORT_SYMBOL_GPL()... this seems like a
> symbol with a very high likelihood to be abused in strange ways.
>
> -hpa
>
Yes, I think EXPORT_SYMBOL_GPL is better. Indeed, there is another issue I
meet about the pcibios NX protection code.
If I set "pcibios_enable = 1" forcely no matter whether set_bios_x had been executed, then
the BIOS code is not NX. The problem is, if set_bios_x had not been executed, of course set_memory_x
for the bios code page has no chance to execute, then why the BIOS code is not NX? Any comment?
Or because the default set for the BIOS range is X, if so we should set_memory_nx if pcibios_enable = 0.
^ permalink raw reply
* Re: [PATCH 2/2] OMAPDSS: DISPC: Handle synclost errors in OMAP3
From: Ville Syrjälä @ 2012-03-15 23:04 UTC (permalink / raw)
To: Chandrabhanu Mahapatra; +Cc: tomi.valkeinen, linux-omap, linux-fbdev
In-Reply-To: <1331812132-9814-1-git-send-email-cmahapatra@ti.com>
On Thu, Mar 15, 2012 at 05:18:52PM +0530, Chandrabhanu Mahapatra wrote:
> 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);
pcd doesn't exist for TV out, which is the reason why you see
'lclk/pclk' ratio used instead in the harmattan kernel.
Another thing which still seems to be wrong in the upstream code is the
use of fclk in the scaling checks. It should be checking lclk instead.
> + 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;
The comment and code here are totally out of sync. IIRC the hblank
length check came directly from the TRM. I have no idea if it's correct
for more recent OMAPs, or if it was just copy pasted from the
old TRM when the TRM got adjusted for more recent chips. That is why I
stuck it into a separate function in harmattan.
--
Ville Syrjälä
syrjala@sci.fi
http://www.sci.fi/~syrjala/
^ permalink raw reply
* Re: [PATCH 1/2] OMAPDSS: DISPC: Enable predecimation
From: Ville Syrjälä @ 2012-03-15 22:28 UTC (permalink / raw)
To: Chandrabhanu Mahapatra; +Cc: tomi.valkeinen, linux-omap, linux-fbdev
In-Reply-To: <1331812108-9776-1-git-send-email-cmahapatra@ti.com>
On Thu, Mar 15, 2012 at 05:18:28PM +0530, Chandrabhanu Mahapatra wrote:
> 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.
Now, where does that number 16 come from? IIRC the hardware can skip
basically any number of pixels/rows. I certainly didn't add any such
limit to the code in the harmattan kernel, and distinctly remember
being able to downscale the N9/N950 UI even down to 1 pixel size :)
> 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.
All the rotation offset calculations still look suspiciously different
to what is in the harmattan kernel. I remember that the original code
was quite broken, and I fixed a lot of things when I was implementing
pre-decimation and some rotation stuff for the N9/N950. Too bad I never
managed to push that stuff upstream...
--
Ville Syrjälä
syrjala@sci.fi
http://www.sci.fi/~syrjala/
^ permalink raw reply
* Re: [Linux-fbdev-devel] [uclinux-dist-devel] [PATCH] [#7001] framebuffer: old image of last app woul
From: Mike Frysinger @ 2012-03-15 19:29 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <201203151508.04564.vapier@gentoo.org>
[-- Attachment #1: Type: Text/Plain, Size: 896 bytes --]
On Thursday 15 March 2012 15:22:34 Geert Uytterhoeven wrote:
> On Thu, Mar 15, 2012 at 20:08, Mike Frysinger wrote:
> > 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.
>
> Indeed. Else can you no longer make a screenshot using "cat /dev/fb0 >
> file".
ironically, that's one method we've documented for Blackfin platforms :)
http://docs.blackfin.uclinux.org/doku.php?id=uclinux-dist:framebuffer
-mike
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [Linux-fbdev-devel] [uclinux-dist-devel] [PATCH] [#7001] framebuffer: old image of last app woul
From: Geert Uytterhoeven @ 2012-03-15 19:22 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <201203151508.04564.vapier@gentoo.org>
[ Corrected obsolete linux-fbdev-devel address ]
On Thu, Mar 15, 2012 at 20:08, Mike Frysinger <vapier@gentoo.org> wrote:
> 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.
Indeed. Else can you no longer make a screenshot using "cat /dev/fb0 > file".
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* 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
* [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
* [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 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
* [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
* [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 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 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 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 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 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
* 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
* [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
* [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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox