linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes
@ 2008-05-30 12:28 Jaya Kumar
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 1/5] pxafb: module unloading support Jaya Kumar
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-30 12:28 UTC (permalink / raw)
  To: ymiao3; +Cc: linux-fbdev-devel, linux-arm-kernel


Hi Eric, arm and fbdev friends,

This RFC consists of five 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 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 achieve the same functionality without manipulating
any pxa registers directly. The patches are split as follows:

1 pxafb: module unloading support
2 pxafb: add shared framebuffer interface
3 gumstix: conversion to MFP support and add bluetooth support
4 am200epd: remove am200epd platform device driver
5 am200epd: add mach-pxa support for am200epd

I would be grateful for any feedback and advice.

Thanks,
jaya


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

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

* [RFC 2.6.26-rc3 1/5] pxafb: module unloading support
  2008-05-30 12:28 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes Jaya Kumar
@ 2008-05-30 12:28 ` Jaya Kumar
  2008-05-30 17:04   ` Krzysztof Helt
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface Jaya Kumar
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Jaya Kumar @ 2008-05-30 12:28 UTC (permalink / raw)
  To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel

This patch to pxafb adds:
 - exit and remove handlers
 - changes to use __devinit/exit for probe functions and __init/exit for
   init/exit functions
 - set g_options to initdata since it is only accessed from pxafb_init
in order to enable module loading/unloading of pxafb.

Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
 drivers/video/pxafb.c |   52 ++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 43 insertions(+), 9 deletions(-)

diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 274bc93..a4bb733 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1246,7 +1246,7 @@ 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 __init pxafb_map_video_memory(struct pxafb_info *fbi)
+static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
 {
 	/*
 	 * We reserve one page for the palette, plus the size
@@ -1346,7 +1346,7 @@ decode_mode:
 	pxafb_decode_mode_info(fbi, inf->modes, inf->num_modes);
 }
 
-static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
+static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
 {
 	struct pxafb_info *fbi;
 	void *addr;
@@ -1408,7 +1408,7 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
 }
 
 #ifdef CONFIG_FB_PXA_PARAMETERS
-static int __init parse_opt_mode(struct device *dev, const char *this_opt)
+static int __devinit parse_opt_mode(struct device *dev, const char *this_opt)
 {
 	struct pxafb_mach_info *inf = dev->platform_data;
 
@@ -1467,7 +1467,7 @@ done:
 	return 0;
 }
 
-static int __init parse_opt(struct device *dev, char *this_opt)
+static int __devinit parse_opt(struct device *dev, char *this_opt)
 {
 	struct pxafb_mach_info *inf = dev->platform_data;
 	struct pxafb_mode_info *mode = &inf->modes[0];
@@ -1565,7 +1565,7 @@ static int __init parse_opt(struct device *dev, char *this_opt)
 	return 0;
 }
 
-static int __init pxafb_parse_options(struct device *dev, char *options)
+static int __devinit pxafb_parse_options(struct device *dev, char *options)
 {
 	char *this_opt;
 	int ret;
@@ -1584,10 +1584,10 @@ static int __init pxafb_parse_options(struct device *dev, char *options)
 	return 0;
 }
 
-static char g_options[256] __devinitdata = "";
+static char g_options[256] __initdata = "";
 
 #ifndef CONFIG_MODULES
-static int __devinit pxafb_setup_options(void)
+static int __init pxafb_setup_options(void)
 {
 	char *options = NULL;
 
@@ -1611,7 +1611,7 @@ MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
 #define pxafb_setup_options()		(0)
 #endif
 
-static int __init pxafb_probe(struct platform_device *dev)
+static int __devinit pxafb_probe(struct platform_device *dev)
 {
 	struct pxafb_info *fbi;
 	struct pxafb_mach_info *inf;
@@ -1776,16 +1776,44 @@ failed:
 	return ret;
 }
 
+static int __devexit pxafb_remove(struct platform_device *dev)
+{
+	struct pxafb_info *fbi = platform_get_drvdata(dev);
+	struct resource *r;
+	int irq;
+
+	if (fbi) {
+		struct fb_info *info = &fbi->fb;
+
+		irq = platform_get_irq(dev, 0);
+		free_irq(irq, fbi);
+
+		r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+		release_mem_region(r->start, r->end - r->start + 1);
+
+		iounmap(fbi->mmio_base);
+
+		dma_free_writecombine(&dev->dev, fbi->map_size,
+					fbi->map_cpu, fbi->map_dma);
+		fb_dealloc_cmap(&info->cmap);
+		unregister_framebuffer(info);
+		kfree(fbi);
+	}
+	return 0;
+}
+
 static struct platform_driver pxafb_driver = {
 	.probe		= pxafb_probe,
+	.remove 	= pxafb_remove,
 	.suspend	= pxafb_suspend,
 	.resume		= pxafb_resume,
 	.driver		= {
+		.owner	= THIS_MODULE,
 		.name	= "pxa2xx-fb",
 	},
 };
 
-static int __devinit pxafb_init(void)
+static int __init pxafb_init(void)
 {
 	if (pxafb_setup_options())
 		return -EINVAL;
@@ -1793,7 +1821,13 @@ static int __devinit pxafb_init(void)
 	return platform_driver_register(&pxafb_driver);
 }
 
+static void __exit pxafb_exit(void)
+{
+	platform_driver_unregister(&pxafb_driver);
+}
+
 module_init(pxafb_init);
+module_exit(pxafb_exit);
 
 MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
 MODULE_LICENSE("GPL");
-- 
1.5.3.6


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

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

* [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface
  2008-05-30 12:28 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes Jaya Kumar
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 1/5] pxafb: module unloading support Jaya Kumar
@ 2008-05-30 12:28 ` Jaya Kumar
  2008-05-30 17:10   ` Krzysztof Helt
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 3/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Jaya Kumar @ 2008-05-30 12:28 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            |   46 ++++++++++++++++++++++++++++++++-----
 include/asm-arm/arch-pxa/pxafb.h |    9 +++++++
 3 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index d6c05b6..b72b73a 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -130,6 +130,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 a4bb733..2a574ad 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 */
@@ -775,10 +777,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);
@@ -819,6 +826,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)) {
@@ -878,6 +886,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;
@@ -1246,14 +1256,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);
 
