linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-13 13:26 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v5 Jaya Kumar
@ 2008-07-13 13:26 ` Jaya Kumar
  2008-07-16  7:00   ` eric miao
  0 siblings, 1 reply; 27+ messages in thread
From: Jaya Kumar @ 2008-07-13 13:26 UTC (permalink / raw)
  To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel

These changes are to make it possible for a secondary driver to share the
pxafb framebuffer. The changes include:
- adding clkdev entry in pxafb_mach_info so that a driver can pass in the
  correct struct device owner for the LCDCLK.
- adding custom_xfer_div entry so that a driver can have custom sized
  transfers. For example, the metronome controller uses 16 bit AMLCD
  transfers but actually has 3 bit pixels in 8 bit containers.
- adding extra_video_mem entry so that a driver can tell pxafb of its
  additional needs.
- adding share_video_mem/unshare_video_mem callbacks to notify the secondary
  driver of the framebuffer address, to allow refcounting, and to cleanup on
  completion.

Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
 arch/arm/mach-pxa/devices.c      |    2 +
 drivers/video/pxafb.c            |   48 +++++++++++++++++++++++++++++++------
 include/asm-arm/arch-pxa/pxafb.h |    9 +++++++
 3 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 84489dc..47af7f6 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -146,6 +146,8 @@ struct platform_device pxa_device_fb = {
 
 void __init set_pxa_fb_info(struct pxafb_mach_info *info)
 {
+	if (!info->clkdev)
+		info->clkdev = &pxa_device_fb.dev;
 	pxa_register_device(&pxa_device_fb, info);
 }
 
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index bb25143..d2bd488 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -57,6 +57,8 @@
  */
 #define DEBUG_VAR 1
 
+static struct platform_driver pxafb_driver;
+
 #include "pxafb.h"
 
 /* Bits which should not be set in machine configuration structures */
@@ -826,10 +828,15 @@ int pxafb_smart_flush(struct fb_info *info)
 static void setup_parallel_timing(struct pxafb_info *fbi,
 				  struct fb_var_screeninfo *var)
 {
+	struct pxafb_mach_info *inf = fbi->dev->platform_data;
 	unsigned int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
+	unsigned int pix_per_line = var->xres;
+
+	if (inf->custom_xfer_div)
+		pix_per_line /= inf->custom_xfer_div;
 
 	fbi->reg_lccr1 =
-		LCCR1_DisWdth(var->xres) +
+		LCCR1_DisWdth(pix_per_line) +
 		LCCR1_HorSnchWdth(var->hsync_len) +
 		LCCR1_BegLnDel(var->left_margin) +
 		LCCR1_EndLnDel(var->right_margin);
@@ -870,6 +877,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
 {
 	u_long flags;
 	size_t nbytes;
+	struct pxafb_mach_info *inf = fbi->dev->platform_data;
 
 #if DEBUG_VAR
 	if (!(fbi->lccr0 & LCCR0_LCDT)) {
@@ -931,6 +939,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
 	fbi->reg_lccr3 |= pxafb_bpp_to_lccr3(var);
 
 	nbytes = var->yres * fbi->fb.fix.line_length;
+	if (inf->custom_xfer_div)
+		nbytes /= inf->custom_xfer_div;
 
 	if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual) {
 		nbytes = nbytes / 2;
@@ -1304,21 +1314,25 @@ static int pxafb_resume(struct platform_device *dev)
  *      cache.  Once this area is remapped, all virtual memory
  *      access to the video memory should occur at the new region.
  */
-static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
+static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi,
+					 struct pxafb_mach_info *inf)
 {
+	int ret;
 	/*
 	 * We reserve one page for the palette, plus the size
 	 * of the framebuffer.
 	 */
 	fbi->video_offset = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
-	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset);
+	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset +
+					inf->extra_video_mem);
 	fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
 					      &fbi->map_dma, GFP_KERNEL);
 
 	if (fbi->map_cpu) {
 		/* prevent initial garbage on screen */
 		memset(fbi->map_cpu, 0, fbi->map_size);
-		fbi->fb.screen_base = fbi->map_cpu + fbi->video_offset;
+		fbi->fb.screen_base = (char __force __iomem *) fbi->map_cpu
+					+ fbi->video_offset;
 		fbi->screen_dma = fbi->map_dma + fbi->video_offset;
 
 		/*
@@ -1340,6 +1354,13 @@ static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
 		fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
 		fbi->n_smart_cmds = 0;
 #endif
+		if (inf->share_video_mem) {
+			ret = inf->share_video_mem(fbi->fb.screen_base,
+				fbi->screen_dma, pxafb_driver.driver.owner,
+				inf->extra_data);
+			if (ret)
+				return ret;
+		}
 	}
 
 	return fbi->map_cpu ? 0 : -ENOMEM;
@@ -1350,6 +1371,7 @@ static void pxafb_decode_mode_info(struct pxafb_info *fbi,
 				   unsigned int num_modes)
 {
 	unsigned int i, smemlen;
+	struct pxafb_mach_info *inf = fbi->dev->platform_data;
 
 	pxafb_setmode(&fbi->fb.var, &modes[0]);
 
@@ -1357,6 +1379,8 @@ static void pxafb_decode_mode_info(struct pxafb_info *fbi,
 		smemlen = modes[i].xres * modes[i].yres * modes[i].bpp / 8;
 		if (smemlen > fbi->fb.fix.smem_len)
 			fbi->fb.fix.smem_len = smemlen;
+		if (inf->custom_xfer_div)
+			fbi->fb.fix.smem_len /= inf->custom_xfer_div;
 	}
 }
 
@@ -1420,7 +1444,7 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
 	memset(fbi, 0, sizeof(struct pxafb_info));
 	fbi->dev = dev;
 
-	fbi->clk = clk_get(dev, "LCDCLK");
+	fbi->clk = clk_get(inf->clkdev, "LCDCLK");
 	if (IS_ERR(fbi->clk)) {
 		kfree(fbi);
 		return NULL;
@@ -1761,10 +1785,12 @@ static int __devinit pxafb_probe(struct platform_device *dev)
 	}
 
 	/* Initialize video memory */
-	ret = pxafb_map_video_memory(fbi);
-	if (ret) {
+	ret = pxafb_map_video_memory(fbi, inf);
+	if (ret == -ENODEV) {
+		dev_err(&dev->dev, "Failed device binding: %d\n", ret);
+		goto failed_free_mem;
+	} else if (ret) {
 		dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret);
-		ret = -ENOMEM;
 		goto failed_free_io;
 	}
 
@@ -1836,6 +1862,8 @@ failed_free_cmap:
 failed_free_irq:
 	free_irq(irq, fbi);
 failed_free_mem:
+	if (inf->unshare_video_mem)
+		inf->unshare_video_mem(inf->extra_data);
 	dma_free_writecombine(&dev->dev, fbi->map_size,
 			fbi->map_cpu, fbi->map_dma);
 failed_free_io:
@@ -1856,6 +1884,7 @@ static int __devexit pxafb_remove(struct platform_device *dev)
 	struct resource *r;
 	int irq;
 	struct fb_info *info;
+	struct pxafb_mach_info *inf;
 
 	if (!fbi)
 		return 0;
@@ -1872,6 +1901,9 @@ static int __devexit pxafb_remove(struct platform_device *dev)
 	irq = platform_get_irq(dev, 0);
 	free_irq(irq, fbi);
 
+	inf = dev->dev.platform_data;
+	if (inf->unshare_video_mem)
+		inf->unshare_video_mem(inf->extra_data);
 	dma_free_writecombine(&dev->dev, fbi->map_size,
 					fbi->map_cpu, fbi->map_dma);
 
diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
index daf018d..8528895 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -139,9 +139,18 @@ struct pxafb_mach_info {
 	 * All other bits in LCCR4 should be left alone.
 	 */
 	u_int		lccr4;
+	unsigned int	custom_xfer_div; /* divides the pixel transfer */
+	/* size of extra mem needed for secondary driver */
+	unsigned int	extra_video_mem;
+	void		*extra_data; /* extra data for secondary */
 	void (*pxafb_backlight_power)(int);
 	void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
 	void (*smart_update)(struct fb_info *);
+	/* share_video_mem allows client drivers to get our framebuffer */
+	int (*share_video_mem)(char __iomem *, dma_addr_t, struct module *,
+				void *);
+	void (*unshare_video_mem)(void *);
+	struct device *clkdev;
 };
 void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
 void set_pxa_fb_parent(struct device *parent_dev);
-- 
1.5.3.6


-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-13 13:26 ` [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface Jaya Kumar
@ 2008-07-16  7:00   ` eric miao
  2008-07-16  8:59     ` Jaya Kumar
  0 siblings, 1 reply; 27+ messages in thread
From: eric miao @ 2008-07-16  7:00 UTC (permalink / raw)
  To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Sun, Jul 13, 2008 at 9:26 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> These changes are to make it possible for a secondary driver to share the
> pxafb framebuffer. The changes include:
> - adding clkdev entry in pxafb_mach_info so that a driver can pass in the
>  correct struct device owner for the LCDCLK.

Is it possible that LCDCLK being requested by device other than
pxa_device_fb?? Could you give an example and we may work out
a better solution.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-16  7:00   ` eric miao
@ 2008-07-16  8:59     ` Jaya Kumar
  2008-07-16  9:08       ` eric miao
  2008-07-16  9:38       ` Russell King - ARM Linux
  0 siblings, 2 replies; 27+ messages in thread
From: Jaya Kumar @ 2008-07-16  8:59 UTC (permalink / raw)
  To: eric miao; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Wed, Jul 16, 2008 at 12:00 AM, eric miao <eric.y.miao@gmail.com> wrote:
> On Sun, Jul 13, 2008 at 9:26 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>> These changes are to make it possible for a secondary driver to share the
>> pxafb framebuffer. The changes include:
>> - adding clkdev entry in pxafb_mach_info so that a driver can pass in the
>>  correct struct device owner for the LCDCLK.
>
> Is it possible that LCDCLK being requested by device other than
> pxa_device_fb?? Could you give an example and we may work out
> a better solution.
>

Hi Eric,

You're right. I think LCDCLK is only ever requested by pxa_device_fb.

I see now that instead of doing:
-       fbi->clk = clk_get(dev, "LCDCLK");
+       fbi->clk = clk_get(inf->clkdev, "LCDCLK");

a better solution would be to directly use pxa_device_fb:
-       fbi->clk = clk_get(dev, "LCDCLK");
+       fbi->clk = clk_get(pxa_device_fb.dev, "LCDCLK");

and then I can avoid doing the clkdev ugliness.

Thanks,
jaya

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-16  8:59     ` Jaya Kumar
@ 2008-07-16  9:08       ` eric miao
  2008-07-16 11:10         ` Jaya Kumar
  2008-07-16  9:38       ` Russell King - ARM Linux
  1 sibling, 1 reply; 27+ messages in thread
From: eric miao @ 2008-07-16  9:08 UTC (permalink / raw)
  To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Wed, Jul 16, 2008 at 4:59 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> On Wed, Jul 16, 2008 at 12:00 AM, eric miao <eric.y.miao@gmail.com> wrote:
>> On Sun, Jul 13, 2008 at 9:26 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>>> These changes are to make it possible for a secondary driver to share the
>>> pxafb framebuffer. The changes include:
>>> - adding clkdev entry in pxafb_mach_info so that a driver can pass in the
>>>  correct struct device owner for the LCDCLK.
>>
>> Is it possible that LCDCLK being requested by device other than
>> pxa_device_fb?? Could you give an example and we may work out
>> a better solution.
>>
>
> Hi Eric,
>
> You're right. I think LCDCLK is only ever requested by pxa_device_fb.
>
> I see now that instead of doing:
> -       fbi->clk = clk_get(dev, "LCDCLK");
> +       fbi->clk = clk_get(inf->clkdev, "LCDCLK");
>
> a better solution would be to directly use pxa_device_fb:
> -       fbi->clk = clk_get(dev, "LCDCLK");
> +       fbi->clk = clk_get(pxa_device_fb.dev, "LCDCLK");
>
> and then I can avoid doing the clkdev ugliness.
>

Mmm... but is there any case that (dev != pxa_device_fb.dev) ??

> Thanks,
> jaya
>



-- 
Cheers
- eric

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-16  8:59     ` Jaya Kumar
  2008-07-16  9:08       ` eric miao
@ 2008-07-16  9:38       ` Russell King - ARM Linux
  2008-07-16 11:18         ` Jaya Kumar
  1 sibling, 1 reply; 27+ messages in thread
From: Russell King - ARM Linux @ 2008-07-16  9:38 UTC (permalink / raw)
  To: Jaya Kumar; +Cc: linux-fbdev-devel, ymiao3, eric miao, linux-arm-kernel

On Wed, Jul 16, 2008 at 01:59:42AM -0700, Jaya Kumar wrote:
> On Wed, Jul 16, 2008 at 12:00 AM, eric miao <eric.y.miao@gmail.com> wrote:
> > On Sun, Jul 13, 2008 at 9:26 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> >> These changes are to make it possible for a secondary driver to share the
> >> pxafb framebuffer. The changes include:
> >> - adding clkdev entry in pxafb_mach_info so that a driver can pass in the
> >>  correct struct device owner for the LCDCLK.
> >
> > Is it possible that LCDCLK being requested by device other than
> > pxa_device_fb?? Could you give an example and we may work out
> > a better solution.
> 
> You're right. I think LCDCLK is only ever requested by pxa_device_fb.
> 
> I see now that instead of doing:
> -       fbi->clk = clk_get(dev, "LCDCLK");
> +       fbi->clk = clk_get(inf->clkdev, "LCDCLK");
> 
> a better solution would be to directly use pxa_device_fb:
> -       fbi->clk = clk_get(dev, "LCDCLK");
> +       fbi->clk = clk_get(pxa_device_fb.dev, "LCDCLK");
> 
> and then I can avoid doing the clkdev ugliness.

PXA devices (intentionally) aren't exported.  Nor are they going to be,
so the above will fail if built as a module.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-16  9:08       ` eric miao
@ 2008-07-16 11:10         ` Jaya Kumar
  0 siblings, 0 replies; 27+ messages in thread
From: Jaya Kumar @ 2008-07-16 11:10 UTC (permalink / raw)
  To: eric miao; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Wed, Jul 16, 2008 at 5:08 PM, eric miao <eric.y.miao@gmail.com> wrote:
> On Wed, Jul 16, 2008 at 4:59 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>> On Wed, Jul 16, 2008 at 12:00 AM, eric miao <eric.y.miao@gmail.com> wrote:
>>> On Sun, Jul 13, 2008 at 9:26 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>>>> These changes are to make it possible for a secondary driver to share the
>>>> pxafb framebuffer. The changes include:
>>>> - adding clkdev entry in pxafb_mach_info so that a driver can pass in the
>>>>  correct struct device owner for the LCDCLK.
>>>
>>> Is it possible that LCDCLK being requested by device other than
>>> pxa_device_fb?? Could you give an example and we may work out
>>> a better solution.
>>>
>>
>> Hi Eric,
>>
>> You're right. I think LCDCLK is only ever requested by pxa_device_fb.
>>
>> I see now that instead of doing:
>> -       fbi->clk = clk_get(dev, "LCDCLK");
>> +       fbi->clk = clk_get(inf->clkdev, "LCDCLK");
>>
>> a better solution would be to directly use pxa_device_fb:
>> -       fbi->clk = clk_get(dev, "LCDCLK");
>> +       fbi->clk = clk_get(pxa_device_fb.dev, "LCDCLK");
>>
>> and then I can avoid doing the clkdev ugliness.
>>
>
> Mmm... but is there any case that (dev != pxa_device_fb.dev) ??
>

Yes. In this case, am200epd because it has a different
platform_device. This is because am200epd doesn't call set_pxa_fb_info
so that it can be unloaded.

Thanks,
jaya

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-16  9:38       ` Russell King - ARM Linux
@ 2008-07-16 11:18         ` Jaya Kumar
  2008-07-20  2:41           ` Jaya Kumar
  0 siblings, 1 reply; 27+ messages in thread
From: Jaya Kumar @ 2008-07-16 11:18 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-fbdev-devel, ymiao3, eric miao, linux-arm-kernel

On Wed, Jul 16, 2008 at 5:38 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Wed, Jul 16, 2008 at 01:59:42AM -0700, Jaya Kumar wrote:
>> On Wed, Jul 16, 2008 at 12:00 AM, eric miao <eric.y.miao@gmail.com> wrote:
>> > On Sun, Jul 13, 2008 at 9:26 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>> >> These changes are to make it possible for a secondary driver to share the
>> >> pxafb framebuffer. The changes include:
>> >> - adding clkdev entry in pxafb_mach_info so that a driver can pass in the
>> >>  correct struct device owner for the LCDCLK.
>> >
>> > Is it possible that LCDCLK being requested by device other than
>> > pxa_device_fb?? Could you give an example and we may work out
>> > a better solution.
>>
>> You're right. I think LCDCLK is only ever requested by pxa_device_fb.
>>
>> I see now that instead of doing:
>> -       fbi->clk = clk_get(dev, "LCDCLK");
>> +       fbi->clk = clk_get(inf->clkdev, "LCDCLK");
>>
>> a better solution would be to directly use pxa_device_fb:
>> -       fbi->clk = clk_get(dev, "LCDCLK");
>> +       fbi->clk = clk_get(pxa_device_fb.dev, "LCDCLK");
>>
>> and then I can avoid doing the clkdev ugliness.
>
> PXA devices (intentionally) aren't exported.  Nor are they going to be,
> so the above will fail if built as a module.
>

Ah... I think this may be the cause of all my troubles. I've been
trying to support am200epd working as a module, and allow it to rmmod
cleanly, hence the inability to use pxa_device_fb through
set_pxa_fb_info. If module support isn't important then I can happily
take out unload support from am200epd and probably can then use
set_pxa_fb_info and also reduce complexity in other parts of the
metronomefb, am200epd, pxafb code.

Thanks,
jaya

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-16 11:18         ` Jaya Kumar
@ 2008-07-20  2:41           ` Jaya Kumar
  2008-07-21  2:10             ` eric miao
  0 siblings, 1 reply; 27+ messages in thread
From: Jaya Kumar @ 2008-07-20  2:41 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-fbdev-devel, ymiao3, eric miao, linux-arm-kernel

On Wed, Jul 16, 2008 at 7:18 AM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> On Wed, Jul 16, 2008 at 5:38 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
>> On Wed, Jul 16, 2008 at 01:59:42AM -0700, Jaya Kumar wrote:
>>> On Wed, Jul 16, 2008 at 12:00 AM, eric miao <eric.y.miao@gmail.com> wrote:
>>> > On Sun, Jul 13, 2008 at 9:26 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>>> >> These changes are to make it possible for a secondary driver to share the
>>> >> pxafb framebuffer. The changes include:
>>> >> - adding clkdev entry in pxafb_mach_info so that a driver can pass in the
>>> >>  correct struct device owner for the LCDCLK.
>>> >
>>> > Is it possible that LCDCLK being requested by device other than
>>> > pxa_device_fb?? Could you give an example and we may work out
>>> > a better solution.
>>>
>>> You're right. I think LCDCLK is only ever requested by pxa_device_fb.
>>>
>>> I see now that instead of doing:
>>> -       fbi->clk = clk_get(dev, "LCDCLK");
>>> +       fbi->clk = clk_get(inf->clkdev, "LCDCLK");
>>>
>>> a better solution would be to directly use pxa_device_fb:
>>> -       fbi->clk = clk_get(dev, "LCDCLK");
>>> +       fbi->clk = clk_get(pxa_device_fb.dev, "LCDCLK");
>>>
>>> and then I can avoid doing the clkdev ugliness.
>>
>> PXA devices (intentionally) aren't exported.  Nor are they going to be,
>> so the above will fail if built as a module.
>>
>
> Ah... I think this may be the cause of all my troubles. I've been
> trying to support am200epd working as a module, and allow it to rmmod
> cleanly, hence the inability to use pxa_device_fb through
> set_pxa_fb_info. If module support isn't important then I can happily
> take out unload support from am200epd and probably can then use
> set_pxa_fb_info and also reduce complexity in other parts of the
> metronomefb, am200epd, pxafb code.
>

Hi Eric,

I've run into some difficulties. set_pxa_fb_info is:

void __init set_pxa_fb_info(struct pxafb_mach_info *info)

and not exported. Therefore am200epd can't be built as a module now
that it depends on set_pxa_fb_info. That is fine, I switched am200epd
to a built-in. But then because set_pxa_fb_info is __init, it
disappears before am200epd is ready to call it. This is because
am200epd needs metronomefb's framebuffer size and info which it only
finds out after full boot into userspace when it gets its firmware
from a udev script. I think this means that I would also need to make
metronomefb a built-in and figure out how to compile in metronome's
firmware. I haven't figured out how to do the latter yet.

I started thinking about maybe creating something different, like
maybe set_mod_pxa_fb_info that would work more dynamically (ie: alloc
a platform_device dynamically, thus making it possible for
device_release to work, rather than using a static struct
pxa_device_fb) and allow for module support without requiring any
exports other than itself. Is this something that's of interest  or
should I focus on the former?

Thanks,
jaya

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-20  6:10 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v6 Jaya Kumar
@ 2008-07-20  6:10 ` Jaya Kumar
  2008-07-21 11:11   ` Russell King - ARM Linux
  0 siblings, 1 reply; 27+ messages in thread
From: Jaya Kumar @ 2008-07-20  6:10 UTC (permalink / raw)
  To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel

These changes are to make it possible for a secondary driver to share the
pxafb framebuffer. The changes include:
- adding custom_xfer_div entry so that a driver can have custom sized
  transfers. For example, the metronome controller uses 16 bit AMLCD
  transfers but actually has 3 bit pixels in 8 bit containers.
- adding extra_video_mem entry so that a driver can tell pxafb of its
  additional needs.
- adding share_video_mem/unshare_video_mem callbacks to notify the secondary
  driver of the framebuffer address, to allow refcounting, and to cleanup on
  completion.

Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
 drivers/video/pxafb.c            |   46 ++++++++++++++++++++++++++++++++-----
 include/asm-arm/arch-pxa/pxafb.h |    8 ++++++
 2 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index bb25143..d343675 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -57,6 +57,8 @@
  */
 #define DEBUG_VAR 1
 
+static struct platform_driver pxafb_driver;
+
 #include "pxafb.h"
 
 /* Bits which should not be set in machine configuration structures */
@@ -826,10 +828,15 @@ int pxafb_smart_flush(struct fb_info *info)
 static void setup_parallel_timing(struct pxafb_info *fbi,
 				  struct fb_var_screeninfo *var)
 {
+	struct pxafb_mach_info *inf = fbi->dev->platform_data;
 	unsigned int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
+	unsigned int pix_per_line = var->xres;
+
+	if (inf->custom_xfer_div)
+		pix_per_line /= inf->custom_xfer_div;
 
 	fbi->reg_lccr1 =
-		LCCR1_DisWdth(var->xres) +
+		LCCR1_DisWdth(pix_per_line) +
 		LCCR1_HorSnchWdth(var->hsync_len) +
 		LCCR1_BegLnDel(var->left_margin) +
 		LCCR1_EndLnDel(var->right_margin);
@@ -870,6 +877,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
 {
 	u_long flags;
 	size_t nbytes;
+	struct pxafb_mach_info *inf = fbi->dev->platform_data;
 
 #if DEBUG_VAR
 	if (!(fbi->lccr0 & LCCR0_LCDT)) {
@@ -931,6 +939,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
 	fbi->reg_lccr3 |= pxafb_bpp_to_lccr3(var);
 
 	nbytes = var->yres * fbi->fb.fix.line_length;
+	if (inf->custom_xfer_div)
+		nbytes /= inf->custom_xfer_div;
 
 	if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual) {
 		nbytes = nbytes / 2;
@@ -1304,21 +1314,25 @@ static int pxafb_resume(struct platform_device *dev)
  *      cache.  Once this area is remapped, all virtual memory
  *      access to the video memory should occur at the new region.
  */
-static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
+static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi,
+					 struct pxafb_mach_info *inf)
 {
+	int ret;
 	/*
 	 * We reserve one page for the palette, plus the size
 	 * of the framebuffer.
 	 */
 	fbi->video_offset = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
-	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset);
+	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset +
+					inf->extra_video_mem);
 	fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
 					      &fbi->map_dma, GFP_KERNEL);
 
 	if (fbi->map_cpu) {
 		/* prevent initial garbage on screen */
 		memset(fbi->map_cpu, 0, fbi->map_size);
-		fbi->fb.screen_base = fbi->map_cpu + fbi->video_offset;
+		fbi->fb.screen_base = (char __force __iomem *) fbi->map_cpu
+					+ fbi->video_offset;
 		fbi->screen_dma = fbi->map_dma + fbi->video_offset;
 
 		/*
@@ -1340,6 +1354,13 @@ static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
 		fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
 		fbi->n_smart_cmds = 0;
 #endif
+		if (inf->share_video_mem) {
+			ret = inf->share_video_mem(fbi->fb.screen_base,
+				fbi->screen_dma, pxafb_driver.driver.owner,
+				inf->extra_data);
+			if (ret)
+				return ret;
+		}
 	}
 
 	return fbi->map_cpu ? 0 : -ENOMEM;
@@ -1350,6 +1371,7 @@ static void pxafb_decode_mode_info(struct pxafb_info *fbi,
 				   unsigned int num_modes)
 {
 	unsigned int i, smemlen;
+	struct pxafb_mach_info *inf = fbi->dev->platform_data;
 
 	pxafb_setmode(&fbi->fb.var, &modes[0]);
 
@@ -1357,6 +1379,8 @@ static void pxafb_decode_mode_info(struct pxafb_info *fbi,
 		smemlen = modes[i].xres * modes[i].yres * modes[i].bpp / 8;
 		if (smemlen > fbi->fb.fix.smem_len)
 			fbi->fb.fix.smem_len = smemlen;
+		if (inf->custom_xfer_div)
+			fbi->fb.fix.smem_len /= inf->custom_xfer_div;
 	}
 }
 
@@ -1761,10 +1785,12 @@ static int __devinit pxafb_probe(struct platform_device *dev)
 	}
 
 	/* Initialize video memory */
-	ret = pxafb_map_video_memory(fbi);
-	if (ret) {
+	ret = pxafb_map_video_memory(fbi, inf);
+	if (ret == -ENODEV) {
+		dev_err(&dev->dev, "Failed device binding: %d\n", ret);
+		goto failed_free_mem;
+	} else if (ret) {
 		dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret);
-		ret = -ENOMEM;
 		goto failed_free_io;
 	}
 
@@ -1836,6 +1862,8 @@ failed_free_cmap:
 failed_free_irq:
 	free_irq(irq, fbi);
 failed_free_mem:
+	if (inf->unshare_video_mem)
+		inf->unshare_video_mem(inf->extra_data);
 	dma_free_writecombine(&dev->dev, fbi->map_size,
 			fbi->map_cpu, fbi->map_dma);
 failed_free_io:
@@ -1856,6 +1884,7 @@ static int __devexit pxafb_remove(struct platform_device *dev)
 	struct resource *r;
 	int irq;
 	struct fb_info *info;
+	struct pxafb_mach_info *inf;
 
 	if (!fbi)
 		return 0;
@@ -1872,6 +1901,9 @@ static int __devexit pxafb_remove(struct platform_device *dev)
 	irq = platform_get_irq(dev, 0);
 	free_irq(irq, fbi);
 
+	inf = dev->dev.platform_data;
+	if (inf->unshare_video_mem)
+		inf->unshare_video_mem(inf->extra_data);
 	dma_free_writecombine(&dev->dev, fbi->map_size,
 					fbi->map_cpu, fbi->map_dma);
 
diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
index daf018d..c73751e 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -139,9 +139,17 @@ struct pxafb_mach_info {
 	 * All other bits in LCCR4 should be left alone.
 	 */
 	u_int		lccr4;
+	unsigned int	custom_xfer_div; /* divides the pixel transfer */
+	/* size of extra mem needed for secondary driver */
+	unsigned int	extra_video_mem;
+	void		*extra_data; /* extra data for secondary */
 	void (*pxafb_backlight_power)(int);
 	void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
 	void (*smart_update)(struct fb_info *);
+	/* share_video_mem allows client drivers to get our framebuffer */
+	int (*share_video_mem)(char __iomem *, dma_addr_t, struct module *,
+				void *);
+	void (*unshare_video_mem)(void *);
 };
 void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
 void set_pxa_fb_parent(struct device *parent_dev);
-- 
1.5.3.6


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-20  2:41           ` Jaya Kumar
@ 2008-07-21  2:10             ` eric miao
  2008-07-21  3:38               ` Jaya Kumar
  0 siblings, 1 reply; 27+ messages in thread
From: eric miao @ 2008-07-21  2:10 UTC (permalink / raw)
  To: Jaya Kumar
  Cc: linux-fbdev-devel, ymiao3, Russell King - ARM Linux,
	linux-arm-kernel

> Hi Eric,
>
> I've run into some difficulties. set_pxa_fb_info is:
>
> void __init set_pxa_fb_info(struct pxafb_mach_info *info)
>
> and not exported. Therefore am200epd can't be built as a module now
> that it depends on set_pxa_fb_info. That is fine, I switched am200epd
> to a built-in. But then because set_pxa_fb_info is __init, it
> disappears before am200epd is ready to call it. This is because
> am200epd needs metronomefb's framebuffer size and info which it only
> finds out after full boot into userspace when it gets its firmware
> from a udev script. I think this means that I would also need to make
> metronomefb a built-in and figure out how to compile in metronome's
> firmware. I haven't figured out how to do the latter yet.
>

I see no reason why set_pxa_fb_info() cannot be exported, though
its primary use is in the board setup code.

> I started thinking about maybe creating something different, like
> maybe set_mod_pxa_fb_info that would work more dynamically (ie: alloc
> a platform_device dynamically, thus making it possible for
> device_release to work, rather than using a static struct
> pxa_device_fb) and allow for module support without requiring any
> exports other than itself. Is this something that's of interest  or
> should I focus on the former?

That sounds a bit trickier maybe we should avoid.

>
> Thanks,
> jaya
>



-- 
Cheers
- eric

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-21  2:10             ` eric miao
@ 2008-07-21  3:38               ` Jaya Kumar
  0 siblings, 0 replies; 27+ messages in thread
From: Jaya Kumar @ 2008-07-21  3:38 UTC (permalink / raw)
  To: eric miao
  Cc: linux-fbdev-devel, ymiao3, Russell King - ARM Linux,
	linux-arm-kernel

On Sun, Jul 20, 2008 at 7:10 PM, eric miao <eric.y.miao@gmail.com> wrote:
>
> I see no reason why set_pxa_fb_info() cannot be exported, though
> its primary use is in the board setup code.

Yup, I see now. In the v6 patchset, I managed to use set_pxa_fb_info
by converting am200epd to a builtin and also changing the way we do
setup_fb for metronomefb. So I'm able to use set_pxa_fb_info without
changes now. :-)

>
>> I started thinking about maybe creating something different, like
>> maybe set_mod_pxa_fb_info that would work more dynamically (ie: alloc
>> a platform_device dynamically, thus making it possible for
>> device_release to work, rather than using a static struct
>> pxa_device_fb) and allow for module support without requiring any
>> exports other than itself. Is this something that's of interest  or
>> should I focus on the former?
>
> That sounds a bit trickier maybe we should avoid.
>

Agreed.

Thanks,
jaya

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-20  6:10 ` [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface Jaya Kumar
@ 2008-07-21 11:11   ` Russell King - ARM Linux
  2008-07-21 12:32     ` Jaya Kumar
  0 siblings, 1 reply; 27+ messages in thread
From: Russell King - ARM Linux @ 2008-07-21 11:11 UTC (permalink / raw)
  To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Sun, Jul 20, 2008 at 02:10:29AM -0400, Jaya Kumar wrote:
>  	if (fbi->map_cpu) {
>  		/* prevent initial garbage on screen */
>  		memset(fbi->map_cpu, 0, fbi->map_size);
> -		fbi->fb.screen_base = fbi->map_cpu + fbi->video_offset;
> +		fbi->fb.screen_base = (char __force __iomem *) fbi->map_cpu
> +					+ fbi->video_offset;

I'm not sure this has any benefits - the use of __force in drivers is
definitely frowned upon.

It's well known that FB doesn't sit well with all the MMIO sparse checking
so it's probably a good idea not to try and make it work.

> @@ -1357,6 +1379,8 @@ static void pxafb_decode_mode_info(struct pxafb_info *fbi,
>  		smemlen = modes[i].xres * modes[i].yres * modes[i].bpp / 8;
>  		if (smemlen > fbi->fb.fix.smem_len)
>  			fbi->fb.fix.smem_len = smemlen;
> +		if (inf->custom_xfer_div)
> +			fbi->fb.fix.smem_len /= inf->custom_xfer_div;

I don't understand this.  If you have a 640x480 display with 8 bits of
memory per pixel, then it's 307200 bytes no matter whether you're only
using the lower 4 bits and the upper 4 are unused.

If, on the other hand, the lower 4 bits contain one pixel and the upper
4 bits contain the other pixel, then you have a 4 bit per pixel
framebuffer, so 'bpp' should be 4.  In which case the original calculation
gives the correct answer.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-21 11:11   ` Russell King - ARM Linux
@ 2008-07-21 12:32     ` Jaya Kumar
  2008-07-26  3:30       ` Jaya Kumar
  0 siblings, 1 reply; 27+ messages in thread
From: Jaya Kumar @ 2008-07-21 12:32 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Mon, Jul 21, 2008 at 7:11 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Sun, Jul 20, 2008 at 02:10:29AM -0400, Jaya Kumar wrote:
>>       if (fbi->map_cpu) {
>>               /* prevent initial garbage on screen */
>>               memset(fbi->map_cpu, 0, fbi->map_size);
>> -             fbi->fb.screen_base = fbi->map_cpu + fbi->video_offset;
>> +             fbi->fb.screen_base = (char __force __iomem *) fbi->map_cpu
>> +                                     + fbi->video_offset;
>
> I'm not sure this has any benefits - the use of __force in drivers is
> definitely frowned upon.
>
> It's well known that FB doesn't sit well with all the MMIO sparse checking
> so it's probably a good idea not to try and make it work.

Ok, I'll take it out. My intentions were to avoid causing any new
sparse warnings.

>
>> @@ -1357,6 +1379,8 @@ static void pxafb_decode_mode_info(struct pxafb_info *fbi,
>>               smemlen = modes[i].xres * modes[i].yres * modes[i].bpp / 8;
>>               if (smemlen > fbi->fb.fix.smem_len)
>>                       fbi->fb.fix.smem_len = smemlen;
>> +             if (inf->custom_xfer_div)
>> +                     fbi->fb.fix.smem_len /= inf->custom_xfer_div;
>
> I don't understand this.  If you have a 640x480 display with 8 bits of
> memory per pixel, then it's 307200 bytes no matter whether you're only
> using the lower 4 bits and the upper 4 are unused.
>
> If, on the other hand, the lower 4 bits contain one pixel and the upper
> 4 bits contain the other pixel, then you have a 4 bit per pixel
> framebuffer, so 'bpp' should be 4.  In which case the original calculation
> gives the correct answer.
>

The complexity I faced is that the transfers used by Metronome on the
AMLCD bus have to be 16-bits wide although it is actually treating the
pixels as 8-bits per pixel and then only using the lower 4-bits within
that for actual content. So what I did in the code is set bits per
pixel, bpp to 16 so that pxafb sets the LCCR3_16BPP flag (so that it
meets Metronome's AMLCD transfer requirements) and then use the
custom_xfer_div to divide the transfer sizes and buffer allocations to
the correct size.

If I set bpp to 8, the allocations and transfer sizes are correct but
then that causes pxafb to set LCCR3_8BPP and that causes Metronome to
fail to display anything.

Instead of doing custom_xfer_div, I had thought about setting
pxafb_mach_info.lccr3 = LCCR3_16BPP to try to force the setting of
LCCR3_16BPP but then I saw:

include/asm/arch-pxa/pxafb.h
         * The following should not be defined in LCCR3
         *      LCCR3_HSP, LCCR3_VSP, LCCR0_Pcd(x), LCCR3_Bpp
         */
        u_int           lccr3;

so I decided to create custom_xfer_div instead. How about if I try a
different way like creating a separate flag that can be used to
predicate the lccr3 setting. Maybe something like:

static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
...
        case 8:
               switch (inf->custom_amlcd_bpp) {
                case 16: ret = LCCR3_16BPP; break;
                default: ret = LCCR3_8BPP; break;
        case 16: ret = LCCR3_16BPP; break;

Thanks,
jaya

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-21 12:32     ` Jaya Kumar
@ 2008-07-26  3:30       ` Jaya Kumar
  2008-07-30  2:41         ` Eric Miao
  0 siblings, 1 reply; 27+ messages in thread
From: Jaya Kumar @ 2008-07-26  3:30 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Mon, Jul 21, 2008 at 8:32 AM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> On Mon, Jul 21, 2008 at 7:11 AM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
>> On Sun, Jul 20, 2008 at 02:10:29AM -0400, Jaya Kumar wrote:
>>
>>> @@ -1357,6 +1379,8 @@ static void pxafb_decode_mode_info(struct pxafb_info *fbi,
>>>               smemlen = modes[i].xres * modes[i].yres * modes[i].bpp / 8;
>>>               if (smemlen > fbi->fb.fix.smem_len)
>>>                       fbi->fb.fix.smem_len = smemlen;
>>> +             if (inf->custom_xfer_div)
>>> +                     fbi->fb.fix.smem_len /= inf->custom_xfer_div;
>>
>> I don't understand this.  If you have a 640x480 display with 8 bits of
>> memory per pixel, then it's 307200 bytes no matter whether you're only
>> using the lower 4 bits and the upper 4 are unused.
>>
>> If, on the other hand, the lower 4 bits contain one pixel and the upper
>> 4 bits contain the other pixel, then you have a 4 bit per pixel
>> framebuffer, so 'bpp' should be 4.  In which case the original calculation
>> gives the correct answer.
>>
>
> The complexity I faced is that the transfers used by Metronome on the
> AMLCD bus have to be 16-bits wide although it is actually treating the
> pixels as 8-bits per pixel and then only using the lower 4-bits within
> that for actual content. So what I did in the code is set bits per
> pixel, bpp to 16 so that pxafb sets the LCCR3_16BPP flag (so that it
> meets Metronome's AMLCD transfer requirements) and then use the
> custom_xfer_div to divide the transfer sizes and buffer allocations to
> the correct size.
>
> If I set bpp to 8, the allocations and transfer sizes are correct but
> then that causes pxafb to set LCCR3_8BPP and that causes Metronome to
> fail to display anything.
>
> Instead of doing custom_xfer_div, I had thought about setting
> pxafb_mach_info.lccr3 = LCCR3_16BPP to try to force the setting of
> LCCR3_16BPP but then I saw:
>
> include/asm/arch-pxa/pxafb.h
>         * The following should not be defined in LCCR3
>         *      LCCR3_HSP, LCCR3_VSP, LCCR0_Pcd(x), LCCR3_Bpp
>         */
>        u_int           lccr3;
>
> so I decided to create custom_xfer_div instead. How about if I try a
> different way like creating a separate flag that can be used to
> predicate the lccr3 setting. Maybe something like:
>
> static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
> ...
>        case 8:
>               switch (inf->custom_amlcd_bpp) {
>                case 16: ret = LCCR3_16BPP; break;
>                default: ret = LCCR3_8BPP; break;
>        case 16: ret = LCCR3_16BPP; break;
>
> Thanks,
> jaya
>

I took a look at doing the above, ie: adjusting bpp instead of
custom_xfer_size. I've realized that I would still need to adjust lccr
in at least one other place:

        fbi->reg_lccr1 =
                LCCR1_DisWdth(var->xres) +

I'll try to improve my explanation. :-)

The reason for this is that metronome requires a different bus width
(16 bit) for AMLCD transfers than it requires for its expected bits
per pixel ( 8 bits). To get LCDC to use 16 bits on the AMLCD bus, we
need to set 16bpp in LCCR3. So we then need to divide down the x
resolution in LCCR1. Eg: 800 pixels at 8bpp is the framebuffer. We
need 16-bit transfers so we set the desired pixels per line in LCCR to
= 800 pixels / ( 16 custom bus bits / 8 bits per pixel ) = 400 pixels
per line. So the code would be like:

pix_per_line = var->xres / ( inf->custom_lccr_bpp / var->bits_per_pixel )

I hope I was able to explain my reasoning for this above.

Thanks,
jaya

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v7
@ 2008-07-26  4:32 Jaya Kumar
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface Jaya Kumar
                   ` (4 more replies)
  0 siblings, 5 replies; 27+ messages in thread
From: Jaya Kumar @ 2008-07-26  4:32 UTC (permalink / raw)
  To: ymiao3; +Cc: linux-fbdev-devel, linux-arm-kernel


Hi Eric, arm and fbdev friends,

This is version 7 of this RFC and contains the following updates:
- replace custom transfer sizes with customized bpp custom_lccr_bpp.
  Improved comments for what the changes do.
- add gpio_request for BTRST pin in gumstix_bluetooth_init

Thanks to Eric and Russell for feedback.
I will take out DEBUG before final.

This RFC consists of patches intended to improve the condition of the
am200epd devkit support. The am200epd devkit contains a gumstix (pxa255) and
a carrier board (am200epd or Lyre), and a metronome display controller.
Previously, there was a drivers/video/am200epd driver that manipulated pxa
LCDC registers and GPSR/GPLR registers directly. That was clearly wrong and
broken so I have removed it and written a new mach-pxa am200epd support
driver.This driver interfaces with pxafb through a set of callbacks to
share/unshare pxafb's framebuffer and achieves the same functionality without
manipulating any pxa registers directly. The patches are split as follows:

pxafb: add shared framebuffer interface
gumstix: conversion to MFP support and add bluetooth support
am200epd: convert to shared fb and use gpio api
metronomefb: convert printk to dev_dbg/err messages
metronomefb: changes to use separate framebuffer

I would be grateful for any feedback and advice.

Thanks,
jaya


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-26  4:32 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v7 Jaya Kumar
@ 2008-07-26  4:32 ` Jaya Kumar
  2008-07-29 15:28   ` Krzysztof Helt
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 27+ messages in thread
From: Jaya Kumar @ 2008-07-26  4:32 UTC (permalink / raw)
  To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel

These changes are to make it possible for a secondary driver to share the
pxafb framebuffer. The changes include:
- adding custom_lccr_bpp entry so that a driver can set a specific
  transfer width on the AMLCD bus while using a separate bits per pixel for
  its actual framebuffer.
- adding extra_video_mem entry so that a driver can tell pxafb of its
  additional needs.
- adding share_video_mem/unshare_video_mem callbacks to notify the secondary
  driver of the framebuffer address, to allow refcounting, and to cleanup on
  completion.

Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
 drivers/video/pxafb.c            |   65 +++++++++++++++++++++++++++++++++-----
 include/asm-arm/arch-pxa/pxafb.h |    8 +++++
 2 files changed, 65 insertions(+), 8 deletions(-)

diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index bb25143..54e0ad1 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -57,6 +57,8 @@
  */
 #define DEBUG_VAR 1
 
+static struct platform_driver pxafb_driver;
+
 #include "pxafb.h"
 
 /* Bits which should not be set in machine configuration structures */
@@ -218,9 +220,25 @@ pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  *  pxafb_bpp_to_lccr3():
  *    Convert a bits per pixel value to the correct bit pattern for LCCR3
  */
-static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
+static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var,
+				struct pxafb_mach_info *inf)
 {
 	int ret = 0;
+
+	/* this is to support devices that have customized
+	 * bpp settings for LCCR that are independent from
+	 * the actual bpp used in the framebuffer.
+	 */
+	if (inf->custom_lccr_bpp) {
+		switch (inf->custom_lccr_bpp) {
+		case 1:  ret = LCCR3_1BPP; break;
+		case 2:  ret = LCCR3_2BPP; break;
+		case 4:  ret = LCCR3_4BPP; break;
+		case 8:  ret = LCCR3_8BPP; break;
+		case 16: ret = LCCR3_16BPP; break;
+		}
+		return ret;
+	}
 	switch (var->bits_per_pixel) {
 	case 1:  ret = LCCR3_1BPP; break;
 	case 2:  ret = LCCR3_2BPP; break;
@@ -826,10 +844,22 @@ int pxafb_smart_flush(struct fb_info *info)
 static void setup_parallel_timing(struct pxafb_info *fbi,
 				  struct fb_var_screeninfo *var)
 {
+	struct pxafb_mach_info *inf = fbi->dev->platform_data;
 	unsigned int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
+	unsigned int pix_per_line = var->xres;
+
+	/*
+	 * We can have a device that needs a different width for its AMLCD
+	 * transfers than its framebuffer's bits per pixel. So we need to
+	 * divide down the x resolution. Eg: 800 pixels at 8bpp is the fb.
+	 * The device uses 16-bit xfers so the desired result is:
+	 * 800 pixels / ( 16 bit xfer / 8bpp ) = 400 pixels per line
+	 */
+	if (inf->custom_lccr_bpp)
+		pix_per_line /= (inf->custom_lccr_bpp / var->bits_per_pixel);
 
 	fbi->reg_lccr1 =
-		LCCR1_DisWdth(var->xres) +
+		LCCR1_DisWdth(pix_per_line) +
 		LCCR1_HorSnchWdth(var->hsync_len) +
 		LCCR1_BegLnDel(var->left_margin) +
 		LCCR1_EndLnDel(var->right_margin);
@@ -870,6 +900,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
 {
 	u_long flags;
 	size_t nbytes;
+	struct pxafb_mach_info *inf = fbi->dev->platform_data;
 
 #if DEBUG_VAR
 	if (!(fbi->lccr0 & LCCR0_LCDT)) {
@@ -928,7 +959,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
 		(LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
 		 LCCR0_QDM | LCCR0_BM  | LCCR0_OUM);
 
-	fbi->reg_lccr3 |= pxafb_bpp_to_lccr3(var);
+	fbi->reg_lccr3 |= pxafb_bpp_to_lccr3(var, inf);
 
 	nbytes = var->yres * fbi->fb.fix.line_length;
 
@@ -1304,14 +1335,17 @@ static int pxafb_resume(struct platform_device *dev)
  *      cache.  Once this area is remapped, all virtual memory
  *      access to the video memory should occur at the new region.
  */
-static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
+static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi,
+						struct pxafb_mach_info *inf)
 {
+	int ret;
 	/*
 	 * We reserve one page for the palette, plus the size
 	 * of the framebuffer.
 	 */
 	fbi->video_offset = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
-	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset);
+	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset +
+					inf->extra_video_mem);
 	fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
 					      &fbi->map_dma, GFP_KERNEL);
 
@@ -1340,6 +1374,13 @@ static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
 		fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
 		fbi->n_smart_cmds = 0;
 #endif
+		if (inf->share_video_mem) {
+			ret = inf->share_video_mem(fbi->fb.screen_base,
+				fbi->screen_dma, pxafb_driver.driver.owner,
+				inf->extra_data);
+			if (ret)
+				return ret;
+		}
 	}
 
 	return fbi->map_cpu ? 0 : -ENOMEM;
@@ -1761,10 +1802,12 @@ static int __devinit pxafb_probe(struct platform_device *dev)
 	}
 
 	/* Initialize video memory */
-	ret = pxafb_map_video_memory(fbi);
-	if (ret) {
+	ret = pxafb_map_video_memory(fbi, inf);
+	if (ret == -ENODEV) {
+		dev_err(&dev->dev, "Failed device binding: %d\n", ret);
+		goto failed_free_mem;
+	} else if (ret) {
 		dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret);
-		ret = -ENOMEM;
 		goto failed_free_io;
 	}
 
@@ -1836,6 +1879,8 @@ failed_free_cmap:
 failed_free_irq:
 	free_irq(irq, fbi);
 failed_free_mem:
+	if (inf->unshare_video_mem)
+		inf->unshare_video_mem(inf->extra_data);
 	dma_free_writecombine(&dev->dev, fbi->map_size,
 			fbi->map_cpu, fbi->map_dma);
 failed_free_io:
@@ -1856,6 +1901,7 @@ static int __devexit pxafb_remove(struct platform_device *dev)
 	struct resource *r;
 	int irq;
 	struct fb_info *info;
+	struct pxafb_mach_info *inf;
 
 	if (!fbi)
 		return 0;
@@ -1872,6 +1918,9 @@ static int __devexit pxafb_remove(struct platform_device *dev)
 	irq = platform_get_irq(dev, 0);
 	free_irq(irq, fbi);
 
+	inf = dev->dev.platform_data;
+	if (inf->unshare_video_mem)
+		inf->unshare_video_mem(inf->extra_data);
 	dma_free_writecombine(&dev->dev, fbi->map_size,
 					fbi->map_cpu, fbi->map_dma);
 
diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
index daf018d..c8c3e84 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -139,9 +139,17 @@ struct pxafb_mach_info {
 	 * All other bits in LCCR4 should be left alone.
 	 */
 	u_int		lccr4;
+	unsigned int	custom_lccr_bpp; /* custom bpp setting */
+	/* size of extra mem needed for secondary driver */
+	unsigned int	extra_video_mem;
+	void		*extra_data; /* extra data for secondary */
 	void (*pxafb_backlight_power)(int);
 	void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
 	void (*smart_update)(struct fb_info *);
+	/* share_video_mem allows client drivers to get our framebuffer */
+	int (*share_video_mem)(char __iomem *, dma_addr_t, struct module *,
+				void *);
+	void (*unshare_video_mem)(void *);
 };
 void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
 void set_pxa_fb_parent(struct device *parent_dev);
-- 
1.5.3.6


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support
  2008-07-26  4:32 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v7 Jaya Kumar
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface Jaya Kumar
@ 2008-07-26  4:32 ` Jaya Kumar
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 3/5] am200epd: convert to shared fb and use gpio api Jaya Kumar
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 27+ messages in thread
From: Jaya Kumar @ 2008-07-26  4:32 UTC (permalink / raw)
  To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel

This patch converts gumstix over to the MFP configuration system and adds
bluetooth support.

Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
 arch/arm/mach-pxa/gumstix.c |  100 +++++++++++++++++++++++++++++++++++-------
 1 files changed, 83 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index bdf2397..49b78e7 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -20,8 +20,12 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/clk.h>
 
 #include <asm/setup.h>
 #include <asm/memory.h>
@@ -40,7 +44,7 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
+#include <asm/arch/mfp-pxa25x.h>
 
 #include "generic.h"
 
@@ -85,21 +89,8 @@ static struct platform_device *devices[] __initdata = {
 };
 
 #ifdef CONFIG_MMC_PXA
-static struct pxamci_platform_data gumstix_mci_platform_data;
-
-static int gumstix_mci_init(struct device *dev, irq_handler_t detect_int,
-				void *data)
-{
-	pxa_gpio_mode(GPIO6_MMCCLK_MD);
-	pxa_gpio_mode(GPIO53_MMCCLK_MD);
-	pxa_gpio_mode(GPIO8_MMCCS0_MD);
-
-	return 0;
-}
-
 static struct pxamci_platform_data gumstix_mci_platform_data = {
 	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
-	.init		= gumstix_mci_init,
 };
 
 static void __init gumstix_mmc_init(void)
@@ -109,11 +100,11 @@ static void __init gumstix_mmc_init(void)
 #else
 static void __init gumstix_mmc_init(void)
 {
-	printk(KERN_INFO "Gumstix mmc disabled\n");
+	pr_debug("Gumstix mmc disabled\n");
 }
 #endif
 
-#ifdef CONFIG_USB_GADGET_PXA2XX
+#ifdef CONFIG_USB_GADGET_PXA25X
 static struct pxa2xx_udc_mach_info gumstix_udc_info __initdata = {
 	.gpio_vbus		= GPIO_GUMSTIX_USB_GPIOn,
 	.gpio_pullup		= GPIO_GUMSTIX_USB_GPIOx,
@@ -126,12 +117,87 @@ static void __init gumstix_udc_init(void)
 #else
 static void gumstix_udc_init(void)
 {
-	printk(KERN_INFO "Gumstix udc is disabled\n");
+	pr_debug("Gumstix udc is disabled\n");
 }
 #endif
 
+#ifdef CONFIG_BT
+/* Normally, the bootloader would have enabled this 32kHz clock but many
+** boards still have u-boot 1.1.4 so we check if it has been turned on and
+** if not, we turn it on with a warning message. */
+static void gumstix_setup_bt_clock(void)
+{
+	int timeout = 500;
+
+	if (!(OSCC & OSCC_OOK))
+		pr_warning("32kHz clock was not on. Bootloader may need to "
+				"be updated\n");
+	else
+		return;
+
+	OSCC |= OSCC_OON;
+	do {
+		if (OSCC & OSCC_OOK)
+			break;
+		udelay(1);
+	} while (--timeout);
+	if (!timeout)
+		pr_err("Failed to start 32kHz clock\n");
+}
+
+static void __init gumstix_bluetooth_init(void)
+{
+	int err;
+
+	gumstix_setup_bt_clock();
+
+	err = gpio_request(GPIO_GUMSTIX_BTRESET, "BTRST");
+	if (err) {
+		pr_err("gumstix: failed request gpio for bluetooth reset\n");
+		return;
+	}
+
+	err = gpio_direction_output(GPIO_GUMSTIX_BTRESET, 1);
+	if (err) {
+		pr_err("gumstix: can't reset bluetooth\n");
+		return;
+	}
+	gpio_set_value(GPIO_GUMSTIX_BTRESET, 0);
+	udelay(100);
+	gpio_set_value(GPIO_GUMSTIX_BTRESET, 1);
+}
+#else
+static void gumstix_bluetooth_init(void)
+{
+	pr_debug("Gumstix Bluetooth is disabled\n");
+}
+#endif
+
+static unsigned long gumstix_pin_config[] __initdata = {
+	GPIO12_32KHz,
+	/* BTUART */
+	GPIO42_HWUART_RXD,
+	GPIO43_HWUART_TXD,
+	GPIO44_HWUART_CTS,
+	GPIO45_HWUART_RTS,
+	/* MMC */
+	GPIO6_MMC_CLK,
+	GPIO53_MMC_CLK,
+	GPIO8_MMC_CS0,
+	/* these are used by AM200EPD */
+	GPIO51_GPIO,
+	GPIO49_GPIO,
+	GPIO48_GPIO,
+	GPIO32_GPIO,
+	GPIO17_GPIO,
+	GPIO16_GPIO,
+};
+
 static void __init gumstix_init(void)
 {
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(gumstix_pin_config));
+
+	gumstix_bluetooth_init();
 	gumstix_udc_init();
 	gumstix_mmc_init();
 	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
-- 
1.5.3.6


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [RFC 2.6.26-rc9 3/5] am200epd: convert to shared fb and use gpio api
  2008-07-26  4:32 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v7 Jaya Kumar
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface Jaya Kumar
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
@ 2008-07-26  4:32 ` Jaya Kumar
  2008-07-30  2:45   ` Eric Miao
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages Jaya Kumar
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 5/5] metronomefb: changes to use separate framebuffer Jaya Kumar
  4 siblings, 1 reply; 27+ messages in thread
From: Jaya Kumar @ 2008-07-26  4:32 UTC (permalink / raw)
  To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel

The original am200epd driver was designed with bad assumptions. It
manipulated GPSR/GPLR registers directly. It relied on direct access to the
pxa LCDC registers which have since conflicted with commit
ce4fb7b892a6d6c6a0f87366b26fd834d2923dd7 . This patch moves it into mach-pxa
and overhauls it to use pxafb's fb. It now uses the generic GPIO api.

Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
 arch/arm/mach-pxa/Kconfig    |    3 +
 arch/arm/mach-pxa/Makefile   |    1 +
 arch/arm/mach-pxa/am200epd.c |  326 ++++++++++++++++++++++++++++++++++++++++++
 drivers/video/Kconfig        |   13 --
 drivers/video/Makefile       |    1 -
 drivers/video/am200epd.c     |  295 --------------------------------------
 6 files changed, 330 insertions(+), 309 deletions(-)
 create mode 100644 arch/arm/mach-pxa/am200epd.c
 delete mode 100644 drivers/video/am200epd.c

diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 3e28521..945014e 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -243,6 +243,9 @@ config PCM990_DISPLAY_NONE
 
 endchoice
 
+config MACH_AM200EPD
+	depends on MACH_GUMSTIX_F
+	bool "Enable AM200EPD board support"
 
 config PXA_EZX
 	bool "Motorola EZX Platform"
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 5220a5c..618fe96 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_CPU_PXA320)	+= pxa320.o
 
 # Specific board support
 obj-$(CONFIG_ARCH_GUMSTIX)	+= gumstix.o
+obj-$(CONFIG_MACH_AM200EPD)	+= am200epd.o
 obj-$(CONFIG_ARCH_LUBBOCK)	+= lubbock.o
 obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
 obj-$(CONFIG_MACH_MAINSTONE)	+= mainstone.o
diff --git a/arch/arm/mach-pxa/am200epd.c b/arch/arm/mach-pxa/am200epd.c
new file mode 100644
index 0000000..7808f78
--- /dev/null
+++ b/arch/arm/mach-pxa/am200epd.c
@@ -0,0 +1,326 @@
+/*
+ * am200epd.c -- Platform device for AM200 EPD kit
+ *
+ * Copyright (C) 2008, Jaya Kumar
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ *
+ * This work was made possible by help and equipment support from E-Ink
+ * Corporation. http://support.eink.com/community
+ *
+ * This driver is written to be used with the Metronome display controller.
+ * on the AM200 EPD prototype kit/development kit with an E-Ink 800x600
+ * Vizplex EPD on a Gumstix board using the Lyre interface board.
+ *
+ */
+
+#define DEBUG 1
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+
+#include <asm/arch/pxafb.h>
+
+#include <video/metronomefb.h>
+
+#include "generic.h"
+#include "devices.h"
+
+static unsigned int panel_type = 6;
+static struct platform_device *am200_device;
+static struct metronome_board am200_board;
+
+static struct pxafb_mode_info am200_fb_mode_9inch7 = {
+	.pixclock	= 40000,
+	.xres		= 1200,
+	.yres		= 842,
+	.bpp		= 8,
+	.hsync_len	= 2,
+	.left_margin	= 2,
+	.right_margin	= 2,
+	.vsync_len	= 1,
+	.upper_margin	= 2,
+	.lower_margin	= 25,
+	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mode_info am200_fb_mode_8inch = {
+	.pixclock	= 40000,
+	.xres		= 1088,
+	.yres		= 791,
+	.bpp		= 8,
+	.hsync_len	= 28,
+	.left_margin	= 8,
+	.right_margin	= 30,
+	.vsync_len	= 8,
+	.upper_margin	= 10,
+	.lower_margin	= 8,
+	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mode_info am200_fb_mode_6inch = {
+	.pixclock	= 40189,
+	.xres		= 832,
+	.yres		= 622,
+	.bpp		= 8,
+	.hsync_len	= 28,
+	.left_margin	= 34,
+	.right_margin	= 34,
+	.vsync_len	= 25,
+	.upper_margin	= 0,
+	.lower_margin	= 2,
+	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mach_info am200_fb_info = {
+	.modes		= &am200_fb_mode_6inch,
+	.num_modes	= 1,
+	.lcd_conn	= LCD_TYPE_COLOR_TFT | LCD_PCLK_EDGE_FALL |
+			  LCD_AC_BIAS_FREQ(24),
+	.custom_lccr_bpp = 16,
+};
+
+/* register offsets for gpio control */
+#define LED_GPIO_PIN 51
+#define STDBY_GPIO_PIN 48
+#define RST_GPIO_PIN 49
+#define RDY_GPIO_PIN 32
+#define ERR_GPIO_PIN 17
+#define PCBPWR_GPIO_PIN 16
+static int gpios[] = { LED_GPIO_PIN , STDBY_GPIO_PIN , RST_GPIO_PIN,
+			RDY_GPIO_PIN, ERR_GPIO_PIN, PCBPWR_GPIO_PIN };
+static char *gpio_names[] = { "LED" , "STDBY" , "RST", "RDY", "ERR", "PCBPWR" };
+
+static int am200_init_gpio_regs(struct metronomefb_par *par)
+{
+	int i;
+	int err;
+
+	for (i = 0; i < ARRAY_SIZE(gpios); i++) {
+		err = gpio_request(gpios[i], gpio_names[i]);
+		if (err) {
+			dev_err(&am200_device->dev, "failed requesting "
+				"gpio %s, err=%d\n", gpio_names[i], err);
+			goto err_req_gpio;
+		}
+	}
+
+	gpio_direction_output(LED_GPIO_PIN, 0);
+	gpio_direction_output(STDBY_GPIO_PIN, 0);
+	gpio_direction_output(RST_GPIO_PIN, 0);
+
+	gpio_direction_input(RDY_GPIO_PIN);
+	gpio_direction_input(ERR_GPIO_PIN);
+
+	gpio_direction_output(PCBPWR_GPIO_PIN, 0);
+
+	return 0;
+
+err_req_gpio:
+	while (i > 0)
+		gpio_free(gpios[i--]);
+
+	return err;
+}
+
+static void am200_cleanup(struct metronomefb_par *par)
+{
+	int i;
+
+	free_irq(IRQ_GPIO(RDY_GPIO_PIN), par->info);
+
+	for (i = 0; i < ARRAY_SIZE(gpios); i++)
+		gpio_free(gpios[i]);
+}
+
+static char __iomem *am200_metromem;
+static dma_addr_t am200_metromem_dma;
+static int am200_preshare_video_mem(char __iomem *video_mem, dma_addr_t dma,
+					struct module *fbmaster, void *data)
+{
+
+	/* try to refcount the caller since we are the consumer after this */
+	if (!try_module_get(fbmaster))
+		return -ENODEV;
+
+	dev_dbg(&am200_device->dev, "mod_get %p\n", fbmaster);
+	am200_board.fbmaster = fbmaster;
+	am200_metromem = video_mem;
+	am200_metromem_dma = dma;
+
+	return 0;
+}
+
+static void am200_unshare_video_mem(void *data)
+{
+	struct metronomefb_par *par = data;
+
+	dev_dbg(&am200_device->dev, "ENTER %s\n", __func__);
+	par->metromem = NULL;
+	par->metromem_dma = 0;
+	dev_dbg(&am200_device->dev, "mod_put %p\n", am200_board.fbmaster);
+	module_put(am200_board.fbmaster);
+}
+
+/* this gets called as part of our init. these steps must be done now so
+ * that we can use set_pxa_fb_info */
+static void __init am200_presetup_fb(void)
+{
+	int fw;
+	int wfm_size;
+	int padding_size;
+
+	switch (panel_type) {
+	case 6:
+		am200_fb_info.modes = &am200_fb_mode_6inch;
+		break;
+	case 8:
+		am200_fb_info.modes = &am200_fb_mode_8inch;
+		break;
+	case 97:
+		am200_fb_info.modes = &am200_fb_mode_9inch7;
+		break;
+	default:
+		dev_err(&am200_device->dev, "invalid panel_type selection,"
+						" setting to 6\n");
+		am200_fb_info.modes = &am200_fb_mode_6inch;
+		break;
+	}
+
+	fw = am200_fb_info.modes->xres;
+	wfm_size = ((16*1024 + 2 + fw - 1) / fw) * fw;
+	padding_size = 4 * fw;
+	am200_fb_info.extra_video_mem = fw + wfm_size + padding_size;
+	am200_fb_info.share_video_mem = am200_preshare_video_mem;
+	am200_fb_info.unshare_video_mem = NULL;
+
+	set_pxa_fb_info(&am200_fb_info);
+
+}
+
+/* this gets called by metronomefb as part of its init, in our case, we
+ * have already completed initial framebuffer init in presetup_fb so we
+ * can just assign the parameters for completeness */
+static int am200_setup_fb(struct metronomefb_par *par)
+{
+
+	am200_fb_info.extra_video_mem = par->extra_size;
+	am200_fb_info.extra_data = (void *) par;
+	am200_fb_info.unshare_video_mem = am200_unshare_video_mem;
+
+	par->metromem = (unsigned char __force *) am200_metromem;
+	par->metromem_dma = am200_metromem_dma;
+
+	return 0;
+}
+
+static int am200_get_panel_type(void)
+{
+	return panel_type;
+}
+
+static irqreturn_t am200_handle_irq(int irq, void *dev_id)
+{
+	struct fb_info *info = dev_id;
+	struct metronomefb_par *par = info->par;
+
+	wake_up_interruptible(&par->waitq);
+	return IRQ_HANDLED;
+}
+
+static int am200_setup_irq(struct fb_info *info)
+{
+	int ret;
+
+	ret = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am200_handle_irq,
+				IRQF_DISABLED|IRQF_TRIGGER_FALLING,
+				"AM200", info);
+	if (ret)
+		dev_err(&am200_device->dev, "request_irq failed: %d\n", ret);
+
+	return ret;
+}
+
+static void am200_set_rst(struct metronomefb_par *par, int state)
+{
+	gpio_set_value(RST_GPIO_PIN, state);
+}
+
+static void am200_set_stdby(struct metronomefb_par *par, int state)
+{
+	gpio_set_value(STDBY_GPIO_PIN, state);
+}
+
+static int am200_wait_event(struct metronomefb_par *par)
+{
+	return wait_event_timeout(par->waitq, gpio_get_value(RDY_GPIO_PIN), HZ);
+}
+
+static int am200_wait_event_intr(struct metronomefb_par *par)
+{
+	int ret;
+
+	ret = wait_event_interruptible_timeout(par->waitq,
+					gpio_get_value(RDY_GPIO_PIN), HZ);
+	return ret;
+}
+
+static struct metronome_board am200_board = {
+	.owner			= THIS_MODULE,
+	.setup_irq		= am200_setup_irq,
+	.setup_io		= am200_init_gpio_regs,
+	.setup_fb		= am200_setup_fb,
+	.set_rst		= am200_set_rst,
+	.set_stdby		= am200_set_stdby,
+	.met_wait_event		= am200_wait_event,
+	.met_wait_event_intr	= am200_wait_event_intr,
+	.get_panel_type		= am200_get_panel_type,
+	.cleanup		= am200_cleanup,
+};
+
+static int __init am200_init(void)
+{
+	int ret;
+
+	/* request our platform independent driver */
+	request_module("metronomefb");
+
+	am200_device = platform_device_alloc("metronomefb", -1);
+	if (!am200_device)
+		return -ENOMEM;
+
+	platform_device_add_data(am200_device, &am200_board,
+					sizeof(am200_board));
+
+	/* this _add binds metronomefb to am200. metronomefb refcounts am200 */
+	ret = platform_device_add(am200_device);
+
+	if (ret)
+		platform_device_put(am200_device);
+
+	am200_presetup_fb();
+
+	return ret;
+}
+
+module_param(panel_type, uint, 0);
+MODULE_PARM_DESC(panel_type, "Select the panel type: 6, 8, 97");
+
+module_init(am200_init);
+
+MODULE_DESCRIPTION("board driver for am200 metronome epd kit");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index e0c5f96..752907d 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1938,19 +1938,6 @@ config FB_XILINX
 	  framebuffer. ML300 carries a 640*480 LCD display on the board,
 	  ML403 uses a standard DB15 VGA connector.
 
-config FB_AM200EPD
-       tristate "AM-200 E-Ink EPD devkit support"
-       depends on FB && ARCH_PXA && MMU
-       select FB_SYS_FILLRECT
-       select FB_SYS_COPYAREA
-       select FB_SYS_IMAGEBLIT
-       select FB_SYS_FOPS
-       select FB_DEFERRED_IO
-       select FB_METRONOME
-       help
-         This enables support for the Metronome display controller used on
-         the E-Ink AM-200 EPD devkit.
-
 config FB_VIRTUAL
 	tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
 	depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 04bca35..80d5842 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -29,7 +29,6 @@ obj-$(CONFIG_FB_DEFERRED_IO)   += fb_defio.o
 
 # Hardware specific drivers go first
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
-obj-$(CONFIG_FB_AM200EPD)         += am200epd.o
 obj-$(CONFIG_FB_ARC)              += arcfb.o
 obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
 obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
diff --git a/drivers/video/am200epd.c b/drivers/video/am200epd.c
deleted file mode 100644
index 51e26c1..0000000
--- a/drivers/video/am200epd.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * linux/drivers/video/am200epd.c -- Platform device for AM200 EPD kit
- *
- * Copyright (C) 2008, Jaya Kumar
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- *
- * This work was made possible by help and equipment support from E-Ink
- * Corporation. http://support.eink.com/community
- *
- * This driver is written to be used with the Metronome display controller.
- * on the AM200 EPD prototype kit/development kit with an E-Ink 800x600
- * Vizplex EPD on a Gumstix board using the Lyre interface board.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/uaccess.h>
-#include <linux/irq.h>
-
-#include <video/metronomefb.h>
-
-#include <asm/arch/pxa-regs.h>
-
-/* register offsets for gpio control */
-#define LED_GPIO_PIN 51
-#define STDBY_GPIO_PIN 48
-#define RST_GPIO_PIN 49
-#define RDY_GPIO_PIN 32
-#define ERR_GPIO_PIN 17
-#define PCBPWR_GPIO_PIN 16
-
-#define AF_SEL_GPIO_N 0x3
-#define GAFR0_U_OFFSET(pin) ((pin - 16) * 2)
-#define GAFR1_L_OFFSET(pin) ((pin - 32) * 2)
-#define GAFR1_U_OFFSET(pin) ((pin - 48) * 2)
-#define GPDR1_OFFSET(pin) (pin - 32)
-#define GPCR1_OFFSET(pin) (pin - 32)
-#define GPSR1_OFFSET(pin) (pin - 32)
-#define GPCR0_OFFSET(pin) (pin)
-#define GPSR0_OFFSET(pin) (pin)
-
-static void am200_set_gpio_output(int pin, int val)
-{
-	u8 index;
-
-	index = pin >> 4;
-
-	switch (index) {
-	case 1:
-		if (val)
-			GPSR0 |= (1 << GPSR0_OFFSET(pin));
-		else
-			GPCR0 |= (1 << GPCR0_OFFSET(pin));
-		break;
-	case 2:
-		break;
-	case 3:
-		if (val)
-			GPSR1 |= (1 << GPSR1_OFFSET(pin));
-		else
-			GPCR1 |= (1 << GPCR1_OFFSET(pin));
-		break;
-	default:
-		printk(KERN_ERR "unimplemented\n");
-	}
-}
-
-static void __devinit am200_init_gpio_pin(int pin, int dir)
-{
-	u8 index;
-	/* dir 0 is output, 1 is input
-	- do 2 things here:
-	- set gpio alternate function to standard gpio
-	- set gpio direction to input or output  */
-
-	index = pin >> 4;
-	switch (index) {
-	case 1:
-		GAFR0_U &= ~(AF_SEL_GPIO_N << GAFR0_U_OFFSET(pin));
-
-		if (dir)
-			GPDR0 &= ~(1 << pin);
-		else
-			GPDR0 |= (1 << pin);
-		break;
-	case 2:
-		GAFR1_L &= ~(AF_SEL_GPIO_N << GAFR1_L_OFFSET(pin));
-
-		if (dir)
-			GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
-		else
-			GPDR1 |= (1 << GPDR1_OFFSET(pin));
-		break;
-	case 3:
-		GAFR1_U &= ~(AF_SEL_GPIO_N << GAFR1_U_OFFSET(pin));
-
-		if (dir)
-			GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
-		else
-			GPDR1 |= (1 << GPDR1_OFFSET(pin));
-		break;
-	default:
-		printk(KERN_ERR "unimplemented\n");
-	}
-}
-
-static void am200_init_gpio_regs(struct metronomefb_par *par)
-{
-	am200_init_gpio_pin(LED_GPIO_PIN, 0);
-	am200_set_gpio_output(LED_GPIO_PIN, 0);
-
-	am200_init_gpio_pin(STDBY_GPIO_PIN, 0);
-	am200_set_gpio_output(STDBY_GPIO_PIN, 0);
-
-	am200_init_gpio_pin(RST_GPIO_PIN, 0);
-	am200_set_gpio_output(RST_GPIO_PIN, 0);
-
-	am200_init_gpio_pin(RDY_GPIO_PIN, 1);
-
-	am200_init_gpio_pin(ERR_GPIO_PIN, 1);
-
-	am200_init_gpio_pin(PCBPWR_GPIO_PIN, 0);
-	am200_set_gpio_output(PCBPWR_GPIO_PIN, 0);
-}
-
-static void am200_disable_lcd_controller(struct metronomefb_par *par)
-{
-	LCSR = 0xffffffff;	/* Clear LCD Status Register */
-	LCCR0 |= LCCR0_DIS;	/* Disable LCD Controller */
-
-	/* we reset and just wait for things to settle */
-	msleep(200);
-}
-
-static void am200_enable_lcd_controller(struct metronomefb_par *par)
-{
-	LCSR = 0xffffffff;
-	FDADR0 = par->metromem_desc_dma;
-	LCCR0 |= LCCR0_ENB;
-}
-
-static void am200_init_lcdc_regs(struct metronomefb_par *par)
-{
-	/* here we do:
-	- disable the lcd controller
-	- setup lcd control registers
-	- setup dma descriptor
-	- reenable lcd controller
-	*/
-
-	/* disable the lcd controller */
-	am200_disable_lcd_controller(par);
-
-	/* setup lcd control registers */
-	LCCR0 = LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_PAS
-		| LCCR0_QDM | LCCR0_BM | LCCR0_OUM;
-
-	LCCR1 = (par->info->var.xres/2 - 1) /* pixels per line */
-		| (27 << 10) /* hsync pulse width - 1 */
-		| (33 << 16) /* eol pixel count */
-		| (33 << 24); /* bol pixel count */
-
-	LCCR2 = (par->info->var.yres - 1) /* lines per panel */
-		| (24 << 10) /* vsync pulse width - 1 */
-		| (2 << 16) /* eof pixel count */
-		| (0 << 24); /* bof pixel count */
-
-	LCCR3 = 2 /* pixel clock divisor */
-		| (24 << 8) /* AC Bias pin freq */
-		| LCCR3_16BPP /* BPP */
-		| LCCR3_PCP;  /* PCP falling edge */
-
-}
-
-static void am200_post_dma_setup(struct metronomefb_par *par)
-{
-	par->metromem_desc->mFDADR0 = par->metromem_desc_dma;
-	par->metromem_desc->mFSADR0 = par->metromem_dma;
-	par->metromem_desc->mFIDR0 = 0;
-	par->metromem_desc->mLDCMD0 = par->info->var.xres
-					* par->info->var.yres;
-	am200_enable_lcd_controller(par);
-}
-
-static void am200_free_irq(struct fb_info *info)
-{
-	free_irq(IRQ_GPIO(RDY_GPIO_PIN), info);
-}
-
-static irqreturn_t am200_handle_irq(int irq, void *dev_id)
-{
-	struct fb_info *info = dev_id;
-	struct metronomefb_par *par = info->par;
-
-	wake_up_interruptible(&par->waitq);
-	return IRQ_HANDLED;
-}
-
-static int am200_setup_irq(struct fb_info *info)
-{
-	int retval;
-
-	retval = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am200_handle_irq,
-				IRQF_DISABLED, "AM200", info);
-	if (retval) {
-		printk(KERN_ERR "am200epd: request_irq failed: %d\n", retval);
-		return retval;
-	}
-
-	return set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQT_FALLING);
-}
-
-static void am200_set_rst(struct metronomefb_par *par, int state)
-{
-	am200_set_gpio_output(RST_GPIO_PIN, state);
-}
-
-static void am200_set_stdby(struct metronomefb_par *par, int state)
-{
-	am200_set_gpio_output(STDBY_GPIO_PIN, state);
-}
-
-static int am200_wait_event(struct metronomefb_par *par)
-{
-	return wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ);
-}
-
-static int am200_wait_event_intr(struct metronomefb_par *par)
-{
-	return wait_event_interruptible_timeout(par->waitq, (GPLR1 & 0x01), HZ);
-}
-
-static struct metronome_board am200_board = {
-	.owner			= THIS_MODULE,
-	.free_irq		= am200_free_irq,
-	.setup_irq		= am200_setup_irq,
-	.init_gpio_regs		= am200_init_gpio_regs,
-	.init_lcdc_regs		= am200_init_lcdc_regs,
-	.post_dma_setup		= am200_post_dma_setup,
-	.set_rst		= am200_set_rst,
-	.set_stdby		= am200_set_stdby,
-	.met_wait_event		= am200_wait_event,
-	.met_wait_event_intr	= am200_wait_event_intr,
-};
-
-static struct platform_device *am200_device;
-
-static int __init am200_init(void)
-{
-	int ret;
-
-	/* request our platform independent driver */
-	request_module("metronomefb");
-
-	am200_device = platform_device_alloc("metronomefb", -1);
-	if (!am200_device)
-		return -ENOMEM;
-
-	platform_device_add_data(am200_device, &am200_board,
-					sizeof(am200_board));
-
-	/* this _add binds metronomefb to am200. metronomefb refcounts am200 */
-	ret = platform_device_add(am200_device);
-
-	if (ret)
-		platform_device_put(am200_device);
-
-	return ret;
-}
-
-static void __exit am200_exit(void)
-{
-	platform_device_unregister(am200_device);
-}
-
-module_init(am200_init);
-module_exit(am200_exit);
-
-MODULE_DESCRIPTION("board driver for am200 metronome epd kit");
-MODULE_AUTHOR("Jaya Kumar");
-MODULE_LICENSE("GPL");
-- 
1.5.3.6


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages
  2008-07-26  4:32 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v7 Jaya Kumar
                   ` (2 preceding siblings ...)
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 3/5] am200epd: convert to shared fb and use gpio api Jaya Kumar
@ 2008-07-26  4:32 ` Jaya Kumar
  2008-07-30  2:50   ` Eric Miao
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 5/5] metronomefb: changes to use separate framebuffer Jaya Kumar
  4 siblings, 1 reply; 27+ messages in thread
From: Jaya Kumar @ 2008-07-26  4:32 UTC (permalink / raw)
  To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel

This patch converts the printk messages in metronomefb to dev_dbg/err type
messages.

Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
 drivers/video/metronomefb.c |   49 +++++++++++++++++++-----------------------
 1 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
index cc4c038..8ccd113 100644
--- a/drivers/video/metronomefb.c
+++ b/drivers/video/metronomefb.c
@@ -18,6 +18,8 @@
  * is provided as am200epd.c
  *
  */
+#define DEBUG 1
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -40,15 +42,6 @@
 
 #include <asm/unaligned.h>
 
-
-#define DEBUG 1
-#ifdef DEBUG
-#define DPRINTK(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
-#else
-#define DPRINTK(f, a...)
-#endif
-
-
 /* Display specific information */
 #define DPY_W 832
 #define DPY_H 622
@@ -135,8 +128,8 @@ static u16 calc_img_cksum(u16 *start, int length)
 
 /* here we decode the incoming waveform file and populate metromem */
 #define EXP_WFORM_SIZE 47001
-static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
-				u8 *frame_count)
+static int __devinit load_waveform(u8 *mem, size_t size, int m, int t,
+				struct metronomefb_par *par)
 {
 	int tta;
 	int wmta;
@@ -148,9 +141,11 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
 	int wfm_idx, owfm_idx;
 	int mem_idx = 0;
 	struct waveform_hdr *wfm_hdr;
+	u8 *metromem = par->metromem_wfm;
+	struct device *dev = par->info->dev;
 
 	if (size != EXP_WFORM_SIZE) {
-		printk(KERN_ERR "Error: unexpected size %d != %d\n", size,
+		dev_err(dev, "Error: unexpected size %d != %d\n", size,
 					EXP_WFORM_SIZE);
 		return -EINVAL;
 	}
@@ -158,16 +153,16 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
 	wfm_hdr = (struct waveform_hdr *) mem;
 
 	if (wfm_hdr->fvsn != 1) {
-		printk(KERN_ERR "Error: bad fvsn %x\n", wfm_hdr->fvsn);
+		dev_err(dev, "Error: bad fvsn %x\n", wfm_hdr->fvsn);
 		return -EINVAL;
 	}
 	if (wfm_hdr->luts != 0) {
-		printk(KERN_ERR "Error: bad luts %x\n", wfm_hdr->luts);
+		dev_err(dev, "Error: bad luts %x\n", wfm_hdr->luts);
 		return -EINVAL;
 	}
 	cksum = calc_cksum(32, 47, mem);
 	if (cksum != wfm_hdr->wfm_cs) {
-		printk(KERN_ERR "Error: bad cksum %x != %x\n", cksum,
+		dev_err(dev, "Error: bad cksum %x != %x\n", cksum,
 					wfm_hdr->wfm_cs);
 		return -EINVAL;
 	}
@@ -175,7 +170,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
 	wfm_hdr->trc += 1;
 	for (i = 0; i < 5; i++) {
 		if (*(wfm_hdr->stuff2a + i) != 0) {
-			printk(KERN_ERR "Error: unexpected value in padding\n");
+			dev_err(dev, "Error: unexpected value in padding\n");
 			return -EINVAL;
 		}
 	}
@@ -200,7 +195,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
 		return -EINVAL;
 	cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
 	if (cksum != mem[cksum_idx]) {
-		printk(KERN_ERR "Error: bad temperature range table cksum"
+		dev_err(dev, "Error: bad temperature range table cksum"
 				" %x != %x\n", cksum, mem[cksum_idx]);
 		return -EINVAL;
 	}
@@ -212,7 +207,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
 		return -EINVAL;
 	cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
 	if (cksum != mem[cksum_idx]) {
-		printk(KERN_ERR "Error: bad mode table address cksum"
+		dev_err(dev, "Error: bad mode table address cksum"
 				" %x != %x\n", cksum, mem[cksum_idx]);
 		return -EINVAL;
 	}
@@ -224,7 +219,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
 		return -EINVAL;
 	cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
 	if (cksum != mem[cksum_idx]) {
-		printk(KERN_ERR "Error: bad temperature table address cksum"
+		dev_err(dev, "Error: bad temperature table address cksum"
 			" %x != %x\n", cksum, mem[cksum_idx]);
 		return -EINVAL;
 	}
@@ -259,11 +254,11 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
 		return -EINVAL;
 	cksum = calc_cksum(owfm_idx, cksum_idx, mem);
 	if (cksum != mem[cksum_idx]) {
-		printk(KERN_ERR "Error: bad waveform data cksum"
+		dev_err(dev, "Error: bad waveform data cksum"
 				" %x != %x\n", cksum, mem[cksum_idx]);
 		return -EINVAL;
 	}
-	*frame_count = (mem_idx/64);
+	par->frame_count = (mem_idx/64);
 
 	return 0;
 }
@@ -662,15 +657,15 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 		b) process waveform and decode into metromem */
 	retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
 	if (retval < 0) {
-		printk(KERN_ERR "metronomefb: couldn't get waveform\n");
+		dev_err(&dev->dev, "Failed to get waveform\n");
 		goto err_dma_free;
 	}
 
-	retval = load_waveform((u8 *) fw_entry->data, fw_entry->size,
-				par->metromem_wfm, 3, 31, &par->frame_count);
+	retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31,
+				par);
 	release_firmware(fw_entry);
 	if (retval < 0) {
-		printk(KERN_ERR "metronomefb: couldn't process waveform\n");
+		dev_err(&dev->dev, "Failed processing waveform\n");
 		goto err_dma_free;
 	}
 
@@ -688,7 +683,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 
 	retval = fb_alloc_cmap(&info->cmap, 8, 0);
 	if (retval < 0) {
-		printk(KERN_ERR "Failed to allocate colormap\n");
+		dev_err(&dev->dev, "Failed to allocate colormap\n");
 		goto err_fb_rel;
 	}
 
@@ -704,7 +699,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 
 	platform_set_drvdata(dev, info);
 
-	printk(KERN_INFO
+	dev_dbg(&dev->dev,
 		"fb%d: Metronome frame buffer device, using %dK of video"
 		" memory\n", info->node, videomemorysize >> 10);
 
-- 
1.5.3.6


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [RFC 2.6.26-rc9 5/5] metronomefb: changes to use separate framebuffer
  2008-07-26  4:32 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v7 Jaya Kumar
                   ` (3 preceding siblings ...)
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages Jaya Kumar
@ 2008-07-26  4:32 ` Jaya Kumar
  4 siblings, 0 replies; 27+ messages in thread
From: Jaya Kumar @ 2008-07-26  4:32 UTC (permalink / raw)
  To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel

These changes are used in order to support the use of a separate
framebuffer provided by the platform device driver. Other changes
are cleanup to error handling and order of release.

Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
 drivers/video/Kconfig       |   18 +++-
 drivers/video/metronomefb.c |  225 +++++++++++++++++++++++++------------------
 include/video/metronomefb.h |   22 ++---
 3 files changed, 151 insertions(+), 114 deletions(-)

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 752907d..dda770c 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -172,11 +172,6 @@ config FB_DEFERRED_IO
 	bool
 	depends on FB
 
-config FB_METRONOME
-	tristate
-	depends on FB
-	depends on FB_DEFERRED_IO
-
 config FB_HECUBA
 	tristate
 	depends on FB
@@ -1975,6 +1970,19 @@ config XEN_FBDEV_FRONTEND
 	  frame buffer driver.  It communicates with a back-end
 	  in another domain.
 
+config FB_METRONOME
+	tristate "E-Ink Metronome/8track controller support"
+	depends on FB
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_DEFERRED_IO
+	help
+	  This driver implements support for the E-Ink Metronome
+	  controller. The pre-release name for this device was 8track
+	  and could also have been called by some vendors as PVI-nnnn.
+
 source "drivers/video/omap/Kconfig"
 
 source "drivers/video/backlight/Kconfig"
diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
index 8ccd113..471b0c1 100644
--- a/drivers/video/metronomefb.c
+++ b/drivers/video/metronomefb.c
@@ -46,16 +46,59 @@
 #define DPY_W 832
 #define DPY_H 622
 
+static int user_wfm_size;
+
 /* frame differs from image. frame includes non-visible pixels */
 struct epd_frame {
 	int fw; /* frame width */
 	int fh; /* frame height */
+	u16 config[4];
+	int wfm_size;
 };
 
 static struct epd_frame epd_frame_table[] = {
 	{
-	.fw = 832,
-	.fh = 622
+		.fw = 832,
+		.fh = 622,
+		.config = {
+			15 /* sdlew */
+			| 2 << 8 /* sdosz */
+			| 0 << 11 /* sdor */
+			| 0 << 12 /* sdces */
+			| 0 << 15, /* sdcer */
+			42 /* gdspl */
+			| 1 << 8 /* gdr1 */
+			| 1 << 9 /* sdshr */
+			| 0 << 15, /* gdspp */
+			18 /* gdspw */
+			| 0 << 15, /* dispc */
+			599 /* vdlc */
+			| 0 << 11 /* dsi */
+			| 0 << 12, /* dsic */
+		},
+		.wfm_size = 47001,
+	},
+	{
+		.fw = 1088,
+		.fh = 791,
+		.config = {
+			0x0104,
+			0x031f,
+			0x0088,
+			0x02ff,
+		},
+		.wfm_size = 46770,
+	},
+	{
+		.fw = 1200,
+		.fh = 842,
+		.config = {
+			0x0101,
+			0x030e,
+			0x0012,
+			0x0280,
+		},
+		.wfm_size = 46770,
 	},
 };
 
@@ -127,7 +170,6 @@ static u16 calc_img_cksum(u16 *start, int length)
 }
 
 /* here we decode the incoming waveform file and populate metromem */
-#define EXP_WFORM_SIZE 47001
 static int __devinit load_waveform(u8 *mem, size_t size, int m, int t,
 				struct metronomefb_par *par)
 {
@@ -144,9 +186,12 @@ static int __devinit load_waveform(u8 *mem, size_t size, int m, int t,
 	u8 *metromem = par->metromem_wfm;
 	struct device *dev = par->info->dev;
 
-	if (size != EXP_WFORM_SIZE) {
+	if (user_wfm_size)
+		epd_frame_table[par->dt].wfm_size = user_wfm_size;
+
+	if (size != epd_frame_table[par->dt].wfm_size) {
 		dev_err(dev, "Error: unexpected size %d != %d\n", size,
-					EXP_WFORM_SIZE);
+					epd_frame_table[par->dt].wfm_size);
 		return -EINVAL;
 	}
 
@@ -330,44 +375,17 @@ static int __devinit metronome_powerup_cmd(struct metronomefb_par *par)
 
 static int __devinit metronome_config_cmd(struct metronomefb_par *par)
 {
-	int i;
-	u16 cs;
-
 	/* setup config command
 	we can't immediately set the opcode since the controller
-	will try parse the command before we've set it all up
-	so we just set cs here and set the opcode at the end */
-
-	cs = 0xCC10;
-
-	/* set the 12 args ( 8 bytes ) for config. see spec for meanings */
-	i = 0;
-	par->metromem_cmd->args[i] = 	15 /* sdlew */
-					| 2 << 8 /* sdosz */
-					| 0 << 11 /* sdor */
-					| 0 << 12 /* sdces */
-					| 0 << 15; /* sdcer */
-	cs += par->metromem_cmd->args[i++];
-
-	par->metromem_cmd->args[i] = 	42 /* gdspl */
-					| 1 << 8 /* gdr1 */
-					| 1 << 9 /* sdshr */
-					| 0 << 15; /* gdspp */
-	cs += par->metromem_cmd->args[i++];
-
-	par->metromem_cmd->args[i] = 	18 /* gdspw */
-					| 0 << 15; /* dispc */
-	cs += par->metromem_cmd->args[i++];
-
-	par->metromem_cmd->args[i] = 	599 /* vdlc */
-					| 0 << 11 /* dsi */
-					| 0 << 12; /* dsic */
-	cs += par->metromem_cmd->args[i++];
+	will try parse the command before we've set it all up */
 
+	memcpy(par->metromem_cmd->args, epd_frame_table[par->dt].config,
+		sizeof(epd_frame_table[par->dt].config));
 	/* the rest are 0 */
-	memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
+	memset((u8 *) (par->metromem_cmd->args + 4), 0, (32-4)*2);
 
-	par->metromem_cmd->csum = cs;
+	par->metromem_cmd->csum = 0xCC10;
+	par->metromem_cmd->csum += calc_img_cksum(par->metromem_cmd->args, 4);
 	par->metromem_cmd->opcode = 0xCC10; /* config cmd */
 
 	return par->board->met_wait_event(par);
@@ -403,12 +421,9 @@ static int __devinit metronome_init_regs(struct metronomefb_par *par)
 {
 	int res;
 
-	par->board->init_gpio_regs(par);
-
-	par->board->init_lcdc_regs(par);
-
-	/* now that lcd is setup, setup dma descriptor */
-	par->board->post_dma_setup(par);
+	res = par->board->setup_io(par);
+	if (res)
+		return res;
 
 	res = metronome_powerup_cmd(par);
 	if (res)
@@ -425,16 +440,16 @@ static int __devinit metronome_init_regs(struct metronomefb_par *par)
 
 static void metronomefb_dpy_update(struct metronomefb_par *par)
 {
+	int fbsize;
 	u16 cksum;
 	unsigned char *buf = (unsigned char __force *)par->info->screen_base;
 
+	fbsize = par->info->fix.smem_len;
 	/* copy from vm to metromem */
-	memcpy(par->metromem_img, buf, DPY_W*DPY_H);
+	memcpy(par->metromem_img, buf, fbsize);
 
-	cksum = calc_img_cksum((u16 *) par->metromem_img,
-				(epd_frame_table[0].fw * DPY_H)/2);
-	*((u16 *)(par->metromem_img) +
-			(epd_frame_table[0].fw * DPY_H)/2) = cksum;
+	cksum = calc_img_cksum((u16 *) par->metromem_img, fbsize/2);
+	*((u16 *)(par->metromem_img) + fbsize/2) = cksum;
 	metronome_display_cmd(par);
 }
 
@@ -569,8 +584,11 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 	unsigned char *videomemory;
 	struct metronomefb_par *par;
 	const struct firmware *fw_entry;
-	int cmd_size, wfm_size, img_size, padding_size, totalsize;
+	int cmd_size, wfm_size, padding_size;
 	int i;
+	int panel_type;
+	int fw, fh;
+	int epd_dt_index;
 
 	/* pick up board specific routines */
 	board = dev->dev.platform_data;
@@ -581,39 +599,65 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 	if (!try_module_get(board->owner))
 		return -ENODEV;
 
+	info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
+	if (!info)
+		goto err;
+
 	/* we have two blocks of memory.
 	info->screen_base which is vm, and is the fb used by apps.
 	par->metromem which is physically contiguous memory and
 	contains the display controller commands, waveform,
 	processed image data and padding. this is the data pulled
-	by the device's LCD controller and pushed to Metronome */
-
-	videomemorysize = (DPY_W*DPY_H);
+	by the device's LCD controller and pushed to Metronome.
+	the metromem memory is allocated by the board driver and
+	is provided to us */
+
+	panel_type = board->get_panel_type();
+	switch (panel_type) {
+	case 6:
+		epd_dt_index = 0;
+		break;
+	case 8:
+		epd_dt_index = 1;
+		break;
+	case 97:
+		epd_dt_index = 2;
+		break;
+	default:
+		dev_err(&dev->dev, "Unexpected panel type. Defaulting to 6\n");
+		epd_dt_index = 0;
+		break;
+	}
+	fw = epd_frame_table[epd_dt_index].fw;
+	fh = epd_frame_table[epd_dt_index].fh;
+	videomemorysize = fw * fh;
 	videomemory = vmalloc(videomemorysize);
 	if (!videomemory)
-		return -ENOMEM;
+		goto err_fb_rel;
 
 	memset(videomemory, 0, videomemorysize);
 
-	info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
-	if (!info)
-		goto err_vfree;
-
 	info->screen_base = (char __force __iomem *)videomemory;
 	info->fbops = &metronomefb_ops;
 
+	metronomefb_fix.line_length = fw;
+	metronomefb_var.xres = fw;
+	metronomefb_var.yres = fh;
+	metronomefb_var.xres_virtual = fw;
+	metronomefb_var.yres_virtual = fh;
 	info->var = metronomefb_var;
 	info->fix = metronomefb_fix;
 	info->fix.smem_len = videomemorysize;
 	par = info->par;
 	par->info = info;
 	par->board = board;
+	par->dt = epd_dt_index;
 	init_waitqueue_head(&par->waitq);
 
 	/* this table caches per page csum values. */
 	par->csum_table = vmalloc(videomemorysize/PAGE_SIZE);
 	if (!par->csum_table)
-		goto err_csum_table;
+		goto err_vfree;
 
 	/* the metromem buffer is divided as follows:
 	command | CRC | padding
@@ -623,34 +667,26 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 	eg: IW=832 IH=622 WS=128
 	*/
 
-	cmd_size = 1 * epd_frame_table[0].fw;
-	wfm_size = ((16*1024 + 2 + epd_frame_table[0].fw - 1)
-			/ epd_frame_table[0].fw) * epd_frame_table[0].fw;
-	img_size = epd_frame_table[0].fh * epd_frame_table[0].fw;
-	padding_size = 4 * epd_frame_table[0].fw;
-	totalsize = cmd_size + wfm_size + img_size + padding_size;
-	par->metromemsize = PAGE_ALIGN(totalsize + 256);
-	DPRINTK("desired memory size = %d\n", par->metromemsize);
-	dev->dev.coherent_dma_mask = 0xffffffffull;
-	par->metromem = dma_alloc_writecombine(&dev->dev, par->metromemsize,
-						&par->metromem_dma, GFP_KERNEL);
+	cmd_size = 1 * fw;
+	wfm_size = ((16*1024 + 2 + fw - 1) / fw) * fw;
+	padding_size = 4 * fw;
+	par->extra_size = cmd_size + wfm_size + padding_size;
+	retval = par->board->setup_fb(par);
+	if (retval) {
+		dev_err(&dev->dev, "Failed to setup fb\n");
+		goto err_csum_table;
+	}
+	/* after this point we should have a framebuffer */
 	if (!par->metromem) {
-		printk(KERN_ERR
-			"metronomefb: unable to allocate dma buffer\n");
-		goto err_vfree;
+		retval = -EINVAL;
+		goto err_csum_table;
 	}
 
 	info->fix.smem_start = par->metromem_dma;
 	par->metromem_cmd = (struct metromem_cmd *) par->metromem;
 	par->metromem_wfm = par->metromem + cmd_size;
 	par->metromem_img = par->metromem + cmd_size + wfm_size;
-	par->metromem_img_csum = (u16 *) (par->metromem_img +
-					(epd_frame_table[0].fw * DPY_H));
-	DPRINTK("img offset=0x%x\n", cmd_size + wfm_size);
-	par->metromem_desc = (struct metromem_desc *) (par->metromem + cmd_size
-					+ wfm_size + img_size + padding_size);
-	par->metromem_desc_dma = par->metromem_dma + cmd_size + wfm_size
-				 + img_size + padding_size;
+	par->metromem_img_csum = (u16 *) (par->metromem_img + (fw * fh));
 
 	/* load the waveform in. assume mode 3, temp 31 for now
 		a) request the waveform file from userspace
@@ -658,7 +694,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 	retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
 	if (retval < 0) {
 		dev_err(&dev->dev, "Failed to get waveform\n");
-		goto err_dma_free;
+		goto err_csum_table;
 	}
 
 	retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31,
@@ -666,11 +702,11 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 	release_firmware(fw_entry);
 	if (retval < 0) {
 		dev_err(&dev->dev, "Failed processing waveform\n");
-		goto err_dma_free;
+		goto err_csum_table;
 	}
 
 	if (board->setup_irq(info))
-		goto err_dma_free;
+		goto err_csum_table;
 
 	retval = metronome_init_regs(par);
 	if (retval < 0)
@@ -684,7 +720,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 	retval = fb_alloc_cmap(&info->cmap, 8, 0);
 	if (retval < 0) {
 		dev_err(&dev->dev, "Failed to allocate colormap\n");
-		goto err_fb_rel;
+		goto err_free_irq;
 	}
 
 	/* set cmap */
@@ -707,17 +743,15 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 
 err_cmap:
 	fb_dealloc_cmap(&info->cmap);
-err_fb_rel:
-	framebuffer_release(info);
 err_free_irq:
-	board->free_irq(info);
-err_dma_free:
-	dma_free_writecombine(&dev->dev, par->metromemsize, par->metromem,
-				par->metromem_dma);
+	board->cleanup(par);
 err_csum_table:
 	vfree(par->csum_table);
 err_vfree:
 	vfree(videomemory);
+err_fb_rel:
+	framebuffer_release(info);
+err:
 	module_put(board->owner);
 	return retval;
 }
@@ -728,15 +762,15 @@ static int __devexit metronomefb_remove(struct platform_device *dev)
 
 	if (info) {
 		struct metronomefb_par *par = info->par;
+
+		unregister_framebuffer(info);
 		fb_deferred_io_cleanup(info);
-		dma_free_writecombine(&dev->dev, par->metromemsize,
-					par->metromem, par->metromem_dma);
 		fb_dealloc_cmap(&info->cmap);
+		par->board->cleanup(par);
 		vfree(par->csum_table);
-		unregister_framebuffer(info);
 		vfree((void __force *)info->screen_base);
-		par->board->free_irq(info);
 		module_put(par->board->owner);
+		dev_dbg(&dev->dev, "calling release\n");
 		framebuffer_release(info);
 	}
 	return 0;
@@ -761,6 +795,9 @@ static void __exit metronomefb_exit(void)
 	platform_driver_unregister(&metronomefb_driver);
 }
 
+module_param(user_wfm_size, uint, 0);
+MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size");
+
 module_init(metronomefb_init);
 module_exit(metronomefb_exit);
 
diff --git a/include/video/metronomefb.h b/include/video/metronomefb.h
index dab04b4..79444cd 100644
--- a/include/video/metronomefb.h
+++ b/include/video/metronomefb.h
@@ -12,14 +12,6 @@
 #ifndef _LINUX_METRONOMEFB_H_
 #define _LINUX_METRONOMEFB_H_
 
-/* address and control descriptors used by metronome controller */
-struct metromem_desc {
-	u32 mFDADR0;
-	u32 mFSADR0;
-	u32 mFIDR0;
-	u32 mLDCMD0;
-};
-
 /* command structure used by metronome controller */
 struct metromem_cmd {
 	u16 opcode;
@@ -30,33 +22,33 @@ struct metromem_cmd {
 /* struct used by metronome. board specific stuff comes from *board */
 struct metronomefb_par {
 	unsigned char *metromem;
-	struct metromem_desc *metromem_desc;
 	struct metromem_cmd *metromem_cmd;
 	unsigned char *metromem_wfm;
 	unsigned char *metromem_img;
 	u16 *metromem_img_csum;
 	u16 *csum_table;
-	int metromemsize;
 	dma_addr_t metromem_dma;
-	dma_addr_t metromem_desc_dma;
 	struct fb_info *info;
 	struct metronome_board *board;
 	wait_queue_head_t waitq;
 	u8 frame_count;
+	int extra_size;
+	int dt;
 };
 
 /* board specific routines */
 struct metronome_board {
 	struct module *owner;
-	void (*free_irq)(struct fb_info *);
-	void (*init_gpio_regs)(struct metronomefb_par *);
-	void (*init_lcdc_regs)(struct metronomefb_par *);
-	void (*post_dma_setup)(struct metronomefb_par *);
+	struct module *fbmaster;
 	void (*set_rst)(struct metronomefb_par *, int);
 	void (*set_stdby)(struct metronomefb_par *, int);
+	void (*cleanup)(struct metronomefb_par *);
 	int (*met_wait_event)(struct metronomefb_par *);
 	int (*met_wait_event_intr)(struct metronomefb_par *);
 	int (*setup_irq)(struct fb_info *);
+	int (*setup_fb)(struct metronomefb_par *);
+	int (*setup_io)(struct metronomefb_par *);
+	int (*get_panel_type)(void);
 };
 
 #endif
-- 
1.5.3.6


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface Jaya Kumar
@ 2008-07-29 15:28   ` Krzysztof Helt
  2008-07-29 16:39     ` Jaya Kumar
  0 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Helt @ 2008-07-29 15:28 UTC (permalink / raw)
  To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Sat, 26 Jul 2008 00:32:50 -0400
Jaya Kumar <jayakumar.lkml@gmail.com> wrote:

> These changes are to make it possible for a secondary driver to share the
> pxafb framebuffer. The changes include:
> - adding custom_lccr_bpp entry so that a driver can set a specific
>   transfer width on the AMLCD bus while using a separate bits per pixel for
>   its actual framebuffer.
> - adding extra_video_mem entry so that a driver can tell pxafb of its
>   additional needs.
> - adding share_video_mem/unshare_video_mem callbacks to notify the secondary
>   driver of the framebuffer address, to allow refcounting, and to cleanup on
>   completion.
> 
> Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>

Acked-by: Krzysztof Helt <krzysztof.h1@wp.pl>


Jaya,

This patch was already Acked-by Eric Miao. Please decide if you want to upload
it into the RMK's patch system or I should CC it to Andrew Morton.
Please add Acked-by tags to patches you post if they are already Acked-by.

Please upload/sent first Acked-by patches to correct persons for merge and repost
only not accepted ones. Whole your work will be merged this step by step approach.

Regards,
Krzysztof

> ---
>  drivers/video/pxafb.c            |   65 +++++++++++++++++++++++++++++++++-----
>  include/asm-arm/arch-pxa/pxafb.h |    8 +++++
>  2 files changed, 65 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
> index bb25143..54e0ad1 100644
> --- a/drivers/video/pxafb.c
> +++ b/drivers/video/pxafb.c
> @@ -57,6 +57,8 @@
>   */
>  #define DEBUG_VAR 1
>  
> +static struct platform_driver pxafb_driver;
> +
>  #include "pxafb.h"
>  
>  /* Bits which should not be set in machine configuration structures */
> @@ -218,9 +220,25 @@ pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
>   *  pxafb_bpp_to_lccr3():
>   *    Convert a bits per pixel value to the correct bit pattern for LCCR3
>   */
> -static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
> +static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var,
> +				struct pxafb_mach_info *inf)
>  {
>  	int ret = 0;
> +
> +	/* this is to support devices that have customized
> +	 * bpp settings for LCCR that are independent from
> +	 * the actual bpp used in the framebuffer.
> +	 */
> +	if (inf->custom_lccr_bpp) {
> +		switch (inf->custom_lccr_bpp) {
> +		case 1:  ret = LCCR3_1BPP; break;
> +		case 2:  ret = LCCR3_2BPP; break;
> +		case 4:  ret = LCCR3_4BPP; break;
> +		case 8:  ret = LCCR3_8BPP; break;
> +		case 16: ret = LCCR3_16BPP; break;
> +		}
> +		return ret;
> +	}
>  	switch (var->bits_per_pixel) {
>  	case 1:  ret = LCCR3_1BPP; break;
>  	case 2:  ret = LCCR3_2BPP; break;
> @@ -826,10 +844,22 @@ int pxafb_smart_flush(struct fb_info *info)
>  static void setup_parallel_timing(struct pxafb_info *fbi,
>  				  struct fb_var_screeninfo *var)
>  {
> +	struct pxafb_mach_info *inf = fbi->dev->platform_data;
>  	unsigned int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
> +	unsigned int pix_per_line = var->xres;
> +
> +	/*
> +	 * We can have a device that needs a different width for its AMLCD
> +	 * transfers than its framebuffer's bits per pixel. So we need to
> +	 * divide down the x resolution. Eg: 800 pixels at 8bpp is the fb.
> +	 * The device uses 16-bit xfers so the desired result is:
> +	 * 800 pixels / ( 16 bit xfer / 8bpp ) = 400 pixels per line
> +	 */
> +	if (inf->custom_lccr_bpp)
> +		pix_per_line /= (inf->custom_lccr_bpp / var->bits_per_pixel);
>  
>  	fbi->reg_lccr1 =
> -		LCCR1_DisWdth(var->xres) +
> +		LCCR1_DisWdth(pix_per_line) +
>  		LCCR1_HorSnchWdth(var->hsync_len) +
>  		LCCR1_BegLnDel(var->left_margin) +
>  		LCCR1_EndLnDel(var->right_margin);
> @@ -870,6 +900,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
>  {
>  	u_long flags;
>  	size_t nbytes;
> +	struct pxafb_mach_info *inf = fbi->dev->platform_data;
>  
>  #if DEBUG_VAR
>  	if (!(fbi->lccr0 & LCCR0_LCDT)) {
> @@ -928,7 +959,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
>  		(LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
>  		 LCCR0_QDM | LCCR0_BM  | LCCR0_OUM);
>  
> -	fbi->reg_lccr3 |= pxafb_bpp_to_lccr3(var);
> +	fbi->reg_lccr3 |= pxafb_bpp_to_lccr3(var, inf);
>  
>  	nbytes = var->yres * fbi->fb.fix.line_length;
>  
> @@ -1304,14 +1335,17 @@ static int pxafb_resume(struct platform_device *dev)
>   *      cache.  Once this area is remapped, all virtual memory
>   *      access to the video memory should occur at the new region.
>   */
> -static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
> +static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi,
> +						struct pxafb_mach_info *inf)
>  {
> +	int ret;
>  	/*
>  	 * We reserve one page for the palette, plus the size
>  	 * of the framebuffer.
>  	 */
>  	fbi->video_offset = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
> -	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset);
> +	fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset +
> +					inf->extra_video_mem);
>  	fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
>  					      &fbi->map_dma, GFP_KERNEL);
>  
> @@ -1340,6 +1374,13 @@ static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
>  		fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
>  		fbi->n_smart_cmds = 0;
>  #endif
> +		if (inf->share_video_mem) {
> +			ret = inf->share_video_mem(fbi->fb.screen_base,
> +				fbi->screen_dma, pxafb_driver.driver.owner,
> +				inf->extra_data);
> +			if (ret)
> +				return ret;
> +		}
>  	}
>  
>  	return fbi->map_cpu ? 0 : -ENOMEM;
> @@ -1761,10 +1802,12 @@ static int __devinit pxafb_probe(struct platform_device *dev)
>  	}
>  
>  	/* Initialize video memory */
> -	ret = pxafb_map_video_memory(fbi);
> -	if (ret) {
> +	ret = pxafb_map_video_memory(fbi, inf);
> +	if (ret == -ENODEV) {
> +		dev_err(&dev->dev, "Failed device binding: %d\n", ret);
> +		goto failed_free_mem;
> +	} else if (ret) {
>  		dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret);
> -		ret = -ENOMEM;
>  		goto failed_free_io;
>  	}
>  
> @@ -1836,6 +1879,8 @@ failed_free_cmap:
>  failed_free_irq:
>  	free_irq(irq, fbi);
>  failed_free_mem:
> +	if (inf->unshare_video_mem)
> +		inf->unshare_video_mem(inf->extra_data);
>  	dma_free_writecombine(&dev->dev, fbi->map_size,
>  			fbi->map_cpu, fbi->map_dma);
>  failed_free_io:
> @@ -1856,6 +1901,7 @@ static int __devexit pxafb_remove(struct platform_device *dev)
>  	struct resource *r;
>  	int irq;
>  	struct fb_info *info;
> +	struct pxafb_mach_info *inf;
>  
>  	if (!fbi)
>  		return 0;
> @@ -1872,6 +1918,9 @@ static int __devexit pxafb_remove(struct platform_device *dev)
>  	irq = platform_get_irq(dev, 0);
>  	free_irq(irq, fbi);
>  
> +	inf = dev->dev.platform_data;
> +	if (inf->unshare_video_mem)
> +		inf->unshare_video_mem(inf->extra_data);
>  	dma_free_writecombine(&dev->dev, fbi->map_size,
>  					fbi->map_cpu, fbi->map_dma);
>  
> diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
> index daf018d..c8c3e84 100644
> --- a/include/asm-arm/arch-pxa/pxafb.h
> +++ b/include/asm-arm/arch-pxa/pxafb.h
> @@ -139,9 +139,17 @@ struct pxafb_mach_info {
>  	 * All other bits in LCCR4 should be left alone.
>  	 */
>  	u_int		lccr4;
> +	unsigned int	custom_lccr_bpp; /* custom bpp setting */
> +	/* size of extra mem needed for secondary driver */
> +	unsigned int	extra_video_mem;
> +	void		*extra_data; /* extra data for secondary */
>  	void (*pxafb_backlight_power)(int);
>  	void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
>  	void (*smart_update)(struct fb_info *);
> +	/* share_video_mem allows client drivers to get our framebuffer */
> +	int (*share_video_mem)(char __iomem *, dma_addr_t, struct module *,
> +				void *);
> +	void (*unshare_video_mem)(void *);
>  };
>  void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
>  void set_pxa_fb_parent(struct device *parent_dev);
> -- 
> 1.5.3.6
> 
> 
> -------------------------------------------------------------------
> List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
> FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
> Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php
> 

----------------------------------------------------------------------
Nie dla mieczakow!
Sprawdz >>> http://link.interia.pl/f1e93


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-29 15:28   ` Krzysztof Helt
@ 2008-07-29 16:39     ` Jaya Kumar
  0 siblings, 0 replies; 27+ messages in thread
From: Jaya Kumar @ 2008-07-29 16:39 UTC (permalink / raw)
  To: Krzysztof Helt; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Tue, Jul 29, 2008 at 11:28 PM, Krzysztof Helt <krzysztof.h1@poczta.fm> wrote:
> On Sat, 26 Jul 2008 00:32:50 -0400
> Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>
>> These changes are to make it possible for a secondary driver to share the
>> pxafb framebuffer. The changes include:
>> - adding custom_lccr_bpp entry so that a driver can set a specific
>>   transfer width on the AMLCD bus while using a separate bits per pixel for
>>   its actual framebuffer.
>> - adding extra_video_mem entry so that a driver can tell pxafb of its
>>   additional needs.
>> - adding share_video_mem/unshare_video_mem callbacks to notify the secondary
>>   driver of the framebuffer address, to allow refcounting, and to cleanup on
>>   completion.
>>
>> Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
>
> Acked-by: Krzysztof Helt <krzysztof.h1@wp.pl>
>
>
> Jaya,
>
> This patch was already Acked-by Eric Miao. Please decide if you want to upload
> it into the RMK's patch system or I should CC it to Andrew Morton.
> Please add Acked-by tags to patches you post if they are already Acked-by.
>

Hi Krzysztof,

Thanks. My intention is to eventually push this set to rmk. Of the
original 10 of this set, I've pushed 4 to rmk which I think are
already in Linus's tree now.

I'll add the acked-by tags to this set when I post next. I was being
cautious about keeping acked-by tags on patches where I've made
changes even if minor. :-)

I think Eric has acked patch #2, the MFP conversion. But this add
shared fb interface to pxafb, patch #1 hasn't received his ack yet so
I am seeking his approval before submitting to rmk.

Thanks,
jaya

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-26  3:30       ` Jaya Kumar
@ 2008-07-30  2:41         ` Eric Miao
  2008-07-30  3:10           ` Jaya Kumar
  0 siblings, 1 reply; 27+ messages in thread
From: Eric Miao @ 2008-07-30  2:41 UTC (permalink / raw)
  To: Jaya Kumar
  Cc: linux-fbdev-devel, ymiao3, Russell King - ARM Linux,
	linux-arm-kernel

On Sat, Jul 26, 2008 at 11:30 AM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> On Mon, Jul 21, 2008 at 8:32 AM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>> On Mon, Jul 21, 2008 at 7:11 AM, Russell King - ARM Linux
>> <linux@arm.linux.org.uk> wrote:
>>> On Sun, Jul 20, 2008 at 02:10:29AM -0400, Jaya Kumar wrote:
>>>
>>>> @@ -1357,6 +1379,8 @@ static void pxafb_decode_mode_info(struct pxafb_info *fbi,
>>>>               smemlen = modes[i].xres * modes[i].yres * modes[i].bpp / 8;
>>>>               if (smemlen > fbi->fb.fix.smem_len)
>>>>                       fbi->fb.fix.smem_len = smemlen;
>>>> +             if (inf->custom_xfer_div)
>>>> +                     fbi->fb.fix.smem_len /= inf->custom_xfer_div;
>>>
>>> I don't understand this.  If you have a 640x480 display with 8 bits of
>>> memory per pixel, then it's 307200 bytes no matter whether you're only
>>> using the lower 4 bits and the upper 4 are unused.
>>>
>>> If, on the other hand, the lower 4 bits contain one pixel and the upper
>>> 4 bits contain the other pixel, then you have a 4 bit per pixel
>>> framebuffer, so 'bpp' should be 4.  In which case the original calculation
>>> gives the correct answer.
>>>
>>
>> The complexity I faced is that the transfers used by Metronome on the
>> AMLCD bus have to be 16-bits wide although it is actually treating the
>> pixels as 8-bits per pixel and then only using the lower 4-bits within
>> that for actual content. So what I did in the code is set bits per
>> pixel, bpp to 16 so that pxafb sets the LCCR3_16BPP flag (so that it
>> meets Metronome's AMLCD transfer requirements) and then use the
>> custom_xfer_div to divide the transfer sizes and buffer allocations to
>> the correct size.
>>
>> If I set bpp to 8, the allocations and transfer sizes are correct but
>> then that causes pxafb to set LCCR3_8BPP and that causes Metronome to
>> fail to display anything.
>>
>> Instead of doing custom_xfer_div, I had thought about setting
>> pxafb_mach_info.lccr3 = LCCR3_16BPP to try to force the setting of
>> LCCR3_16BPP but then I saw:
>>
>> include/asm/arch-pxa/pxafb.h
>>         * The following should not be defined in LCCR3
>>         *      LCCR3_HSP, LCCR3_VSP, LCCR0_Pcd(x), LCCR3_Bpp
>>         */
>>        u_int           lccr3;
>>
>> so I decided to create custom_xfer_div instead. How about if I try a
>> different way like creating a separate flag that can be used to
>> predicate the lccr3 setting. Maybe something like:
>>
>> static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
>> ...
>>        case 8:
>>               switch (inf->custom_amlcd_bpp) {
>>                case 16: ret = LCCR3_16BPP; break;
>>                default: ret = LCCR3_8BPP; break;
>>        case 16: ret = LCCR3_16BPP; break;
>>
>> Thanks,
>> jaya
>>
>
> I took a look at doing the above, ie: adjusting bpp instead of
> custom_xfer_size. I've realized that I would still need to adjust lccr
> in at least one other place:
>
>        fbi->reg_lccr1 =
>                LCCR1_DisWdth(var->xres) +
>
> I'll try to improve my explanation. :-)
>
> The reason for this is that metronome requires a different bus width
> (16 bit) for AMLCD transfers than it requires for its expected bits
> per pixel ( 8 bits). To get LCDC to use 16 bits on the AMLCD bus, we
> need to set 16bpp in LCCR3. So we then need to divide down the x
> resolution in LCCR1. Eg: 800 pixels at 8bpp is the framebuffer. We
> need 16-bit transfers so we set the desired pixels per line in LCCR to
> = 800 pixels / ( 16 custom bus bits / 8 bits per pixel ) = 400 pixels
> per line. So the code would be like:
>
> pix_per_line = var->xres / ( inf->custom_lccr_bpp / var->bits_per_pixel )
>
> I hope I was able to explain my reasoning for this above.
>

Sorry for the delay, I begin to understand the way this metronome is
working, so each transfer is 16-bit wide and contains two 8-bit pixels?

Then the most simple way is to treat this display as 16-bit, and
adjust the resolution parameters in the platform data with a nice
comment.

The problem of doing so is that:
1) framebuffer console cann't work anymore, and will show garbage
instead of showing the nice penguine logo

2) the framebuffer application has to be aware of this, and handles
the pixel format correctly.

Provided the fact of this weird organized pixel format, I don't see many
chances that X window or console can be run on top of this, but a
specialized application, no?

> Thanks,
> jaya
>
> -------------------------------------------------------------------
> List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
> FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
> Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php
>



-- 
Cheers
- eric

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 3/5] am200epd: convert to shared fb and use gpio api
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 3/5] am200epd: convert to shared fb and use gpio api Jaya Kumar
@ 2008-07-30  2:45   ` Eric Miao
  0 siblings, 0 replies; 27+ messages in thread
From: Eric Miao @ 2008-07-30  2:45 UTC (permalink / raw)
  To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Sat, Jul 26, 2008 at 12:32 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> The original am200epd driver was designed with bad assumptions. It
> manipulated GPSR/GPLR registers directly. It relied on direct access to the
> pxa LCDC registers which have since conflicted with commit
> ce4fb7b892a6d6c6a0f87366b26fd834d2923dd7 . This patch moves it into mach-pxa
> and overhauls it to use pxafb's fb. It now uses the generic GPIO api.

Is it possible for a separate patch for the GPIO conversion, which I'm
totally happy with. And that's going to make review and merging a bit
quicker.

Thanks.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages
  2008-07-26  4:32 ` [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages Jaya Kumar
@ 2008-07-30  2:50   ` Eric Miao
  2008-07-30  3:18     ` Jaya Kumar
  0 siblings, 1 reply; 27+ messages in thread
From: Eric Miao @ 2008-07-30  2:50 UTC (permalink / raw)
  To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Sat, Jul 26, 2008 at 12:32 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> This patch converts the printk messages in metronomefb to dev_dbg/err type
> messages.
>

I think this is already Acked (except for the DEBUG definition), so it would
probably nice if you can re-order the patch series and put this in the front,
so the next time we can focus on those patches with concerns only, and
get things merged a bit quicker.

That will take you sometime, though. Sorry about that and thanks for the
good work.

> Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
> ---
>  drivers/video/metronomefb.c |   49 +++++++++++++++++++-----------------------
>  1 files changed, 22 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
> index cc4c038..8ccd113 100644
> --- a/drivers/video/metronomefb.c
> +++ b/drivers/video/metronomefb.c
> @@ -18,6 +18,8 @@
>  * is provided as am200epd.c
>  *
>  */
> +#define DEBUG 1
> +
>  #include <linux/module.h>
>  #include <linux/kernel.h>
>  #include <linux/errno.h>
> @@ -40,15 +42,6 @@
>
>  #include <asm/unaligned.h>
>
> -
> -#define DEBUG 1
> -#ifdef DEBUG
> -#define DPRINTK(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
> -#else
> -#define DPRINTK(f, a...)
> -#endif
> -
> -
>  /* Display specific information */
>  #define DPY_W 832
>  #define DPY_H 622
> @@ -135,8 +128,8 @@ static u16 calc_img_cksum(u16 *start, int length)
>
>  /* here we decode the incoming waveform file and populate metromem */
>  #define EXP_WFORM_SIZE 47001
> -static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
> -                               u8 *frame_count)
> +static int __devinit load_waveform(u8 *mem, size_t size, int m, int t,
> +                               struct metronomefb_par *par)
>  {
>        int tta;
>        int wmta;
> @@ -148,9 +141,11 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
>        int wfm_idx, owfm_idx;
>        int mem_idx = 0;
>        struct waveform_hdr *wfm_hdr;
> +       u8 *metromem = par->metromem_wfm;
> +       struct device *dev = par->info->dev;
>
>        if (size != EXP_WFORM_SIZE) {
> -               printk(KERN_ERR "Error: unexpected size %d != %d\n", size,
> +               dev_err(dev, "Error: unexpected size %d != %d\n", size,
>                                        EXP_WFORM_SIZE);
>                return -EINVAL;
>        }
> @@ -158,16 +153,16 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
>        wfm_hdr = (struct waveform_hdr *) mem;
>
>        if (wfm_hdr->fvsn != 1) {
> -               printk(KERN_ERR "Error: bad fvsn %x\n", wfm_hdr->fvsn);
> +               dev_err(dev, "Error: bad fvsn %x\n", wfm_hdr->fvsn);
>                return -EINVAL;
>        }
>        if (wfm_hdr->luts != 0) {
> -               printk(KERN_ERR "Error: bad luts %x\n", wfm_hdr->luts);
> +               dev_err(dev, "Error: bad luts %x\n", wfm_hdr->luts);
>                return -EINVAL;
>        }
>        cksum = calc_cksum(32, 47, mem);
>        if (cksum != wfm_hdr->wfm_cs) {
> -               printk(KERN_ERR "Error: bad cksum %x != %x\n", cksum,
> +               dev_err(dev, "Error: bad cksum %x != %x\n", cksum,
>                                        wfm_hdr->wfm_cs);
>                return -EINVAL;
>        }
> @@ -175,7 +170,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
>        wfm_hdr->trc += 1;
>        for (i = 0; i < 5; i++) {
>                if (*(wfm_hdr->stuff2a + i) != 0) {
> -                       printk(KERN_ERR "Error: unexpected value in padding\n");
> +                       dev_err(dev, "Error: unexpected value in padding\n");
>                        return -EINVAL;
>                }
>        }
> @@ -200,7 +195,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
>                return -EINVAL;
>        cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
>        if (cksum != mem[cksum_idx]) {
> -               printk(KERN_ERR "Error: bad temperature range table cksum"
> +               dev_err(dev, "Error: bad temperature range table cksum"
>                                " %x != %x\n", cksum, mem[cksum_idx]);
>                return -EINVAL;
>        }
> @@ -212,7 +207,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
>                return -EINVAL;
>        cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
>        if (cksum != mem[cksum_idx]) {
> -               printk(KERN_ERR "Error: bad mode table address cksum"
> +               dev_err(dev, "Error: bad mode table address cksum"
>                                " %x != %x\n", cksum, mem[cksum_idx]);
>                return -EINVAL;
>        }
> @@ -224,7 +219,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
>                return -EINVAL;
>        cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
>        if (cksum != mem[cksum_idx]) {
> -               printk(KERN_ERR "Error: bad temperature table address cksum"
> +               dev_err(dev, "Error: bad temperature table address cksum"
>                        " %x != %x\n", cksum, mem[cksum_idx]);
>                return -EINVAL;
>        }
> @@ -259,11 +254,11 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
>                return -EINVAL;
>        cksum = calc_cksum(owfm_idx, cksum_idx, mem);
>        if (cksum != mem[cksum_idx]) {
> -               printk(KERN_ERR "Error: bad waveform data cksum"
> +               dev_err(dev, "Error: bad waveform data cksum"
>                                " %x != %x\n", cksum, mem[cksum_idx]);
>                return -EINVAL;
>        }
> -       *frame_count = (mem_idx/64);
> +       par->frame_count = (mem_idx/64);
>
>        return 0;
>  }
> @@ -662,15 +657,15 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
>                b) process waveform and decode into metromem */
>        retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
>        if (retval < 0) {
> -               printk(KERN_ERR "metronomefb: couldn't get waveform\n");
> +               dev_err(&dev->dev, "Failed to get waveform\n");
>                goto err_dma_free;
>        }
>
> -       retval = load_waveform((u8 *) fw_entry->data, fw_entry->size,
> -                               par->metromem_wfm, 3, 31, &par->frame_count);
> +       retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31,
> +                               par);
>        release_firmware(fw_entry);
>        if (retval < 0) {
> -               printk(KERN_ERR "metronomefb: couldn't process waveform\n");
> +               dev_err(&dev->dev, "Failed processing waveform\n");
>                goto err_dma_free;
>        }
>
> @@ -688,7 +683,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
>
>        retval = fb_alloc_cmap(&info->cmap, 8, 0);
>        if (retval < 0) {
> -               printk(KERN_ERR "Failed to allocate colormap\n");
> +               dev_err(&dev->dev, "Failed to allocate colormap\n");
>                goto err_fb_rel;
>        }
>
> @@ -704,7 +699,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
>
>        platform_set_drvdata(dev, info);
>
> -       printk(KERN_INFO
> +       dev_dbg(&dev->dev,
>                "fb%d: Metronome frame buffer device, using %dK of video"
>                " memory\n", info->node, videomemorysize >> 10);
>
> --
> 1.5.3.6
>
>
> -------------------------------------------------------------------
> List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
> FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
> Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php
>



-- 
Cheers
- eric

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface
  2008-07-30  2:41         ` Eric Miao
@ 2008-07-30  3:10           ` Jaya Kumar
  0 siblings, 0 replies; 27+ messages in thread
From: Jaya Kumar @ 2008-07-30  3:10 UTC (permalink / raw)
  To: Eric Miao
  Cc: linux-fbdev-devel, ymiao3, Russell King - ARM Linux,
	linux-arm-kernel

On Tue, Jul 29, 2008 at 10:41 PM, Eric Miao <eric.y.miao@gmail.com> wrote:
> On Sat, Jul 26, 2008 at 11:30 AM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>>
>> I took a look at doing the above, ie: adjusting bpp instead of
>> custom_xfer_size. I've realized that I would still need to adjust lccr
>> in at least one other place:
>>
>>        fbi->reg_lccr1 =
>>                LCCR1_DisWdth(var->xres) +
>>
>> I'll try to improve my explanation. :-)
>>
>> The reason for this is that metronome requires a different bus width
>> (16 bit) for AMLCD transfers than it requires for its expected bits
>> per pixel ( 8 bits). To get LCDC to use 16 bits on the AMLCD bus, we
>> need to set 16bpp in LCCR3. So we then need to divide down the x
>> resolution in LCCR1. Eg: 800 pixels at 8bpp is the framebuffer. We
>> need 16-bit transfers so we set the desired pixels per line in LCCR to
>> = 800 pixels / ( 16 custom bus bits / 8 bits per pixel ) = 400 pixels
>> per line. So the code would be like:
>>
>> pix_per_line = var->xres / ( inf->custom_lccr_bpp / var->bits_per_pixel )
>>
>> I hope I was able to explain my reasoning for this above.
>>
>
> Sorry for the delay, I begin to understand the way this metronome is
> working, so each transfer is 16-bit wide and contains two 8-bit pixels?

Correct, the AMLCD xfer is 16-bit wide and is treated by Metronome as
2 8-bit pixels.

>
> Then the most simple way is to treat this display as 16-bit, and
> adjust the resolution parameters in the platform data with a nice
> comment.

I originally had it as .bpp = 16 ( in v6 and before) and used
custom_xfer_data to divide down the buffer sizes. The resolution needs
to stay at 800x600 so that the reported resolution for the display is
correct. So've I changed that to .bpp = 8 and used custom_lccr_bpp to
set LCCR3 to 16bpp in v7. Let me know if the implementation in v7 is
consistent with your suggestion.

>
> The problem of doing so is that:
> 1) framebuffer console cann't work anymore, and will show garbage
> instead of showing the nice penguine logo
>
> 2) the framebuffer application has to be aware of this, and handles
> the pixel format correctly.
>
> Provided the fact of this weird organized pixel format, I don't see many
> chances that X window or console can be run on top of this, but a
> specialized application, no?

Deferred IO converts the pixel data organization for the Metronome
controller so the latter is transparent to anything above fbdev. I
have tested with Xfbdev and it works quite well. So no specialized
applications needed. :-) Some video clips of it running here:
http://youtube.com/watch?v=Or3R3Q8oyuE and also a LinuxJournal article
showing the display with dillo and other standard applications.
http://www.linuxjournal.com/article/10110

Thanks,
jaya

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages
  2008-07-30  2:50   ` Eric Miao
@ 2008-07-30  3:18     ` Jaya Kumar
  0 siblings, 0 replies; 27+ messages in thread
From: Jaya Kumar @ 2008-07-30  3:18 UTC (permalink / raw)
  To: Eric Miao; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Tue, Jul 29, 2008 at 10:50 PM, Eric Miao <eric.y.miao@gmail.com> wrote:
> On Sat, Jul 26, 2008 at 12:32 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>> This patch converts the printk messages in metronomefb to dev_dbg/err type
>> messages.
>>
>
> I think this is already Acked (except for the DEBUG definition), so it would
> probably nice if you can re-order the patch series and put this in the front,
> so the next time we can focus on those patches with concerns only, and
> get things merged a bit quicker.
>
> That will take you sometime, though. Sorry about that and thanks for the
> good work.

Hi Eric,

No worries. Yup, I'll take DEBUG out before posting final. Thanks for
the review.

Regards,
jaya

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2008-07-30  3:18 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-26  4:32 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v7 Jaya Kumar
2008-07-26  4:32 ` [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface Jaya Kumar
2008-07-29 15:28   ` Krzysztof Helt
2008-07-29 16:39     ` Jaya Kumar
2008-07-26  4:32 ` [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
2008-07-26  4:32 ` [RFC 2.6.26-rc9 3/5] am200epd: convert to shared fb and use gpio api Jaya Kumar
2008-07-30  2:45   ` Eric Miao
2008-07-26  4:32 ` [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages Jaya Kumar
2008-07-30  2:50   ` Eric Miao
2008-07-30  3:18     ` Jaya Kumar
2008-07-26  4:32 ` [RFC 2.6.26-rc9 5/5] metronomefb: changes to use separate framebuffer Jaya Kumar
  -- strict thread matches above, loose matches on Subject: below --
2008-07-20  6:10 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v6 Jaya Kumar
2008-07-20  6:10 ` [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface Jaya Kumar
2008-07-21 11:11   ` Russell King - ARM Linux
2008-07-21 12:32     ` Jaya Kumar
2008-07-26  3:30       ` Jaya Kumar
2008-07-30  2:41         ` Eric Miao
2008-07-30  3:10           ` Jaya Kumar
2008-07-13 13:26 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v5 Jaya Kumar
2008-07-13 13:26 ` [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface Jaya Kumar
2008-07-16  7:00   ` eric miao
2008-07-16  8:59     ` Jaya Kumar
2008-07-16  9:08       ` eric miao
2008-07-16 11:10         ` Jaya Kumar
2008-07-16  9:38       ` Russell King - ARM Linux
2008-07-16 11:18         ` Jaya Kumar
2008-07-20  2:41           ` Jaya Kumar
2008-07-21  2:10             ` eric miao
2008-07-21  3:38               ` Jaya Kumar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).