* [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v5
@ 2008-07-13 13:26 Jaya Kumar
2008-07-13 13:26 ` [RFC 2.6.26-rc9 1/5] pxafb: add shared framebuffer interface Jaya Kumar
` (4 more replies)
0 siblings, 5 replies; 22+ messages in thread
From: Jaya Kumar @ 2008-07-13 13:26 UTC (permalink / raw)
To: ymiao3; +Cc: linux-fbdev-devel, linux-arm-kernel
Hi Eric, arm and fbdev friends,
This is version 5 of this RFC and contains the following updates:
- fix unnecessary error assignment
- get rid of unnecessary ifdef's in gpio init
- remove incorrect clk32K disable
- add warning if clk32K is not enabled by bootloader
- combine the move of am200epd to mach-pxa with the conversion to new code
- get rid of use of direct setting of LCCR
- get rid of set_irq_type
- get rid of RTSL
- rebase code to using .26rc9 + linux-2.6-arm.git/pxa
Thanks to Krzysztof and Eric for feedback.
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
-------------------------------------------------------------------------
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 [flat|nested] 22+ messages in thread
* [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
2008-07-13 13:26 ` [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; 22+ 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] 22+ messages in thread
* [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support
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-13 13:26 ` Jaya Kumar
2008-07-16 6:55 ` eric miao
2008-07-13 13:26 ` [RFC 2.6.26-rc9 3/5] am200epd: convert to shared fb and use gpio api Jaya Kumar
` (2 subsequent siblings)
4 siblings, 1 reply; 22+ 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
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 | 77 +++++++++++++++++++++++++++++++++---------
arch/arm/mach-pxa/pxa25x.c | 31 +++++++++++++++++
2 files changed, 91 insertions(+), 17 deletions(-)
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index bdf2397..73c1cc5 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,64 @@ 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 = {
+ 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));
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index c5b845b..5930a8b 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>
@@ -155,6 +156,30 @@ static const struct clkops clk_pxa25x_gpio11_ops = {
.disable = clk_gpio11_disable,
};
+static void clk_32k_enable(struct clk *clk)
+{
+ 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 const struct clkops clk_32k_ops = {
+ .enable = clk_32k_enable,
+};
+
/*
* 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
@@ -169,6 +194,12 @@ static struct clk pxa25x_hwuart_clk =
* Please be careful not to disrupt the ordering.
*/
static struct clk pxa25x_clks[] = {
+ {
+ .name = "CLK_32K",
+ .ops = &clk_32k_ops,
+ .rate = 32768,
+ .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),
--
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] 22+ messages in thread
* [RFC 2.6.26-rc9 3/5] am200epd: convert to shared fb and use gpio api
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-13 13:26 ` [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
@ 2008-07-13 13:26 ` Jaya Kumar
2008-07-13 13:26 ` [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages Jaya Kumar
2008-07-13 13:26 ` [RFC 2.6.26-rc9 5/5] metronomefb: changes to use separate framebuffer Jaya Kumar
4 siblings, 0 replies; 22+ 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
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 | 9 +
arch/arm/mach-pxa/Makefile | 1 +
arch/arm/mach-pxa/am200epd.c | 340 ++++++++++++++++++++++++++++++++++++++++++
arch/arm/mach-pxa/devices.c | 1 +
drivers/video/Kconfig | 13 --
drivers/video/Makefile | 1 -
drivers/video/am200epd.c | 295 ------------------------------------
7 files changed, 351 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..ee6456f 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -243,6 +243,15 @@ config PCM990_DISPLAY_NONE
endchoice
+config MACH_AM200EPD
+ depends on MACH_GUMSTIX_F
+ 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
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..c62a17d
--- /dev/null
+++ b/arch/arm/mach-pxa/am200epd.c
@@ -0,0 +1,340 @@
+/*
+ * 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,
+ .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(char __iomem *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 = (unsigned char __force *)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|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);
+
+ 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 47af7f6..d85ea98 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -143,6 +143,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/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
-------------------------------------------------------------------------
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] 22+ messages in thread
* [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages
2008-07-13 13:26 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v5 Jaya Kumar
` (2 preceding siblings ...)
2008-07-13 13:26 ` [RFC 2.6.26-rc9 3/5] am200epd: convert to shared fb and use gpio api Jaya Kumar
@ 2008-07-13 13:26 ` Jaya Kumar
2008-07-16 7:09 ` eric miao
2008-07-13 13:26 ` [RFC 2.6.26-rc9 5/5] metronomefb: changes to use separate framebuffer Jaya Kumar
4 siblings, 1 reply; 22+ 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
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
-------------------------------------------------------------------------
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] 22+ messages in thread
* [RFC 2.6.26-rc9 5/5] metronomefb: changes to use separate framebuffer
2008-07-13 13:26 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v5 Jaya Kumar
` (3 preceding siblings ...)
2008-07-13 13:26 ` [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages Jaya Kumar
@ 2008-07-13 13:26 ` Jaya Kumar
4 siblings, 0 replies; 22+ 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 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/metronomefb.c | 225 +++++++++++++++++++++++++------------------
include/video/metronomefb.h | 22 ++---
2 files changed, 138 insertions(+), 109 deletions(-)
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
-------------------------------------------------------------------------
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] 22+ messages in thread
* Re: [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support
2008-07-13 13:26 ` [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
@ 2008-07-16 6:55 ` eric miao
2008-07-16 7:09 ` Jaya Kumar
0 siblings, 1 reply; 22+ messages in thread
From: eric miao @ 2008-07-16 6:55 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:
> This patch converts gumstix over to the MFP configuration system and adds
> bluetooth support. Added a CLK_32K clock to enable bluetooth.
>
The CLK_32KHz is assumed to be enabled always, so it's really not
necessary to create a struct clk for it. Please remove that from this
patch.
> Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
> ---
> arch/arm/mach-pxa/gumstix.c | 77 +++++++++++++++++++++++++++++++++---------
> arch/arm/mach-pxa/pxa25x.c | 31 +++++++++++++++++
> 2 files changed, 91 insertions(+), 17 deletions(-)
>
> diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
> index bdf2397..73c1cc5 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,64 @@ 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 = {
> + 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));
> diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
> index c5b845b..5930a8b 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>
> @@ -155,6 +156,30 @@ static const struct clkops clk_pxa25x_gpio11_ops = {
> .disable = clk_gpio11_disable,
> };
>
> +static void clk_32k_enable(struct clk *clk)
> +{
> + 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 const struct clkops clk_32k_ops = {
> + .enable = clk_32k_enable,
> +};
> +
> /*
> * 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
> @@ -169,6 +194,12 @@ static struct clk pxa25x_hwuart_clk =
> * Please be careful not to disrupt the ordering.
> */
> static struct clk pxa25x_clks[] = {
> + {
> + .name = "CLK_32K",
> + .ops = &clk_32k_ops,
> + .rate = 32768,
> + .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),
> --
> 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] 22+ 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; 22+ 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] 22+ messages in thread
* Re: [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support
2008-07-16 6:55 ` eric miao
@ 2008-07-16 7:09 ` Jaya Kumar
2008-07-16 7:13 ` eric miao
0 siblings, 1 reply; 22+ messages in thread
From: Jaya Kumar @ 2008-07-16 7:09 UTC (permalink / raw)
To: eric miao; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel
On Tue, Jul 15, 2008 at 11:55 PM, eric miao <eric.y.miao@gmail.com> wrote:
> On Sun, Jul 13, 2008 at 9:26 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>> This patch converts gumstix over to the MFP configuration system and adds
>> bluetooth support. Added a CLK_32K clock to enable bluetooth.
>>
>
> The CLK_32KHz is assumed to be enabled always, so it's really not
> necessary to create a struct clk for it. Please remove that from this
> patch.
>
Hi Eric,
Ok, I will take it out.
To clarify, the bulk of gumstix's that have been shipped all come with
U-boot 1.1.4 which does not turn it on by default and so my intention
based on your previous feedback was basically: if CLK_32K not on, then
warn the user, and then turn on the clk32k so that bluetooth works on
such boards.
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] 22+ messages in thread
* Re: [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages
2008-07-13 13:26 ` [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages Jaya Kumar
@ 2008-07-16 7:09 ` eric miao
0 siblings, 0 replies; 22+ messages in thread
From: eric miao @ 2008-07-16 7:09 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:
> This patch converts the printk messages in metronomefb to dev_dbg/err type
> messages.
>
This is always a good thing to do :)
> Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
With the removal of "#define DEBUG 1",
Acked-by: Eric Miao <eric.miao@marvell.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
> +
Don't leave DEBUG in the final patch please.
-------------------------------------------------------------------------
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] 22+ messages in thread
* Re: [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support
2008-07-16 7:09 ` Jaya Kumar
@ 2008-07-16 7:13 ` eric miao
0 siblings, 0 replies; 22+ messages in thread
From: eric miao @ 2008-07-16 7:13 UTC (permalink / raw)
To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel
On Wed, Jul 16, 2008 at 3:09 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> On Tue, Jul 15, 2008 at 11:55 PM, eric miao <eric.y.miao@gmail.com> wrote:
>> On Sun, Jul 13, 2008 at 9:26 PM, Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>>> This patch converts gumstix over to the MFP configuration system and adds
>>> bluetooth support. Added a CLK_32K clock to enable bluetooth.
>>>
>>
>> The CLK_32KHz is assumed to be enabled always, so it's really not
>> necessary to create a struct clk for it. Please remove that from this
>> patch.
>>
>
> Hi Eric,
>
> Ok, I will take it out.
>
> To clarify, the bulk of gumstix's that have been shipped all come with
> U-boot 1.1.4 which does not turn it on by default and so my intention
> based on your previous feedback was basically: if CLK_32K not on, then
> warn the user, and then turn on the clk32k so that bluetooth works on
> such boards.
>
Then we should probably enable the 32K OSCC in the board init code
instead, maybe gumstix_init_32K() in gumstix_init(). Feel free to fire
another patch for this please, and leave enough comments.
> 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] 22+ 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; 22+ 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] 22+ 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; 22+ 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] 22+ 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; 22+ 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] 22+ 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; 22+ 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] 22+ 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; 22+ 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] 22+ 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; 22+ 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] 22+ messages in thread
* [RFC 2.6.26-rc9 3/5] am200epd: convert to shared fb and use gpio api
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
0 siblings, 0 replies; 22+ 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
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..87e9fa8
--- /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 = 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,
+ .lcd_conn = LCD_TYPE_COLOR_TFT | LCD_PCLK_EDGE_FALL |
+ LCD_AC_BIAS_FREQ(24),
+ .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 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] 22+ 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; 22+ 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] 22+ 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; 22+ 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] 22+ 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 ` Jaya Kumar
2008-07-30 2:45 ` Eric Miao
0 siblings, 1 reply; 22+ 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] 22+ 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; 22+ 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] 22+ messages in thread
end of thread, other threads:[~2008-07-30 2:45 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
2008-07-13 13:26 ` [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
2008-07-16 6:55 ` eric miao
2008-07-16 7:09 ` Jaya Kumar
2008-07-16 7:13 ` eric miao
2008-07-13 13:26 ` [RFC 2.6.26-rc9 3/5] am200epd: convert to shared fb and use gpio api Jaya Kumar
2008-07-13 13:26 ` [RFC 2.6.26-rc9 4/5] metronomefb: convert printk to dev_dbg/err messages Jaya Kumar
2008-07-16 7:09 ` eric miao
2008-07-13 13:26 ` [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 3/5] am200epd: convert to shared fb and use gpio api Jaya Kumar
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 3/5] am200epd: convert to shared fb and use gpio api Jaya Kumar
2008-07-30 2:45 ` Eric Miao
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).