@@ -1280,6 +1293,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;
@@ -1290,6 +1310,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]);
 
@@ -1297,6 +1318,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)
+			smemlen /= inf->custom_xfer_div;
 	}
 }
 
@@ -1360,7 +1383,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;
@@ -1701,8 +1724,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);
+		ret = -ENODEV;
+		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;
@@ -1770,6 +1797,8 @@ failed_free_io:
 failed_free_mem:
 	dma_free_writecombine(&dev->dev, fbi->map_size,
 			fbi->map_cpu, fbi->map_dma);
+	if (inf->unshare_video_mem)
+		inf->unshare_video_mem(inf->extra_data);
 failed:
 	platform_set_drvdata(dev, NULL);
 	kfree(fbi);
@@ -1783,6 +1812,7 @@ static int __devexit pxafb_remove(struct platform_device *dev)
 	int irq;
 
 	if (fbi) {
+		struct pxafb_mach_info *inf;
 		struct fb_info *info = &fbi->fb;
 
 		irq = platform_get_irq(dev, 0);
@@ -1792,7 +1822,9 @@ static int __devexit pxafb_remove(struct platform_device *dev)
 		release_mem_region(r->start, r->end - r->start + 1);
 
 		iounmap(fbi->mmio_base);
-
+		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);
 		fb_dealloc_cmap(&info->cmap);
diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
index bbd2239..c703633 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -138,9 +138,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)(unsigned char *, 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


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

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

* [RFC 2.6.26-rc3 3/5] gumstix: conversion to MFP support and add bluetooth support
  2008-05-30 12:28 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes Jaya Kumar
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 1/5] pxafb: module unloading support Jaya Kumar
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface Jaya Kumar
@ 2008-05-30 12:28 ` Jaya Kumar
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 4/5] am200epd: remove am200epd platform device driver Jaya Kumar
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 5/5] am200epd: add mach-pxa support for am200epd Jaya Kumar
  4 siblings, 0 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-30 12:28 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. Added a CLK_32K clock to enable bluetooth.

Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
 arch/arm/mach-pxa/gumstix.c           |   79 ++++++++++++++++++++++++++-------
 arch/arm/mach-pxa/pxa25x.c            |   31 +++++++++++++
 include/asm-arm/arch-pxa/mfp-pxa25x.h |    1 +
 3 files changed, 95 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index bdf2397..3e0a962 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,7 +100,7 @@ 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
 
@@ -126,12 +117,68 @@ 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
+static void __init gumstix_bluetooth_init(void)
+{
+	int err;
+	struct clk *clk32k;
+
+	clk32k = clk_get(NULL, "CLK_32K");
+	if (IS_ERR(clk32k)) {
+		pr_err("gumstix: failed to find 32kHz clock\n");
+		return;
+	}
+	clk_enable(clk32k);
+
+	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 = {
+#ifdef CONFIG_BT
+	GPIO12_32KHz,
+	/* BTUART */
+	GPIO42_HWUART_RXD,
+	GPIO43_HWUART_TXD,
+	GPIO44_HWUART_CTS,
+	GPIO45_HWUART_RTSL,
+#endif
+#ifdef CONFIG_MMC_PXA
+	/* MMC */
+	GPIO6_MMC_CLK,
+	GPIO53_MMC_CLK,
+	GPIO8_MMC_CS0,
+#endif
+	/* 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));
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index e5b417d..1ffe773 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -22,6 +22,7 @@
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
 #include <linux/sysdev.h>
+#include <linux/delay.h>
 
 #include <asm/hardware.h>
 #include <asm/arch/irqs.h>
@@ -108,6 +109,30 @@ static const struct clkops clk_pxa25x_lcd_ops = {
 	.getrate	= clk_pxa25x_lcd_getrate,
 };
 
+static void clk_32k_enable(struct clk *clk)
+{
+	int timeout = 500;
+
+	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 clk_32k_disable(struct clk *clk)
+{
+	OSCC &= ~OSCC_OON;
+}
+
+static const struct clkops clk_32k_ops = {
+	.enable		= clk_32k_enable,
+	.disable	= clk_32k_disable,
+};
+
 /*
  * 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz)
  * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
@@ -118,6 +143,12 @@ static struct clk pxa25x_hwuart_clk =
 ;
 
 static struct clk pxa25x_clks[] = {
+	{
+		.name           = "CLK_32K",
+		.ops            = &clk_32k_ops,
+		.rate           = 32000,
+		.delay          = 70,
+	},
 	INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev),
 	INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev),
 	INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
diff --git a/include/asm-arm/arch-pxa/mfp-pxa25x.h b/include/asm-arm/arch-pxa/mfp-pxa25x.h
index 0499323..6c82a74 100644
--- a/include/asm-arm/arch-pxa/mfp-pxa25x.h
+++ b/include/asm-arm/arch-pxa/mfp-pxa25x.h
@@ -79,6 +79,7 @@
 #define GPIO43_HWUART_TXD	MFP_CFG_OUT(GPIO43, AF3, DRIVE_HIGH)
 #define GPIO44_HWUART_CTS	MFP_CFG_IN(GPIO44, AF3)
 #define GPIO45_HWUART_RTS	MFP_CFG_OUT(GPIO45, AF3, DRIVE_HIGH)
+#define GPIO45_HWUART_RTSL	MFP_CFG_OUT(GPIO45, AF3, DRIVE_LOW)
 #define GPIO48_HWUART_TXD	MFP_CFG_OUT(GPIO48, AF1, DRIVE_HIGH)
 #define GPIO49_HWUART_RXD	MFP_CFG_IN(GPIO49, AF1)
 #define GPIO50_HWUART_CTS	MFP_CFG_IN(GPIO50, AF1)
-- 
1.5.3.6


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

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

* [RFC 2.6.26-rc3 4/5] am200epd: remove am200epd platform device driver
  2008-05-30 12:28 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes Jaya Kumar
                   ` (2 preceding siblings ...)
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 3/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
@ 2008-05-30 12:28 ` Jaya Kumar
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 5/5] am200epd: add mach-pxa support for am200epd Jaya Kumar
  4 siblings, 0 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-30 12:28 UTC (permalink / raw)
  To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel

The 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 . Thus, it is broken and this patch
removes it.

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

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 002b61b..2bbd328 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1937,19 +1937,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: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

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

* [RFC 2.6.26-rc3 5/5] am200epd: add mach-pxa support for am200epd
  2008-05-30 12:28 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes Jaya Kumar
                   ` (3 preceding siblings ...)
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 4/5] am200epd: remove am200epd platform device driver Jaya Kumar
@ 2008-05-30 12:28 ` Jaya Kumar
  4 siblings, 0 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-30 12:28 UTC (permalink / raw)
  To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel

am200epd implements mach-pxa support for the am200epd carrier board. It
interfaces with metronomefb and pxafb in order to support various E-Ink
panels.
This patch does:
- export pxa_device_fb to be accessed by am200epd
- redo the metronomefb interface code to interface properly with am200epd
- allow am200epd to handle different panels properly
- cleanup to use dev_dbg instead of printk
- remove mach-pxa like structure from metronomefb
- add board support for am200epd

Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
 arch/arm/mach-pxa/Kconfig    |   17 ++
 arch/arm/mach-pxa/Makefile   |    1 +
 arch/arm/mach-pxa/am200epd.c |  347 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-pxa/devices.c  |    1 +
 drivers/video/metronomefb.c  |  270 ++++++++++++++++++--------------
 include/video/metronomefb.h  |   21 +--
 6 files changed, 524 insertions(+), 133 deletions(-)
 create mode 100644 arch/arm/mach-pxa/am200epd.c

diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 5da7a68..1bcff21 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -179,6 +179,23 @@ endchoice
 
 endif
 
+if MACH_GUMSTIX_F
+
+choice
+	prompt "Select base board for Gumstix board"
+
+config MACH_AM200EPD
+	tristate "Enable AM200EPD board support"
+	select FB_METRONOME
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_DEFERRED_IO
+
+endchoice
+
+endif
 
 if MACH_TRIZEPS4
 
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 0e6d05b..c72db62 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,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..7aeee2c
--- /dev/null
+++ b/arch/arm/mach-pxa/am200epd.c
@@ -0,0 +1,347 @@
+/*
+ * 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		= 16,
+	.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		= 16,
+	.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		= 16,
+	.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,
+	.lccr0		= LCCR0_Pas | LCCR0_Sngl | LCCR0_Color,
+	.lccr3		= 0,
+	.lcd_conn	= LCD_TYPE_COLOR_TFT | LCD_PCLK_EDGE_FALL |
+			  LCD_AC_BIAS_FREQ(24),
+	.clkdev		= &pxa_device_fb.dev,
+	.custom_xfer_div = 2,
+};
+
+/* 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 struct platform_device *am200_pxa_device_fb;
+
+static int am200_pxa_register_device(struct platform_device *dev,
+					struct pxafb_mach_info *data)
+{
+	int ret;
+
+	am200_pxa_device_fb = platform_device_alloc("pxa2xx-fb", -1);
+	if (!am200_pxa_device_fb)
+		return -ENOMEM;
+
+	platform_device_add_data(am200_pxa_device_fb, data, sizeof(*data));
+
+	platform_device_add_resources(am200_pxa_device_fb,
+					pxa_device_fb.resource,
+					pxa_device_fb.num_resources);
+
+	am200_pxa_device_fb->dev.dma_mask = pxa_device_fb.dev.dma_mask;
+	am200_pxa_device_fb->dev.coherent_dma_mask =
+					pxa_device_fb.dev.coherent_dma_mask;
+
+	ret = platform_device_add(am200_pxa_device_fb);
+
+	if (ret) {
+		dev_err(&am200_device->dev, "failed adding pxafb %d\n", ret);
+		platform_device_put(am200_pxa_device_fb);
+	}
+
+	return ret;
+}
+
+static int am200_share_video_mem(unsigned char *video_mem, dma_addr_t dma,
+					struct module *fbmaster, void *data)
+{
+	struct metronomefb_par *par = 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;
+	par->metromem = video_mem;
+	par->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);
+}
+
+static int am200_setup_fb(struct metronomefb_par *par)
+{
+	int ret;
+
+	am200_fb_info.extra_video_mem = par->extra_size;
+	am200_fb_info.extra_data = (void *) par;
+	am200_fb_info.share_video_mem = am200_share_video_mem;
+	am200_fb_info.unshare_video_mem = am200_unshare_video_mem;
+
+	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;
+	}
+
+	ret = am200_pxa_register_device(&pxa_device_fb, &am200_fb_info);
+	return ret;
+}
+
+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, "AM200", info);
+	if (ret) {
+		dev_err(&am200_device->dev, "request_irq failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQT_FALLING);
+	if (ret)
+		dev_err(&am200_device->dev, "set_irq_type 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);
+
+	return ret;
+}
+
+static void __exit am200_exit(void)
+{
+	platform_device_unregister(am200_pxa_device_fb);
+	platform_device_unregister(am200_device);
+}
+
+module_param(panel_type, uint, 0);
+MODULE_PARM_DESC(panel_type, "Select the panel type: 6, 8, 97");
+
+module_init(am200_init);
+module_exit(am200_exit);
+
+MODULE_DESCRIPTION("board driver for am200 metronome epd kit");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index b72b73a..fe0eb07 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -127,6 +127,7 @@ struct platform_device pxa_device_fb = {
 	.num_resources	= ARRAY_SIZE(pxafb_resources),
 	.resource	= pxafb_resources,
 };
+EXPORT_SYMBOL_GPL(pxa_device_fb);
 
 void __init set_pxa_fb_info(struct pxafb_mach_info *info)
 {
diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
index cc4c038..6e1c1eb 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,29 +42,63 @@
 
 #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
 
+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,
 	},
 };
 
@@ -134,9 +170,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,26 +183,31 @@ 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,
-					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,
+					epd_frame_table[par->dt].wfm_size);
 		return -EINVAL;
 	}
 
 	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 +215,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 +240,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 +252,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 +264,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 +299,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;
 }
@@ -335,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);
@@ -408,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)
@@ -430,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,13 +579,16 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 {
 	struct fb_info *info;
 	struct metronome_board *board;
-	int retval = -ENOMEM;
+	int ret = -ENOMEM;
 	int videomemorysize;
 	unsigned char *videomemory;
 	struct metronomefb_par *par;
 	const struct firmware *fw_entry;
 	int cmd_size, wfm_size, img_size, padding_size, totalsize;
 	int i;
+	int panel_type;
+	int fw, fh;
+	int epd_dt_index;
 
 	/* pick up board specific routines */
 	board = dev->dev.platform_data;
@@ -591,9 +604,29 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 	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;
@@ -607,12 +640,18 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 	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. */
@@ -628,20 +667,21 @@ 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;
+	cmd_size = 1 * fw;
+	wfm_size = ((16*1024 + 2 + fw - 1) / fw) * fw;
+	img_size = fh * fw;
+	padding_size = 4 * fw;
+	par->extra_size = cmd_size + wfm_size + padding_size;
 	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);
+	ret = par->board->setup_fb(par);
+	if (ret) {
+		dev_err(&dev->dev, "Failed to setup fb\n");
+		goto err_vfree;
+	}
+	/* after this point we should have a framebuffer */
 	if (!par->metromem) {
-		printk(KERN_ERR
-			"metronomefb: unable to allocate dma buffer\n");
+		ret = -EINVAL;
 		goto err_vfree;
 	}
 
@@ -649,36 +689,29 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 	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
 		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");
-		goto err_dma_free;
+	ret = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
+	if (ret < 0) {
+		dev_err(&dev->dev, "Failed to get waveform\n");
+		goto err_csum_table;
 	}
 
-	retval = load_waveform((u8 *) fw_entry->data, fw_entry->size,
-				par->metromem_wfm, 3, 31, &par->frame_count);
+	ret = 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");
-		goto err_dma_free;
+	if (ret < 0) {
+		dev_err(&dev->dev, "Failed processing waveform\n");
+		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)
+	ret = metronome_init_regs(par);
+	if (ret < 0)
 		goto err_free_irq;
 
 	info->flags = FBINFO_FLAG_DEFAULT;
@@ -686,9 +719,9 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 	info->fbdefio = &metronomefb_defio;
 	fb_deferred_io_init(info);
 
-	retval = fb_alloc_cmap(&info->cmap, 8, 0);
-	if (retval < 0) {
-		printk(KERN_ERR "Failed to allocate colormap\n");
+	ret = fb_alloc_cmap(&info->cmap, 8, 0);
+	if (ret < 0) {
+		dev_err(&dev->dev, "Failed to allocate colormap\n");
 		goto err_fb_rel;
 	}
 
@@ -698,13 +731,13 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
 	memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*8);
 	memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*8);
 
-	retval = register_framebuffer(info);
-	if (retval < 0)
+	ret = register_framebuffer(info);
+	if (ret < 0)
 		goto err_cmap;
 
 	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);
 
@@ -715,16 +748,13 @@ err_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);
 	module_put(board->owner);
-	return retval;
+	return ret;
 }
 
 static int __devexit metronomefb_remove(struct platform_device *dev)
@@ -734,14 +764,13 @@ static int __devexit metronomefb_remove(struct platform_device *dev)
 	if (info) {
 		struct metronomefb_par *par = info->par;
 		fb_deferred_io_cleanup(info);
-		dma_free_writecombine(&dev->dev, par->metromemsize,
-					par->metromem, par->metromem_dma);
 		fb_dealloc_cmap(&info->cmap);
 		vfree(par->csum_table);
 		unregister_framebuffer(info);
 		vfree((void __force *)info->screen_base);
-		par->board->free_irq(info);
+		par->board->cleanup(par);
 		module_put(par->board->owner);
+		dev_dbg(&dev->dev, "calling release\n");
 		framebuffer_release(info);
 	}
 	return 0;
@@ -766,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..7eeddf2 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,7 +22,6 @@ 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;
@@ -38,25 +29,27 @@ struct metronomefb_par {
 	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: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

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

* Re: [RFC 2.6.26-rc3 1/5] pxafb: module unloading support
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 1/5] pxafb: module unloading support Jaya Kumar
@ 2008-05-30 17:04   ` Krzysztof Helt
  2008-05-31  1:02     ` Jaya Kumar
  0 siblings, 1 reply; 11+ messages in thread
From: Krzysztof Helt @ 2008-05-30 17:04 UTC (permalink / raw)
  To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Fri, 30 May 2008 08:28:46 -0400
Jaya Kumar <jayakumar.lkml@gmail.com> wrote:

> This patch to pxafb adds:
>  - exit and remove handlers
>  - changes to use __devinit/exit for probe functions and __init/exit for
>    init/exit functions
>  - set g_options to initdata since it is only accessed from pxafb_init
> in order to enable module loading/unloading of pxafb.
> 
> Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
> ---
>  drivers/video/pxafb.c |   52 ++++++++++++++++++++++++++++++++++++++++--------
>  1 files changed, 43 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
> index 274bc93..a4bb733 100644
> --- a/drivers/video/pxafb.c
> +++ b/drivers/video/pxafb.c

> @@ -1584,10 +1584,10 @@ static int __init pxafb_parse_options(struct device *dev, char *options)
>  	return 0;
>  }
>  
> -static char g_options[256] __devinitdata = "";
> +static char g_options[256] __initdata = "";
>  

This is not right. The g_options is used by
the pxafb_probe (below) and pxafb_parse_options
which are now __devinit.

> @@ -1611,7 +1611,7 @@ MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
>  #define pxafb_setup_options()		(0)
>  #endif
>  
> -static int __init pxafb_probe(struct platform_device *dev)
> +static int __devinit pxafb_probe(struct platform_device *dev)
>  {
>  	struct pxafb_info *fbi;
>  	struct pxafb_mach_info *inf;


> @@ -1776,16 +1776,44 @@ failed:
>  	return ret;
>  }
>  
> +static int __devexit pxafb_remove(struct platform_device *dev)
> +{
> +	struct pxafb_info *fbi = platform_get_drvdata(dev);
> +	struct resource *r;
> +	int irq;
> +
> +	if (fbi) {
> +		struct fb_info *info = &fbi->fb;
> +
> +		irq = platform_get_irq(dev, 0);
> +		free_irq(irq, fbi);
> +
> +		r = platform_get_resource(dev, IORESOURCE_MEM, 0);
> +		release_mem_region(r->start, r->end - r->start + 1);
> +
> +		iounmap(fbi->mmio_base);
> +

I can be wrong here, but should not the iounmap be done before
releasing the iomaped region?

Regards,
Krzysztof


----------------------------------------------------------------------
Mucha powraca!
Sprawdz >>> http://link.interia.pl/f1e0d


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

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

* Re: [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface
  2008-05-30 12:28 ` [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface Jaya Kumar
@ 2008-05-30 17:10   ` Krzysztof Helt
  2008-05-31  0:49     ` Jaya Kumar
  0 siblings, 1 reply; 11+ messages in thread
From: Krzysztof Helt @ 2008-05-30 17:10 UTC (permalink / raw)
  To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Fri, 30 May 2008 08:28:47 -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 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            |   46 ++++++++++++++++++++++++++++++++-----
>  include/asm-arm/arch-pxa/pxafb.h |    9 +++++++
>  3 files changed, 50 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
> index d6c05b6..b72b73a 100644
> --- a/arch/arm/mach-pxa/devices.c
> +++ b/arch/arm/mach-pxa/devices.c

> @@ -1297,6 +1318,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)
> +			smemlen /= inf->custom_xfer_div;
>  	}
>  }
>  

