* [RFC 2.6.26-rc9 1/5] metronomefb: convert printk to dev_dbg/err messages
2008-07-30 12:51 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v8 Jaya Kumar
@ 2008-07-30 12:51 ` Jaya Kumar
2008-07-30 12:51 ` [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
` (3 subsequent siblings)
4 siblings, 0 replies; 12+ messages in thread
From: Jaya Kumar @ 2008-07-30 12:51 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>
Acked-by: Eric Miao <eric.miao@marvell.com>
---
drivers/video/metronomefb.c | 47 ++++++++++++++++++------------------------
1 files changed, 20 insertions(+), 27 deletions(-)
diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
index cc4c038..7cda4f8 100644
--- a/drivers/video/metronomefb.c
+++ b/drivers/video/metronomefb.c
@@ -40,15 +40,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 +126,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 +139,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 +151,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 +168,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 +193,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 +205,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 +217,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 +252,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 +655,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 +681,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 +697,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
platform_set_drvdata(dev, info);
- printk(KERN_INFO
+ dev_dbg(&dev->dev,
"fb%d: Metronome frame buffer device, using %dK of video"
" memory\n", info->node, videomemorysize >> 10);
--
1.5.3.6
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
^ permalink raw reply related [flat|nested] 12+ messages in thread* [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support
2008-07-30 12:51 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v8 Jaya Kumar
2008-07-30 12:51 ` [RFC 2.6.26-rc9 1/5] metronomefb: convert printk to dev_dbg/err messages Jaya Kumar
@ 2008-07-30 12:51 ` Jaya Kumar
2008-07-30 12:51 ` [RFC 2.6.26-rc9 3/5] pxafb: add shared framebuffer interface Jaya Kumar
` (2 subsequent siblings)
4 siblings, 0 replies; 12+ messages in thread
From: Jaya Kumar @ 2008-07-30 12:51 UTC (permalink / raw)
To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel
This patch converts gumstix over to the MFP configuration system and adds
bluetooth support.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
Acked-by: Eric Miao <eric.miao@marvell.com>
---
arch/arm/mach-pxa/gumstix.c | 100 +++++++++++++++++++++++++++++++++++-------
1 files changed, 83 insertions(+), 17 deletions(-)
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index bdf2397..49b78e7 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -20,8 +20,12 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/setup.h>
#include <asm/memory.h>
@@ -40,7 +44,7 @@
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
+#include <asm/arch/mfp-pxa25x.h>
#include "generic.h"
@@ -85,21 +89,8 @@ static struct platform_device *devices[] __initdata = {
};
#ifdef CONFIG_MMC_PXA
-static struct pxamci_platform_data gumstix_mci_platform_data;
-
-static int gumstix_mci_init(struct device *dev, irq_handler_t detect_int,
- void *data)
-{
- pxa_gpio_mode(GPIO6_MMCCLK_MD);
- pxa_gpio_mode(GPIO53_MMCCLK_MD);
- pxa_gpio_mode(GPIO8_MMCCS0_MD);
-
- return 0;
-}
-
static struct pxamci_platform_data gumstix_mci_platform_data = {
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
- .init = gumstix_mci_init,
};
static void __init gumstix_mmc_init(void)
@@ -109,11 +100,11 @@ static void __init gumstix_mmc_init(void)
#else
static void __init gumstix_mmc_init(void)
{
- printk(KERN_INFO "Gumstix mmc disabled\n");
+ pr_debug("Gumstix mmc disabled\n");
}
#endif
-#ifdef CONFIG_USB_GADGET_PXA2XX
+#ifdef CONFIG_USB_GADGET_PXA25X
static struct pxa2xx_udc_mach_info gumstix_udc_info __initdata = {
.gpio_vbus = GPIO_GUMSTIX_USB_GPIOn,
.gpio_pullup = GPIO_GUMSTIX_USB_GPIOx,
@@ -126,12 +117,87 @@ static void __init gumstix_udc_init(void)
#else
static void gumstix_udc_init(void)
{
- printk(KERN_INFO "Gumstix udc is disabled\n");
+ pr_debug("Gumstix udc is disabled\n");
}
#endif
+#ifdef CONFIG_BT
+/* Normally, the bootloader would have enabled this 32kHz clock but many
+** boards still have u-boot 1.1.4 so we check if it has been turned on and
+** if not, we turn it on with a warning message. */
+static void gumstix_setup_bt_clock(void)
+{
+ int timeout = 500;
+
+ if (!(OSCC & OSCC_OOK))
+ pr_warning("32kHz clock was not on. Bootloader may need to "
+ "be updated\n");
+ else
+ return;
+
+ OSCC |= OSCC_OON;
+ do {
+ if (OSCC & OSCC_OOK)
+ break;
+ udelay(1);
+ } while (--timeout);
+ if (!timeout)
+ pr_err("Failed to start 32kHz clock\n");
+}
+
+static void __init gumstix_bluetooth_init(void)
+{
+ int err;
+
+ gumstix_setup_bt_clock();
+
+ err = gpio_request(GPIO_GUMSTIX_BTRESET, "BTRST");
+ if (err) {
+ pr_err("gumstix: failed request gpio for bluetooth reset\n");
+ return;
+ }
+
+ err = gpio_direction_output(GPIO_GUMSTIX_BTRESET, 1);
+ if (err) {
+ pr_err("gumstix: can't reset bluetooth\n");
+ return;
+ }
+ gpio_set_value(GPIO_GUMSTIX_BTRESET, 0);
+ udelay(100);
+ gpio_set_value(GPIO_GUMSTIX_BTRESET, 1);
+}
+#else
+static void gumstix_bluetooth_init(void)
+{
+ pr_debug("Gumstix Bluetooth is disabled\n");
+}
+#endif
+
+static unsigned long gumstix_pin_config[] __initdata = {
+ GPIO12_32KHz,
+ /* BTUART */
+ GPIO42_HWUART_RXD,
+ GPIO43_HWUART_TXD,
+ GPIO44_HWUART_CTS,
+ GPIO45_HWUART_RTS,
+ /* MMC */
+ GPIO6_MMC_CLK,
+ GPIO53_MMC_CLK,
+ GPIO8_MMC_CS0,
+ /* these are used by AM200EPD */
+ GPIO51_GPIO,
+ GPIO49_GPIO,
+ GPIO48_GPIO,
+ GPIO32_GPIO,
+ GPIO17_GPIO,
+ GPIO16_GPIO,
+};
+
static void __init gumstix_init(void)
{
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(gumstix_pin_config));
+
+ gumstix_bluetooth_init();
gumstix_udc_init();
gumstix_mmc_init();
(void) platform_add_devices(devices, ARRAY_SIZE(devices));
--
1.5.3.6
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
^ permalink raw reply related [flat|nested] 12+ messages in thread* [RFC 2.6.26-rc9 3/5] pxafb: add shared framebuffer interface
2008-07-30 12:51 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v8 Jaya Kumar
2008-07-30 12:51 ` [RFC 2.6.26-rc9 1/5] metronomefb: convert printk to dev_dbg/err messages Jaya Kumar
2008-07-30 12:51 ` [RFC 2.6.26-rc9 2/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
@ 2008-07-30 12:51 ` Jaya Kumar
2008-07-31 15:28 ` Krzysztof Helt
2008-07-30 12:51 ` [RFC 2.6.26-rc9 4/5] am200epd: convert to shared fb and use gpio api Jaya Kumar
2008-07-30 12:51 ` [RFC 2.6.26-rc9 5/5] metronomefb: changes to use separate framebuffer Jaya Kumar
4 siblings, 1 reply; 12+ messages in thread
From: Jaya Kumar @ 2008-07-30 12:51 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 extra_video_mem entry so that a driver can tell pxafb of its
additional needs.
- adding share_video_mem/unshare_video_mem callbacks to notify the secondary
driver of the framebuffer address, to allow refcounting, and to cleanup on
completion.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
drivers/video/pxafb.c | 31 ++++++++++++++++++++++++++-----
include/asm-arm/arch-pxa/pxafb.h | 7 +++++++
2 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index bb25143..f799c52 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 */
@@ -870,6 +872,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)) {
@@ -1304,14 +1307,17 @@ static int pxafb_resume(struct platform_device *dev)
* cache. Once this area is remapped, all virtual memory
* access to the video memory should occur at the new region.
*/
-static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
+static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi,
+ struct pxafb_mach_info *inf)
{
+ int ret;
/*
* We reserve one page for the palette, plus the size
* of the framebuffer.
*/
fbi->video_offset = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
- fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset);
+ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset +
+ inf->extra_video_mem);
fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
&fbi->map_dma, GFP_KERNEL);
@@ -1340,6 +1346,13 @@ static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
fbi->n_smart_cmds = 0;
#endif
+ if (inf->share_video_mem) {
+ ret = inf->share_video_mem(fbi->fb.screen_base,
+ fbi->screen_dma, pxafb_driver.driver.owner,
+ inf->extra_data);
+ if (ret)
+ return ret;
+ }
}
return fbi->map_cpu ? 0 : -ENOMEM;
@@ -1761,10 +1774,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 +1851,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 +1873,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 +1890,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..1ff9281 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -139,9 +139,16 @@ struct pxafb_mach_info {
* All other bits in LCCR4 should be left alone.
*/
u_int lccr4;
+ /* size of extra mem needed for secondary driver */
+ unsigned int extra_video_mem;
+ void *extra_data; /* extra data for secondary */
void (*pxafb_backlight_power)(int);
void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
void (*smart_update)(struct fb_info *);
+ /* share_video_mem allows client drivers to get our framebuffer */
+ int (*share_video_mem)(char __iomem *, dma_addr_t, struct module *,
+ void *);
+ void (*unshare_video_mem)(void *);
};
void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
void set_pxa_fb_parent(struct device *parent_dev);
--
1.5.3.6
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [RFC 2.6.26-rc9 3/5] pxafb: add shared framebuffer interface
2008-07-30 12:51 ` [RFC 2.6.26-rc9 3/5] pxafb: add shared framebuffer interface Jaya Kumar
@ 2008-07-31 15:28 ` Krzysztof Helt
2008-08-02 12:06 ` Jaya Kumar
0 siblings, 1 reply; 12+ messages in thread
From: Krzysztof Helt @ 2008-07-31 15:28 UTC (permalink / raw)
To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel
On Wed, 30 Jul 2008 08:51:07 -0400
Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> These changes are to make it possible for a secondary driver to share the
> pxafb framebuffer. The changes include:
> - adding 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>
> ---
> diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
> index bb25143..f799c52 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;
> +
Not needed - see below
(...)
> -static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
> +static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi,
> + struct pxafb_mach_info *inf)
> {
> + int ret;
> /*
> * We reserve one page for the palette, plus the size
> * of the framebuffer.
> */
> fbi->video_offset = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
> - fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset);
> + fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset +
> + inf->extra_video_mem);
> fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
> &fbi->map_dma, GFP_KERNEL);
>
> @@ -1340,6 +1346,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,
You should use here either THIS_MODULE or runtime information
from fbi->fb.device.driver.owner.
> + inf->extra_data);
> + if (ret)
> + return ret;
> + }
> }
>
The rest of the patch is ok.
Regards,
Krzysztof
----------------------------------------------------------------------
Partyjka w Chinczyka?
Graj >>> http://link.interia.pl/f1e67
-------------------------------------------------------------------------
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] 12+ messages in thread* Re: [RFC 2.6.26-rc9 3/5] pxafb: add shared framebuffer interface
2008-07-31 15:28 ` Krzysztof Helt
@ 2008-08-02 12:06 ` Jaya Kumar
0 siblings, 0 replies; 12+ messages in thread
From: Jaya Kumar @ 2008-08-02 12:06 UTC (permalink / raw)
To: Krzysztof Helt; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel
On Thu, Jul 31, 2008 at 11:28 AM, Krzysztof Helt <krzysztof.h1@poczta.fm> wrote:
> On Wed, 30 Jul 2008 08:51:07 -0400
> Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>
>> These changes are to make it possible for a secondary driver to share the
>> pxafb framebuffer. The changes include:
>> - adding 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.
>>
Hi Krzysztof,
Thanks for the review. I have a feeling though that I have made a
design mistake. My approach has been too specific to pxafb and I think
the addition of callbacks to mach_pxa_info is not something that will
be acked. My apologies for that. So I'll go and take some time to
rethink my design and hopefully come up with something cleaner and
more generic. I have an idea of using fb notifiers which I think will
allow this all to work without needing any custom changes to pxafb.
I'm sorry for having taken up everyones time with the previous
approach.
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] 12+ messages in thread
* [RFC 2.6.26-rc9 4/5] am200epd: convert to shared fb and use gpio api
2008-07-30 12:51 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v8 Jaya Kumar
` (2 preceding siblings ...)
2008-07-30 12:51 ` [RFC 2.6.26-rc9 3/5] pxafb: add shared framebuffer interface Jaya Kumar
@ 2008-07-30 12:51 ` Jaya Kumar
2008-07-31 15:46 ` Krzysztof Helt
2008-07-30 12:51 ` [RFC 2.6.26-rc9 5/5] metronomefb: changes to use separate framebuffer Jaya Kumar
4 siblings, 1 reply; 12+ messages in thread
From: Jaya Kumar @ 2008-07-30 12:51 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 | 323 ++++++++++++++++++++++++++++++++++++++++++
drivers/video/Kconfig | 13 --
drivers/video/Makefile | 1 -
drivers/video/am200epd.c | 295 --------------------------------------
6 files changed, 327 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..f5bb902
--- /dev/null
+++ b/arch/arm/mach-pxa/am200epd.c
@@ -0,0 +1,323 @@
+/*
+ * 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/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/2,
+ .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/2,
+ .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/2,
+ .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),
+};
+
+/* 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 = PAGE_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] 12+ messages in thread* Re: [RFC 2.6.26-rc9 4/5] am200epd: convert to shared fb and use gpio api
2008-07-30 12:51 ` [RFC 2.6.26-rc9 4/5] am200epd: convert to shared fb and use gpio api Jaya Kumar
@ 2008-07-31 15:46 ` Krzysztof Helt
2008-08-02 13:32 ` Jaya Kumar
0 siblings, 1 reply; 12+ messages in thread
From: Krzysztof Helt @ 2008-07-31 15:46 UTC (permalink / raw)
To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel
On Wed, 30 Jul 2008 08:51:08 -0400
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.
>
> 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 | 323 ++++++++++++++++++++++++++++++++++++++++++
> drivers/video/Kconfig | 13 --
> drivers/video/Makefile | 1 -
> drivers/video/am200epd.c | 295 --------------------------------------
> 6 files changed, 327 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..f5bb902
> --- /dev/null
> +++ b/arch/arm/mach-pxa/am200epd.c
> @@ -0,0 +1,323 @@
> +/*
> + * 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/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/2,
> + .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/2,
> + .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/2,
> + .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),
> +};
> +
> +/* 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;
IMO, these variables should be part of metronomefb or am200_device platform data.
The former is better. Use the data pointer in the function below to pass the metronomefb
pointer.
> +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 = PAGE_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)
> +{
You may pass metronomefb_par* here to avoid one reference.
> + 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;
> +}
You may drop the ret variable here.
> +
> +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);
The second parameter is instance id. Probably 0 is better here.
> + 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();
Should the am200 be set up in case of error?
> +
> + 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");
Regards,
Krzysztof
----------------------------------------------------------------------
Od puzzla do przepisu! Zagraj i wygraj!
Kliknij >>> http://link.interia.pl/f1eb2
-------------------------------------------------------------------------
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] 12+ messages in thread* Re: [RFC 2.6.26-rc9 4/5] am200epd: convert to shared fb and use gpio api
2008-07-31 15:46 ` Krzysztof Helt
@ 2008-08-02 13:32 ` Jaya Kumar
2008-08-03 14:29 ` Krzysztof Helt
0 siblings, 1 reply; 12+ messages in thread
From: Jaya Kumar @ 2008-08-02 13:32 UTC (permalink / raw)
To: Krzysztof Helt; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel
On Thu, Jul 31, 2008 at 11:46 AM, Krzysztof Helt <krzysztof.h1@poczta.fm> wrote:
> On Wed, 30 Jul 2008 08:51:08 -0400
> Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>
>> +
>> +static irqreturn_t am200_handle_irq(int irq, void *dev_id)
>> +{
>
> You may pass metronomefb_par* here to avoid one reference.
Agreed.
>> + ret = wait_event_interruptible_timeout(par->waitq,
>> + gpio_get_value(RDY_GPIO_PIN), HZ);
>> + return ret;
>> +}
>
> You may drop the ret variable here.
Agreed.
>> + am200_device = platform_device_alloc("metronomefb", -1);
>
> The second parameter is instance id. Probably 0 is better here.
I would like to mark it as single instance only, -1. I see in platform.c:
if (pdev->id != -1)
snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name,
pdev->id);
else
strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
>> + am200_presetup_fb();
>
> Should the am200 be set up in case of error?
Agreed, will fix the error.
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] 12+ messages in thread* Re: [RFC 2.6.26-rc9 4/5] am200epd: convert to shared fb and use gpio api
2008-08-02 13:32 ` Jaya Kumar
@ 2008-08-03 14:29 ` Krzysztof Helt
0 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Helt @ 2008-08-03 14:29 UTC (permalink / raw)
To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel
On Sat, 2 Aug 2008 09:32:13 -0400
"Jaya Kumar" <jayakumar.lkml@gmail.com> wrote:
> On Thu, Jul 31, 2008 at 11:46 AM, Krzysztof Helt <krzysztof.h1@poczta.fm> wrote:
> > On Wed, 30 Jul 2008 08:51:08 -0400
> > Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> >
>
> >> + am200_device = platform_device_alloc("metronomefb", -1);
> >
> > The second parameter is instance id. Probably 0 is better here.
>
> I would like to mark it as single instance only, -1. I see in platform.c:
>
> if (pdev->id != -1)
> snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name,
> pdev->id);
> else
> strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
>
>
Ok.
Regards,
Krzysztof
----------------------------------------------------------------------
Tanie rozmowy!
Sprawdz >>> http://link.interia.pl/f1e91
-------------------------------------------------------------------------
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] 12+ messages in thread
* [RFC 2.6.26-rc9 5/5] metronomefb: changes to use separate framebuffer
2008-07-30 12:51 [RFC 2.6.26-rc9 0/5] am200epd, pxafb, metronomefb changes v8 Jaya Kumar
` (3 preceding siblings ...)
2008-07-30 12:51 ` [RFC 2.6.26-rc9 4/5] am200epd: convert to shared fb and use gpio api Jaya Kumar
@ 2008-07-30 12:51 ` Jaya Kumar
2008-08-01 20:47 ` Krzysztof Helt
4 siblings, 1 reply; 12+ messages in thread
From: Jaya Kumar @ 2008-07-30 12:51 UTC (permalink / raw)
To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel
These changes are used in order to support the use of a separate
framebuffer provided by the platform device driver. Other changes
are cleanup to error handling and order of release.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
drivers/video/Kconfig | 18 +++-
drivers/video/metronomefb.c | 227 +++++++++++++++++++++++++------------------
include/video/metronomefb.h | 22 ++---
3 files changed, 153 insertions(+), 114 deletions(-)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 752907d..dda770c 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -172,11 +172,6 @@ config FB_DEFERRED_IO
bool
depends on FB
-config FB_METRONOME
- tristate
- depends on FB
- depends on FB_DEFERRED_IO
-
config FB_HECUBA
tristate
depends on FB
@@ -1975,6 +1970,19 @@ config XEN_FBDEV_FRONTEND
frame buffer driver. It communicates with a back-end
in another domain.
+config FB_METRONOME
+ tristate "E-Ink Metronome/8track controller support"
+ depends on FB
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
+ help
+ This driver implements support for the E-Ink Metronome
+ controller. The pre-release name for this device was 8track
+ and could also have been called by some vendors as PVI-nnnn.
+
source "drivers/video/omap/Kconfig"
source "drivers/video/backlight/Kconfig"
diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
index 7cda4f8..0222044 100644
--- a/drivers/video/metronomefb.c
+++ b/drivers/video/metronomefb.c
@@ -44,16 +44,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,
},
};
@@ -125,7 +168,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)
{
@@ -142,9 +184,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;
}
@@ -328,44 +373,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);
@@ -401,12 +419,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)
@@ -423,16 +438,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);
}
@@ -567,8 +582,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;
@@ -579,39 +597,67 @@ 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;
+ /* we need to add a spare page because our csum caching scheme walks
+ * to the end of the page */
+ videomemorysize = PAGE_SIZE + (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
@@ -621,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
@@ -656,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,
@@ -664,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)
@@ -682,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 */
@@ -705,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;
}
@@ -726,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;
@@ -759,6 +795,9 @@ static void __exit metronomefb_exit(void)
platform_driver_unregister(&metronomefb_driver);
}
+module_param(user_wfm_size, uint, 0);
+MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size");
+
module_init(metronomefb_init);
module_exit(metronomefb_exit);
diff --git a/include/video/metronomefb.h b/include/video/metronomefb.h
index dab04b4..79444cd 100644
--- a/include/video/metronomefb.h
+++ b/include/video/metronomefb.h
@@ -12,14 +12,6 @@
#ifndef _LINUX_METRONOMEFB_H_
#define _LINUX_METRONOMEFB_H_
-/* address and control descriptors used by metronome controller */
-struct metromem_desc {
- u32 mFDADR0;
- u32 mFSADR0;
- u32 mFIDR0;
- u32 mLDCMD0;
-};
-
/* command structure used by metronome controller */
struct metromem_cmd {
u16 opcode;
@@ -30,33 +22,33 @@ struct metromem_cmd {
/* struct used by metronome. board specific stuff comes from *board */
struct metronomefb_par {
unsigned char *metromem;
- struct metromem_desc *metromem_desc;
struct metromem_cmd *metromem_cmd;
unsigned char *metromem_wfm;
unsigned char *metromem_img;
u16 *metromem_img_csum;
u16 *csum_table;
- int metromemsize;
dma_addr_t metromem_dma;
- dma_addr_t metromem_desc_dma;
struct fb_info *info;
struct metronome_board *board;
wait_queue_head_t waitq;
u8 frame_count;
+ int extra_size;
+ int dt;
};
/* board specific routines */
struct metronome_board {
struct module *owner;
- void (*free_irq)(struct fb_info *);
- void (*init_gpio_regs)(struct metronomefb_par *);
- void (*init_lcdc_regs)(struct metronomefb_par *);
- void (*post_dma_setup)(struct metronomefb_par *);
+ struct module *fbmaster;
void (*set_rst)(struct metronomefb_par *, int);
void (*set_stdby)(struct metronomefb_par *, int);
+ void (*cleanup)(struct metronomefb_par *);
int (*met_wait_event)(struct metronomefb_par *);
int (*met_wait_event_intr)(struct metronomefb_par *);
int (*setup_irq)(struct fb_info *);
+ int (*setup_fb)(struct metronomefb_par *);
+ int (*setup_io)(struct metronomefb_par *);
+ int (*get_panel_type)(void);
};
#endif
--
1.5.3.6
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [RFC 2.6.26-rc9 5/5] metronomefb: changes to use separate framebuffer
2008-07-30 12:51 ` [RFC 2.6.26-rc9 5/5] metronomefb: changes to use separate framebuffer Jaya Kumar
@ 2008-08-01 20:47 ` Krzysztof Helt
0 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Helt @ 2008-08-01 20:47 UTC (permalink / raw)
To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel
On Wed, 30 Jul 2008 08:51:09 -0400
Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> These changes are used in order to support the use of a separate
> framebuffer provided by the platform device driver. Other changes
> are cleanup to error handling and order of release.
>
> Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
> ---
> drivers/video/Kconfig | 18 +++-
> drivers/video/metronomefb.c | 227 +++++++++++++++++++++++++------------------
> include/video/metronomefb.h | 22 ++---
> 3 files changed, 153 insertions(+), 114 deletions(-)
>
Acked-by: Krzysztof Helt <krzysztof.h1@wp.pl>
----------------------------------------------------------------------
W kosciele tez zdarzaja sie wpadki!
Smieszny filmik >>> http://link.interia.pl/f1e61
-------------------------------------------------------------------------
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] 12+ messages in thread