This one should be rather:

+		if (inf->custom_xfer_div)
+			fbi->fb.fix.smem_len  /= inf->custom_xfer_div;

Otherwise is does nothing (the function ends here).

Regards,
Krzysztof


----------------------------------------------------------------------
Mucha powraca!
Sprawdz >>> http://link.interia.pl/f1e0d


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

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

* Re: [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface
  2008-05-30 17:10   ` Krzysztof Helt
@ 2008-05-31  0:49     ` Jaya Kumar
  0 siblings, 0 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-31  0:49 UTC (permalink / raw)
  To: Krzysztof Helt; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Fri, May 30, 2008 at 1:10 PM, Krzysztof Helt <krzysztof.h1@poczta.fm> wrote:
>
> This one should be rather:
>
> +               if (inf->custom_xfer_div)
> +                       fbi->fb.fix.smem_len  /= inf->custom_xfer_div;
>
> Otherwise is does nothing (the function ends here).
>

Thanks for catching it. Will fix and repost.

jaya

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

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

* Re: [RFC 2.6.26-rc3 1/5] pxafb: module unloading support
  2008-05-30 17:04   ` Krzysztof Helt
@ 2008-05-31  1:02     ` Jaya Kumar
  0 siblings, 0 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-31  1:02 UTC (permalink / raw)
  To: Krzysztof Helt; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel

On Fri, May 30, 2008 at 1:04 PM, Krzysztof Helt <krzysztof.h1@poczta.fm> wrote:
> On Fri, 30 May 2008 08:28:46 -0400
> Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>
>> -static char g_options[256] __devinitdata = "";
>> +static char g_options[256] __initdata = "";
>>
>
> This is not right. The g_options is used by
> the pxafb_probe (below) and pxafb_parse_options
> which are now __devinit.

Ah, I see it now. Will fix.

>> +
>> +             r = platform_get_resource(dev, IORESOURCE_MEM, 0);
>> +             release_mem_region(r->start, r->end - r->start + 1);
>> +
>> +             iounmap(fbi->mmio_base);
>> +
>
> I can be wrong here, but should not the iounmap be done before
> releasing the iomaped region?
>

Yes, I agree with you. I used the same sequence I saw in the
pxafb_probe failout path:

failed_free_res:
        release_mem_region(r->start, r->end - r->start + 1);
failed_free_io:
        iounmap(fbi->mmio_base);

I will reorder both as the correction.

Thanks,
jaya

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

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

* [RFC 2.6.26-rc3 3/5] gumstix: conversion to MFP support and add bluetooth support
  2008-05-31  4:41 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes v2 Jaya Kumar
@ 2008-05-31  4:41 ` Jaya Kumar
  0 siblings, 0 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-31  4:41 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. Added a CLK_32K clock to enable bluetooth.

Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
 arch/arm/mach-pxa/gumstix.c           |   79 ++++++++++++++++++++++++++-------
 arch/arm/mach-pxa/pxa25x.c            |   31 +++++++++++++
 include/asm-arm/arch-pxa/mfp-pxa25x.h |    1 +
 3 files changed, 95 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index bdf2397..3e0a962 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,7 +100,7 @@ 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
 
@@ -126,12 +117,68 @@ 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
+static void __init gumstix_bluetooth_init(void)
+{
+	int err;
+	struct clk *clk32k;
+
+	clk32k = clk_get(NULL, "CLK_32K");
+	if (IS_ERR(clk32k)) {
+		pr_err("gumstix: failed to find 32kHz clock\n");
+		return;
+	}
+	clk_enable(clk32k);
+
+	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 = {
+#ifdef CONFIG_BT
+	GPIO12_32KHz,
+	/* BTUART */
+	GPIO42_HWUART_RXD,
+	GPIO43_HWUART_TXD,
+	GPIO44_HWUART_CTS,
+	GPIO45_HWUART_RTSL,
+#endif
+#ifdef CONFIG_MMC_PXA
+	/* MMC */
+	GPIO6_MMC_CLK,
+	GPIO53_MMC_CLK,
+	GPIO8_MMC_CS0,
+#endif
+	/* 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));
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index e5b417d..1ffe773 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -22,6 +22,7 @@
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
 #include <linux/sysdev.h>
+#include <linux/delay.h>
 
 #include <asm/hardware.h>
 #include <asm/arch/irqs.h>
@@ -108,6 +109,30 @@ static const struct clkops clk_pxa25x_lcd_ops = {
 	.getrate	= clk_pxa25x_lcd_getrate,
 };
 
+static void clk_32k_enable(struct clk *clk)
+{
+	int timeout = 500;
+
+	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 clk_32k_disable(struct clk *clk)
+{
+	OSCC &= ~OSCC_OON;
+}
+
+static const struct clkops clk_32k_ops = {
+	.enable		= clk_32k_enable,
+	.disable	= clk_32k_disable,
+};
+
 /*
  * 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz)
  * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
@@ -118,6 +143,12 @@ static struct clk pxa25x_hwuart_clk =
 ;
 
 static struct clk pxa25x_clks[] = {
+	{
+		.name           = "CLK_32K",
+		.ops            = &clk_32k_ops,
+		.rate           = 32000,
+		.delay          = 70,
+	},
 	INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev),
 	INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev),
 	INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
diff --git a/include/asm-arm/arch-pxa/mfp-pxa25x.h b/include/asm-arm/arch-pxa/mfp-pxa25x.h
index 0499323..6c82a74 100644
--- a/include/asm-arm/arch-pxa/mfp-pxa25x.h
+++ b/include/asm-arm/arch-pxa/mfp-pxa25x.h
@@ -79,6 +79,7 @@
 #define GPIO43_HWUART_TXD	MFP_CFG_OUT(GPIO43, AF3, DRIVE_HIGH)
 #define GPIO44_HWUART_CTS	MFP_CFG_IN(GPIO44, AF3)
 #define GPIO45_HWUART_RTS	MFP_CFG_OUT(GPIO45, AF3, DRIVE_HIGH)
+#define GPIO45_HWUART_RTSL	MFP_CFG_OUT(GPIO45, AF3, DRIVE_LOW)
 #define GPIO48_HWUART_TXD	MFP_CFG_OUT(GPIO48, AF1, DRIVE_HIGH)
 #define GPIO49_HWUART_RXD	MFP_CFG_IN(GPIO49, AF1)
 #define GPIO50_HWUART_CTS	MFP_CFG_IN(GPIO50, AF1)
-- 
1.5.3.6


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

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

end of thread, other threads:[~2008-05-31  5:39 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-30 12:28 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 1/5] pxafb: module unloading support Jaya Kumar
2008-05-30 17:04   ` Krzysztof Helt
2008-05-31  1:02     ` Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface Jaya Kumar
2008-05-30 17:10   ` Krzysztof Helt
2008-05-31  0:49     ` Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 3/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 4/5] am200epd: remove am200epd platform device driver Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 5/5] am200epd: add mach-pxa support for am200epd Jaya Kumar
  -- strict thread matches above, loose matches on Subject: below --
2008-05-31  4:41 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes v2 Jaya Kumar
2008-05-31  4:41 ` [RFC 2.6.26-rc3 3/5] gumstix: conversion to MFP support and add bluetooth support 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).