* [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes
@ 2008-05-30 12:28 Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 1/5] pxafb: module unloading support Jaya Kumar
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-30 12:28 UTC (permalink / raw)
To: ymiao3; +Cc: linux-fbdev-devel, linux-arm-kernel
Hi Eric, arm and fbdev friends,
This RFC consists of five patches intended to improve the condition of the
am200epd devkit support. The am200epd devkit contains a gumstix (pxa255) and
a carrier board (am200epd or Lyre), and a metronome display controller.
Previously, there was a drivers/video/am200epd driver that manipulated pxa
LCDC registers and GPSR/GPLR registers directly. That was clearly wrong so I
have removed it and written a new mach-pxa am200epd support driver. This
driver interfaces with pxafb through a set of callbacks to share/unshare
pxafb's framebuffer and achieve the same functionality without manipulating
any pxa registers directly. The patches are split as follows:
1 pxafb: module unloading support
2 pxafb: add shared framebuffer interface
3 gumstix: conversion to MFP support and add bluetooth support
4 am200epd: remove am200epd platform device driver
5 am200epd: add mach-pxa support for am200epd
I would be grateful for any feedback and advice.
Thanks,
jaya
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC 2.6.26-rc3 1/5] pxafb: module unloading support
2008-05-30 12:28 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes Jaya Kumar
@ 2008-05-30 12:28 ` Jaya Kumar
2008-05-30 17:04 ` Krzysztof Helt
2008-05-30 12:28 ` [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface Jaya Kumar
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Jaya Kumar @ 2008-05-30 12:28 UTC (permalink / raw)
To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel
This patch to pxafb adds:
- exit and remove handlers
- changes to use __devinit/exit for probe functions and __init/exit for
init/exit functions
- set g_options to initdata since it is only accessed from pxafb_init
in order to enable module loading/unloading of pxafb.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
drivers/video/pxafb.c | 52 ++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 43 insertions(+), 9 deletions(-)
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 274bc93..a4bb733 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1246,7 +1246,7 @@ static int pxafb_resume(struct platform_device *dev)
* cache. Once this area is remapped, all virtual memory
* access to the video memory should occur at the new region.
*/
-static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
+static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
{
/*
* We reserve one page for the palette, plus the size
@@ -1346,7 +1346,7 @@ decode_mode:
pxafb_decode_mode_info(fbi, inf->modes, inf->num_modes);
}
-static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
+static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
{
struct pxafb_info *fbi;
void *addr;
@@ -1408,7 +1408,7 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
}
#ifdef CONFIG_FB_PXA_PARAMETERS
-static int __init parse_opt_mode(struct device *dev, const char *this_opt)
+static int __devinit parse_opt_mode(struct device *dev, const char *this_opt)
{
struct pxafb_mach_info *inf = dev->platform_data;
@@ -1467,7 +1467,7 @@ done:
return 0;
}
-static int __init parse_opt(struct device *dev, char *this_opt)
+static int __devinit parse_opt(struct device *dev, char *this_opt)
{
struct pxafb_mach_info *inf = dev->platform_data;
struct pxafb_mode_info *mode = &inf->modes[0];
@@ -1565,7 +1565,7 @@ static int __init parse_opt(struct device *dev, char *this_opt)
return 0;
}
-static int __init pxafb_parse_options(struct device *dev, char *options)
+static int __devinit pxafb_parse_options(struct device *dev, char *options)
{
char *this_opt;
int ret;
@@ -1584,10 +1584,10 @@ static int __init pxafb_parse_options(struct device *dev, char *options)
return 0;
}
-static char g_options[256] __devinitdata = "";
+static char g_options[256] __initdata = "";
#ifndef CONFIG_MODULES
-static int __devinit pxafb_setup_options(void)
+static int __init pxafb_setup_options(void)
{
char *options = NULL;
@@ -1611,7 +1611,7 @@ MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
#define pxafb_setup_options() (0)
#endif
-static int __init pxafb_probe(struct platform_device *dev)
+static int __devinit pxafb_probe(struct platform_device *dev)
{
struct pxafb_info *fbi;
struct pxafb_mach_info *inf;
@@ -1776,16 +1776,44 @@ failed:
return ret;
}
+static int __devexit pxafb_remove(struct platform_device *dev)
+{
+ struct pxafb_info *fbi = platform_get_drvdata(dev);
+ struct resource *r;
+ int irq;
+
+ if (fbi) {
+ struct fb_info *info = &fbi->fb;
+
+ irq = platform_get_irq(dev, 0);
+ free_irq(irq, fbi);
+
+ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ release_mem_region(r->start, r->end - r->start + 1);
+
+ iounmap(fbi->mmio_base);
+
+ dma_free_writecombine(&dev->dev, fbi->map_size,
+ fbi->map_cpu, fbi->map_dma);
+ fb_dealloc_cmap(&info->cmap);
+ unregister_framebuffer(info);
+ kfree(fbi);
+ }
+ return 0;
+}
+
static struct platform_driver pxafb_driver = {
.probe = pxafb_probe,
+ .remove = pxafb_remove,
.suspend = pxafb_suspend,
.resume = pxafb_resume,
.driver = {
+ .owner = THIS_MODULE,
.name = "pxa2xx-fb",
},
};
-static int __devinit pxafb_init(void)
+static int __init pxafb_init(void)
{
if (pxafb_setup_options())
return -EINVAL;
@@ -1793,7 +1821,13 @@ static int __devinit pxafb_init(void)
return platform_driver_register(&pxafb_driver);
}
+static void __exit pxafb_exit(void)
+{
+ platform_driver_unregister(&pxafb_driver);
+}
+
module_init(pxafb_init);
+module_exit(pxafb_exit);
MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
MODULE_LICENSE("GPL");
--
1.5.3.6
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface
2008-05-30 12:28 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 1/5] pxafb: module unloading support Jaya Kumar
@ 2008-05-30 12:28 ` Jaya Kumar
2008-05-30 17:10 ` Krzysztof Helt
2008-05-30 12:28 ` [RFC 2.6.26-rc3 3/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Jaya Kumar @ 2008-05-30 12:28 UTC (permalink / raw)
To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel
These changes are to make it possible for a secondary driver to share the
pxafb framebuffer. The changes include:
- adding clkdev entry in pxafb_mach_info so that a driver can pass in the
correct struct device owner for the LCDCLK.
- adding custom_xfer_div entry so that a driver can have custom sized
transfers. For example, the metronome controller uses 16 bit AMLCD
transfers but actually has 3 bit pixels in 8 bit containers.
- adding extra_video_mem entry so that a driver can tell pxafb of its
additional needs.
- adding share_video_mem/unshare_video_mem callbacks to notify the secondary
driver of the framebuffer address, to allow refcounting, and to cleanup on
completion.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
arch/arm/mach-pxa/devices.c | 2 +
drivers/video/pxafb.c | 46 ++++++++++++++++++++++++++++++++-----
include/asm-arm/arch-pxa/pxafb.h | 9 +++++++
3 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index d6c05b6..b72b73a 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -130,6 +130,8 @@ struct platform_device pxa_device_fb = {
void __init set_pxa_fb_info(struct pxafb_mach_info *info)
{
+ if (!info->clkdev)
+ info->clkdev = &pxa_device_fb.dev;
pxa_register_device(&pxa_device_fb, info);
}
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index a4bb733..2a574ad 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -57,6 +57,8 @@
*/
#define DEBUG_VAR 1
+static struct platform_driver pxafb_driver;
+
#include "pxafb.h"
/* Bits which should not be set in machine configuration structures */
@@ -775,10 +777,15 @@ int pxafb_smart_flush(struct fb_info *info)
static void setup_parallel_timing(struct pxafb_info *fbi,
struct fb_var_screeninfo *var)
{
+ struct pxafb_mach_info *inf = fbi->dev->platform_data;
unsigned int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
+ unsigned int pix_per_line = var->xres;
+
+ if (inf->custom_xfer_div)
+ pix_per_line /= inf->custom_xfer_div;
fbi->reg_lccr1 =
- LCCR1_DisWdth(var->xres) +
+ LCCR1_DisWdth(pix_per_line) +
LCCR1_HorSnchWdth(var->hsync_len) +
LCCR1_BegLnDel(var->left_margin) +
LCCR1_EndLnDel(var->right_margin);
@@ -819,6 +826,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
{
u_long flags;
size_t nbytes;
+ struct pxafb_mach_info *inf = fbi->dev->platform_data;
#if DEBUG_VAR
if (!(fbi->lccr0 & LCCR0_LCDT)) {
@@ -878,6 +886,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
fbi->reg_lccr3 |= pxafb_bpp_to_lccr3(var);
nbytes = var->yres * fbi->fb.fix.line_length;
+ if (inf->custom_xfer_div)
+ nbytes /= inf->custom_xfer_div;
if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual) {
nbytes = nbytes / 2;
@@ -1246,14 +1256,17 @@ static int pxafb_resume(struct platform_device *dev)
* cache. Once this area is remapped, all virtual memory
* access to the video memory should occur at the new region.
*/
-static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
+static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi,
+ struct pxafb_mach_info *inf)
{
+ int ret;
/*
* We reserve one page for the palette, plus the size
* of the framebuffer.
*/
fbi->video_offset = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
- fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset);
+ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset +
+ inf->extra_video_mem);
fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
&fbi->map_dma, GFP_KERNEL);
@@ -1280,6 +1293,13 @@ static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
fbi->n_smart_cmds = 0;
#endif
+ if (inf->share_video_mem) {
+ ret = inf->share_video_mem(fbi->fb.screen_base,
+ fbi->screen_dma, pxafb_driver.driver.owner,
+ inf->extra_data);
+ if (ret)
+ return ret;
+ }
}
return fbi->map_cpu ? 0 : -ENOMEM;
@@ -1290,6 +1310,7 @@ static void pxafb_decode_mode_info(struct pxafb_info *fbi,
unsigned int num_modes)
{
unsigned int i, smemlen;
+ struct pxafb_mach_info *inf = fbi->dev->platform_data;
pxafb_setmode(&fbi->fb.var, &modes[0]);
@@ -1297,6 +1318,8 @@ static void pxafb_decode_mode_info(struct pxafb_info *fbi,
smemlen = modes[i].xres * modes[i].yres * modes[i].bpp / 8;
if (smemlen > fbi->fb.fix.smem_len)
fbi->fb.fix.smem_len = smemlen;
+ if (inf->custom_xfer_div)
+ smemlen /= inf->custom_xfer_div;
}
}
@@ -1360,7 +1383,7 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
memset(fbi, 0, sizeof(struct pxafb_info));
fbi->dev = dev;
- fbi->clk = clk_get(dev, "LCDCLK");
+ fbi->clk = clk_get(inf->clkdev, "LCDCLK");
if (IS_ERR(fbi->clk)) {
kfree(fbi);
return NULL;
@@ -1701,8 +1724,12 @@ static int __devinit pxafb_probe(struct platform_device *dev)
}
/* Initialize video memory */
- ret = pxafb_map_video_memory(fbi);
- if (ret) {
+ ret = pxafb_map_video_memory(fbi, inf);
+ if (ret == -ENODEV) {
+ dev_err(&dev->dev, "Failed device binding: %d\n", ret);
+ ret = -ENODEV;
+ goto failed_free_mem;
+ } else if (ret) {
dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret);
ret = -ENOMEM;
goto failed_free_io;
@@ -1770,6 +1797,8 @@ failed_free_io:
failed_free_mem:
dma_free_writecombine(&dev->dev, fbi->map_size,
fbi->map_cpu, fbi->map_dma);
+ if (inf->unshare_video_mem)
+ inf->unshare_video_mem(inf->extra_data);
failed:
platform_set_drvdata(dev, NULL);
kfree(fbi);
@@ -1783,6 +1812,7 @@ static int __devexit pxafb_remove(struct platform_device *dev)
int irq;
if (fbi) {
+ struct pxafb_mach_info *inf;
struct fb_info *info = &fbi->fb;
irq = platform_get_irq(dev, 0);
@@ -1792,7 +1822,9 @@ static int __devexit pxafb_remove(struct platform_device *dev)
release_mem_region(r->start, r->end - r->start + 1);
iounmap(fbi->mmio_base);
-
+ inf = dev->dev.platform_data;
+ if (inf->unshare_video_mem)
+ inf->unshare_video_mem(inf->extra_data);
dma_free_writecombine(&dev->dev, fbi->map_size,
fbi->map_cpu, fbi->map_dma);
fb_dealloc_cmap(&info->cmap);
diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
index bbd2239..c703633 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -138,9 +138,18 @@ struct pxafb_mach_info {
* All other bits in LCCR4 should be left alone.
*/
u_int lccr4;
+ unsigned int custom_xfer_div; /* divides the pixel transfer */
+ /* size of extra mem needed for secondary driver */
+ unsigned int extra_video_mem;
+ void *extra_data; /* extra data for secondary */
void (*pxafb_backlight_power)(int);
void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
void (*smart_update)(struct fb_info *);
+ /* share_video_mem allows client drivers to get our framebuffer */
+ int (*share_video_mem)(unsigned char *, dma_addr_t, struct module *,
+ void *);
+ void (*unshare_video_mem)(void *);
+ struct device *clkdev;
};
void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
void set_pxa_fb_parent(struct device *parent_dev);
--
1.5.3.6
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC 2.6.26-rc3 3/5] gumstix: conversion to MFP support and add bluetooth support
2008-05-30 12:28 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 1/5] pxafb: module unloading support Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface Jaya Kumar
@ 2008-05-30 12:28 ` Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 4/5] am200epd: remove am200epd platform device driver Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 5/5] am200epd: add mach-pxa support for am200epd Jaya Kumar
4 siblings, 0 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-30 12:28 UTC (permalink / raw)
To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel
This patch converts gumstix over to the MFP configuration system and adds
bluetooth support. Added a CLK_32K clock to enable bluetooth.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
arch/arm/mach-pxa/gumstix.c | 79 ++++++++++++++++++++++++++-------
arch/arm/mach-pxa/pxa25x.c | 31 +++++++++++++
include/asm-arm/arch-pxa/mfp-pxa25x.h | 1 +
3 files changed, 95 insertions(+), 16 deletions(-)
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index bdf2397..3e0a962 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -20,8 +20,12 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/setup.h>
#include <asm/memory.h>
@@ -40,7 +44,7 @@
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
+#include <asm/arch/mfp-pxa25x.h>
#include "generic.h"
@@ -85,21 +89,8 @@ static struct platform_device *devices[] __initdata = {
};
#ifdef CONFIG_MMC_PXA
-static struct pxamci_platform_data gumstix_mci_platform_data;
-
-static int gumstix_mci_init(struct device *dev, irq_handler_t detect_int,
- void *data)
-{
- pxa_gpio_mode(GPIO6_MMCCLK_MD);
- pxa_gpio_mode(GPIO53_MMCCLK_MD);
- pxa_gpio_mode(GPIO8_MMCCS0_MD);
-
- return 0;
-}
-
static struct pxamci_platform_data gumstix_mci_platform_data = {
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
- .init = gumstix_mci_init,
};
static void __init gumstix_mmc_init(void)
@@ -109,7 +100,7 @@ static void __init gumstix_mmc_init(void)
#else
static void __init gumstix_mmc_init(void)
{
- printk(KERN_INFO "Gumstix mmc disabled\n");
+ pr_debug("Gumstix mmc disabled\n");
}
#endif
@@ -126,12 +117,68 @@ static void __init gumstix_udc_init(void)
#else
static void gumstix_udc_init(void)
{
- printk(KERN_INFO "Gumstix udc is disabled\n");
+ pr_debug("Gumstix udc is disabled\n");
+}
+#endif
+
+#ifdef CONFIG_BT
+static void __init gumstix_bluetooth_init(void)
+{
+ int err;
+ struct clk *clk32k;
+
+ clk32k = clk_get(NULL, "CLK_32K");
+ if (IS_ERR(clk32k)) {
+ pr_err("gumstix: failed to find 32kHz clock\n");
+ return;
+ }
+ clk_enable(clk32k);
+
+ err = gpio_direction_output(GPIO_GUMSTIX_BTRESET, 1);
+ if (err) {
+ pr_err("gumstix: can't reset bluetooth\n");
+ return;
+ }
+ gpio_set_value(GPIO_GUMSTIX_BTRESET, 0);
+ udelay(100);
+ gpio_set_value(GPIO_GUMSTIX_BTRESET, 1);
+}
+#else
+static void gumstix_bluetooth_init(void)
+{
+ pr_debug("Gumstix Bluetooth is disabled\n");
}
#endif
+static unsigned long gumstix_pin_config[] __initdata = {
+#ifdef CONFIG_BT
+ GPIO12_32KHz,
+ /* BTUART */
+ GPIO42_HWUART_RXD,
+ GPIO43_HWUART_TXD,
+ GPIO44_HWUART_CTS,
+ GPIO45_HWUART_RTSL,
+#endif
+#ifdef CONFIG_MMC_PXA
+ /* MMC */
+ GPIO6_MMC_CLK,
+ GPIO53_MMC_CLK,
+ GPIO8_MMC_CS0,
+#endif
+ /* these are used by AM200EPD */
+ GPIO51_GPIO,
+ GPIO49_GPIO,
+ GPIO48_GPIO,
+ GPIO32_GPIO,
+ GPIO17_GPIO,
+ GPIO16_GPIO,
+};
+
static void __init gumstix_init(void)
{
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(gumstix_pin_config));
+
+ gumstix_bluetooth_init();
gumstix_udc_init();
gumstix_mmc_init();
(void) platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index e5b417d..1ffe773 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -22,6 +22,7 @@
#include <linux/platform_device.h>
#include <linux/suspend.h>
#include <linux/sysdev.h>
+#include <linux/delay.h>
#include <asm/hardware.h>
#include <asm/arch/irqs.h>
@@ -108,6 +109,30 @@ static const struct clkops clk_pxa25x_lcd_ops = {
.getrate = clk_pxa25x_lcd_getrate,
};
+static void clk_32k_enable(struct clk *clk)
+{
+ int timeout = 500;
+
+ OSCC |= OSCC_OON;
+ do {
+ if (OSCC & OSCC_OOK)
+ break;
+ udelay(1);
+ } while (--timeout);
+ if (!timeout)
+ pr_err("Failed to start 32kHz clock\n");
+}
+
+static void clk_32k_disable(struct clk *clk)
+{
+ OSCC &= ~OSCC_OON;
+}
+
+static const struct clkops clk_32k_ops = {
+ .enable = clk_32k_enable,
+ .disable = clk_32k_disable,
+};
+
/*
* 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz)
* 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
@@ -118,6 +143,12 @@ static struct clk pxa25x_hwuart_clk =
;
static struct clk pxa25x_clks[] = {
+ {
+ .name = "CLK_32K",
+ .ops = &clk_32k_ops,
+ .rate = 32000,
+ .delay = 70,
+ },
INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev),
INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev),
INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
diff --git a/include/asm-arm/arch-pxa/mfp-pxa25x.h b/include/asm-arm/arch-pxa/mfp-pxa25x.h
index 0499323..6c82a74 100644
--- a/include/asm-arm/arch-pxa/mfp-pxa25x.h
+++ b/include/asm-arm/arch-pxa/mfp-pxa25x.h
@@ -79,6 +79,7 @@
#define GPIO43_HWUART_TXD MFP_CFG_OUT(GPIO43, AF3, DRIVE_HIGH)
#define GPIO44_HWUART_CTS MFP_CFG_IN(GPIO44, AF3)
#define GPIO45_HWUART_RTS MFP_CFG_OUT(GPIO45, AF3, DRIVE_HIGH)
+#define GPIO45_HWUART_RTSL MFP_CFG_OUT(GPIO45, AF3, DRIVE_LOW)
#define GPIO48_HWUART_TXD MFP_CFG_OUT(GPIO48, AF1, DRIVE_HIGH)
#define GPIO49_HWUART_RXD MFP_CFG_IN(GPIO49, AF1)
#define GPIO50_HWUART_CTS MFP_CFG_IN(GPIO50, AF1)
--
1.5.3.6
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC 2.6.26-rc3 4/5] am200epd: remove am200epd platform device driver
2008-05-30 12:28 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes Jaya Kumar
` (2 preceding siblings ...)
2008-05-30 12:28 ` [RFC 2.6.26-rc3 3/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
@ 2008-05-30 12:28 ` Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 5/5] am200epd: add mach-pxa support for am200epd Jaya Kumar
4 siblings, 0 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-30 12:28 UTC (permalink / raw)
To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel
The am200epd driver was designed with bad assumptions. It manipulated
GPSR/GPLR registers directly. It relied on direct access to the pxa LCDC
registers which have since conflicted with commit
ce4fb7b892a6d6c6a0f87366b26fd834d2923dd7 . Thus, it is broken and this patch
removes it.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
drivers/video/Kconfig | 13 --
drivers/video/Makefile | 1 -
drivers/video/am200epd.c | 295 ----------------------------------------------
3 files changed, 0 insertions(+), 309 deletions(-)
delete mode 100644 drivers/video/am200epd.c
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 002b61b..2bbd328 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1937,19 +1937,6 @@ config FB_XILINX
framebuffer. ML300 carries a 640*480 LCD display on the board,
ML403 uses a standard DB15 VGA connector.
-config FB_AM200EPD
- tristate "AM-200 E-Ink EPD devkit support"
- depends on FB && ARCH_PXA && MMU
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- select FB_DEFERRED_IO
- select FB_METRONOME
- help
- This enables support for the Metronome display controller used on
- the E-Ink AM-200 EPD devkit.
-
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 04bca35..80d5842 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -29,7 +29,6 @@ obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
# Hardware specific drivers go first
obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o
-obj-$(CONFIG_FB_AM200EPD) += am200epd.o
obj-$(CONFIG_FB_ARC) += arcfb.o
obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
diff --git a/drivers/video/am200epd.c b/drivers/video/am200epd.c
deleted file mode 100644
index 51e26c1..0000000
--- a/drivers/video/am200epd.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * linux/drivers/video/am200epd.c -- Platform device for AM200 EPD kit
- *
- * Copyright (C) 2008, Jaya Kumar
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- *
- * This work was made possible by help and equipment support from E-Ink
- * Corporation. http://support.eink.com/community
- *
- * This driver is written to be used with the Metronome display controller.
- * on the AM200 EPD prototype kit/development kit with an E-Ink 800x600
- * Vizplex EPD on a Gumstix board using the Lyre interface board.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/uaccess.h>
-#include <linux/irq.h>
-
-#include <video/metronomefb.h>
-
-#include <asm/arch/pxa-regs.h>
-
-/* register offsets for gpio control */
-#define LED_GPIO_PIN 51
-#define STDBY_GPIO_PIN 48
-#define RST_GPIO_PIN 49
-#define RDY_GPIO_PIN 32
-#define ERR_GPIO_PIN 17
-#define PCBPWR_GPIO_PIN 16
-
-#define AF_SEL_GPIO_N 0x3
-#define GAFR0_U_OFFSET(pin) ((pin - 16) * 2)
-#define GAFR1_L_OFFSET(pin) ((pin - 32) * 2)
-#define GAFR1_U_OFFSET(pin) ((pin - 48) * 2)
-#define GPDR1_OFFSET(pin) (pin - 32)
-#define GPCR1_OFFSET(pin) (pin - 32)
-#define GPSR1_OFFSET(pin) (pin - 32)
-#define GPCR0_OFFSET(pin) (pin)
-#define GPSR0_OFFSET(pin) (pin)
-
-static void am200_set_gpio_output(int pin, int val)
-{
- u8 index;
-
- index = pin >> 4;
-
- switch (index) {
- case 1:
- if (val)
- GPSR0 |= (1 << GPSR0_OFFSET(pin));
- else
- GPCR0 |= (1 << GPCR0_OFFSET(pin));
- break;
- case 2:
- break;
- case 3:
- if (val)
- GPSR1 |= (1 << GPSR1_OFFSET(pin));
- else
- GPCR1 |= (1 << GPCR1_OFFSET(pin));
- break;
- default:
- printk(KERN_ERR "unimplemented\n");
- }
-}
-
-static void __devinit am200_init_gpio_pin(int pin, int dir)
-{
- u8 index;
- /* dir 0 is output, 1 is input
- - do 2 things here:
- - set gpio alternate function to standard gpio
- - set gpio direction to input or output */
-
- index = pin >> 4;
- switch (index) {
- case 1:
- GAFR0_U &= ~(AF_SEL_GPIO_N << GAFR0_U_OFFSET(pin));
-
- if (dir)
- GPDR0 &= ~(1 << pin);
- else
- GPDR0 |= (1 << pin);
- break;
- case 2:
- GAFR1_L &= ~(AF_SEL_GPIO_N << GAFR1_L_OFFSET(pin));
-
- if (dir)
- GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
- else
- GPDR1 |= (1 << GPDR1_OFFSET(pin));
- break;
- case 3:
- GAFR1_U &= ~(AF_SEL_GPIO_N << GAFR1_U_OFFSET(pin));
-
- if (dir)
- GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
- else
- GPDR1 |= (1 << GPDR1_OFFSET(pin));
- break;
- default:
- printk(KERN_ERR "unimplemented\n");
- }
-}
-
-static void am200_init_gpio_regs(struct metronomefb_par *par)
-{
- am200_init_gpio_pin(LED_GPIO_PIN, 0);
- am200_set_gpio_output(LED_GPIO_PIN, 0);
-
- am200_init_gpio_pin(STDBY_GPIO_PIN, 0);
- am200_set_gpio_output(STDBY_GPIO_PIN, 0);
-
- am200_init_gpio_pin(RST_GPIO_PIN, 0);
- am200_set_gpio_output(RST_GPIO_PIN, 0);
-
- am200_init_gpio_pin(RDY_GPIO_PIN, 1);
-
- am200_init_gpio_pin(ERR_GPIO_PIN, 1);
-
- am200_init_gpio_pin(PCBPWR_GPIO_PIN, 0);
- am200_set_gpio_output(PCBPWR_GPIO_PIN, 0);
-}
-
-static void am200_disable_lcd_controller(struct metronomefb_par *par)
-{
- LCSR = 0xffffffff; /* Clear LCD Status Register */
- LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */
-
- /* we reset and just wait for things to settle */
- msleep(200);
-}
-
-static void am200_enable_lcd_controller(struct metronomefb_par *par)
-{
- LCSR = 0xffffffff;
- FDADR0 = par->metromem_desc_dma;
- LCCR0 |= LCCR0_ENB;
-}
-
-static void am200_init_lcdc_regs(struct metronomefb_par *par)
-{
- /* here we do:
- - disable the lcd controller
- - setup lcd control registers
- - setup dma descriptor
- - reenable lcd controller
- */
-
- /* disable the lcd controller */
- am200_disable_lcd_controller(par);
-
- /* setup lcd control registers */
- LCCR0 = LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_PAS
- | LCCR0_QDM | LCCR0_BM | LCCR0_OUM;
-
- LCCR1 = (par->info->var.xres/2 - 1) /* pixels per line */
- | (27 << 10) /* hsync pulse width - 1 */
- | (33 << 16) /* eol pixel count */
- | (33 << 24); /* bol pixel count */
-
- LCCR2 = (par->info->var.yres - 1) /* lines per panel */
- | (24 << 10) /* vsync pulse width - 1 */
- | (2 << 16) /* eof pixel count */
- | (0 << 24); /* bof pixel count */
-
- LCCR3 = 2 /* pixel clock divisor */
- | (24 << 8) /* AC Bias pin freq */
- | LCCR3_16BPP /* BPP */
- | LCCR3_PCP; /* PCP falling edge */
-
-}
-
-static void am200_post_dma_setup(struct metronomefb_par *par)
-{
- par->metromem_desc->mFDADR0 = par->metromem_desc_dma;
- par->metromem_desc->mFSADR0 = par->metromem_dma;
- par->metromem_desc->mFIDR0 = 0;
- par->metromem_desc->mLDCMD0 = par->info->var.xres
- * par->info->var.yres;
- am200_enable_lcd_controller(par);
-}
-
-static void am200_free_irq(struct fb_info *info)
-{
- free_irq(IRQ_GPIO(RDY_GPIO_PIN), info);
-}
-
-static irqreturn_t am200_handle_irq(int irq, void *dev_id)
-{
- struct fb_info *info = dev_id;
- struct metronomefb_par *par = info->par;
-
- wake_up_interruptible(&par->waitq);
- return IRQ_HANDLED;
-}
-
-static int am200_setup_irq(struct fb_info *info)
-{
- int retval;
-
- retval = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am200_handle_irq,
- IRQF_DISABLED, "AM200", info);
- if (retval) {
- printk(KERN_ERR "am200epd: request_irq failed: %d\n", retval);
- return retval;
- }
-
- return set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQT_FALLING);
-}
-
-static void am200_set_rst(struct metronomefb_par *par, int state)
-{
- am200_set_gpio_output(RST_GPIO_PIN, state);
-}
-
-static void am200_set_stdby(struct metronomefb_par *par, int state)
-{
- am200_set_gpio_output(STDBY_GPIO_PIN, state);
-}
-
-static int am200_wait_event(struct metronomefb_par *par)
-{
- return wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ);
-}
-
-static int am200_wait_event_intr(struct metronomefb_par *par)
-{
- return wait_event_interruptible_timeout(par->waitq, (GPLR1 & 0x01), HZ);
-}
-
-static struct metronome_board am200_board = {
- .owner = THIS_MODULE,
- .free_irq = am200_free_irq,
- .setup_irq = am200_setup_irq,
- .init_gpio_regs = am200_init_gpio_regs,
- .init_lcdc_regs = am200_init_lcdc_regs,
- .post_dma_setup = am200_post_dma_setup,
- .set_rst = am200_set_rst,
- .set_stdby = am200_set_stdby,
- .met_wait_event = am200_wait_event,
- .met_wait_event_intr = am200_wait_event_intr,
-};
-
-static struct platform_device *am200_device;
-
-static int __init am200_init(void)
-{
- int ret;
-
- /* request our platform independent driver */
- request_module("metronomefb");
-
- am200_device = platform_device_alloc("metronomefb", -1);
- if (!am200_device)
- return -ENOMEM;
-
- platform_device_add_data(am200_device, &am200_board,
- sizeof(am200_board));
-
- /* this _add binds metronomefb to am200. metronomefb refcounts am200 */
- ret = platform_device_add(am200_device);
-
- if (ret)
- platform_device_put(am200_device);
-
- return ret;
-}
-
-static void __exit am200_exit(void)
-{
- platform_device_unregister(am200_device);
-}
-
-module_init(am200_init);
-module_exit(am200_exit);
-
-MODULE_DESCRIPTION("board driver for am200 metronome epd kit");
-MODULE_AUTHOR("Jaya Kumar");
-MODULE_LICENSE("GPL");
--
1.5.3.6
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC 2.6.26-rc3 5/5] am200epd: add mach-pxa support for am200epd
2008-05-30 12:28 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes Jaya Kumar
` (3 preceding siblings ...)
2008-05-30 12:28 ` [RFC 2.6.26-rc3 4/5] am200epd: remove am200epd platform device driver Jaya Kumar
@ 2008-05-30 12:28 ` Jaya Kumar
4 siblings, 0 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-30 12:28 UTC (permalink / raw)
To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel
am200epd implements mach-pxa support for the am200epd carrier board. It
interfaces with metronomefb and pxafb in order to support various E-Ink
panels.
This patch does:
- export pxa_device_fb to be accessed by am200epd
- redo the metronomefb interface code to interface properly with am200epd
- allow am200epd to handle different panels properly
- cleanup to use dev_dbg instead of printk
- remove mach-pxa like structure from metronomefb
- add board support for am200epd
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
arch/arm/mach-pxa/Kconfig | 17 ++
arch/arm/mach-pxa/Makefile | 1 +
arch/arm/mach-pxa/am200epd.c | 347 ++++++++++++++++++++++++++++++++++++++++++
arch/arm/mach-pxa/devices.c | 1 +
drivers/video/metronomefb.c | 270 ++++++++++++++++++--------------
include/video/metronomefb.h | 21 +--
6 files changed, 524 insertions(+), 133 deletions(-)
create mode 100644 arch/arm/mach-pxa/am200epd.c
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 5da7a68..1bcff21 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -179,6 +179,23 @@ endchoice
endif
+if MACH_GUMSTIX_F
+
+choice
+ prompt "Select base board for Gumstix board"
+
+config MACH_AM200EPD
+ tristate "Enable AM200EPD board support"
+ select FB_METRONOME
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
+
+endchoice
+
+endif
if MACH_TRIZEPS4
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 0e6d05b..c72db62 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_CPU_PXA320) += pxa320.o
# Specific board support
obj-$(CONFIG_ARCH_GUMSTIX) += gumstix.o
+obj-$(CONFIG_MACH_AM200EPD) += am200epd.o
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
diff --git a/arch/arm/mach-pxa/am200epd.c b/arch/arm/mach-pxa/am200epd.c
new file mode 100644
index 0000000..7aeee2c
--- /dev/null
+++ b/arch/arm/mach-pxa/am200epd.c
@@ -0,0 +1,347 @@
+/*
+ * am200epd.c -- Platform device for AM200 EPD kit
+ *
+ * Copyright (C) 2008, Jaya Kumar
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ *
+ * This work was made possible by help and equipment support from E-Ink
+ * Corporation. http://support.eink.com/community
+ *
+ * This driver is written to be used with the Metronome display controller.
+ * on the AM200 EPD prototype kit/development kit with an E-Ink 800x600
+ * Vizplex EPD on a Gumstix board using the Lyre interface board.
+ *
+ */
+
+#define DEBUG 1
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+
+#include <asm/arch/pxafb.h>
+
+#include <video/metronomefb.h>
+
+#include "generic.h"
+#include "devices.h"
+
+static unsigned int panel_type = 6;
+static struct platform_device *am200_device;
+static struct metronome_board am200_board;
+
+static struct pxafb_mode_info am200_fb_mode_9inch7 = {
+ .pixclock = 40000,
+ .xres = 1200,
+ .yres = 842,
+ .bpp = 16,
+ .hsync_len = 2,
+ .left_margin = 2,
+ .right_margin = 2,
+ .vsync_len = 1,
+ .upper_margin = 2,
+ .lower_margin = 25,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mode_info am200_fb_mode_8inch = {
+ .pixclock = 40000,
+ .xres = 1088,
+ .yres = 791,
+ .bpp = 16,
+ .hsync_len = 28,
+ .left_margin = 8,
+ .right_margin = 30,
+ .vsync_len = 8,
+ .upper_margin = 10,
+ .lower_margin = 8,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mode_info am200_fb_mode_6inch = {
+ .pixclock = 40189,
+ .xres = 832,
+ .yres = 622,
+ .bpp = 16,
+ .hsync_len = 28,
+ .left_margin = 34,
+ .right_margin = 34,
+ .vsync_len = 25,
+ .upper_margin = 0,
+ .lower_margin = 2,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct pxafb_mach_info am200_fb_info = {
+ .modes = &am200_fb_mode_6inch,
+ .num_modes = 1,
+ .lccr0 = LCCR0_Pas | LCCR0_Sngl | LCCR0_Color,
+ .lccr3 = 0,
+ .lcd_conn = LCD_TYPE_COLOR_TFT | LCD_PCLK_EDGE_FALL |
+ LCD_AC_BIAS_FREQ(24),
+ .clkdev = &pxa_device_fb.dev,
+ .custom_xfer_div = 2,
+};
+
+/* register offsets for gpio control */
+#define LED_GPIO_PIN 51
+#define STDBY_GPIO_PIN 48
+#define RST_GPIO_PIN 49
+#define RDY_GPIO_PIN 32
+#define ERR_GPIO_PIN 17
+#define PCBPWR_GPIO_PIN 16
+static int gpios[] = { LED_GPIO_PIN , STDBY_GPIO_PIN , RST_GPIO_PIN,
+ RDY_GPIO_PIN, ERR_GPIO_PIN, PCBPWR_GPIO_PIN };
+static char *gpio_names[] = { "LED" , "STDBY" , "RST", "RDY", "ERR", "PCBPWR" };
+
+static int am200_init_gpio_regs(struct metronomefb_par *par)
+{
+ int i;
+ int err;
+
+ for (i = 0; i < ARRAY_SIZE(gpios); i++) {
+ err = gpio_request(gpios[i], gpio_names[i]);
+ if (err) {
+ dev_err(&am200_device->dev, "failed requesting "
+ "gpio %s, err=%d\n", gpio_names[i], err);
+ goto err_req_gpio;
+ }
+ }
+
+ gpio_direction_output(LED_GPIO_PIN, 0);
+ gpio_direction_output(STDBY_GPIO_PIN, 0);
+ gpio_direction_output(RST_GPIO_PIN, 0);
+
+ gpio_direction_input(RDY_GPIO_PIN);
+ gpio_direction_input(ERR_GPIO_PIN);
+
+ gpio_direction_output(PCBPWR_GPIO_PIN, 0);
+
+ return 0;
+
+err_req_gpio:
+ while (i > 0)
+ gpio_free(gpios[i--]);
+
+ return err;
+}
+
+static void am200_cleanup(struct metronomefb_par *par)
+{
+ int i;
+
+ free_irq(IRQ_GPIO(RDY_GPIO_PIN), par->info);
+
+ for (i = 0; i < ARRAY_SIZE(gpios); i++)
+ gpio_free(gpios[i]);
+}
+
+static struct platform_device *am200_pxa_device_fb;
+
+static int am200_pxa_register_device(struct platform_device *dev,
+ struct pxafb_mach_info *data)
+{
+ int ret;
+
+ am200_pxa_device_fb = platform_device_alloc("pxa2xx-fb", -1);
+ if (!am200_pxa_device_fb)
+ return -ENOMEM;
+
+ platform_device_add_data(am200_pxa_device_fb, data, sizeof(*data));
+
+ platform_device_add_resources(am200_pxa_device_fb,
+ pxa_device_fb.resource,
+ pxa_device_fb.num_resources);
+
+ am200_pxa_device_fb->dev.dma_mask = pxa_device_fb.dev.dma_mask;
+ am200_pxa_device_fb->dev.coherent_dma_mask =
+ pxa_device_fb.dev.coherent_dma_mask;
+
+ ret = platform_device_add(am200_pxa_device_fb);
+
+ if (ret) {
+ dev_err(&am200_device->dev, "failed adding pxafb %d\n", ret);
+ platform_device_put(am200_pxa_device_fb);
+ }
+
+ return ret;
+}
+
+static int am200_share_video_mem(unsigned char *video_mem, dma_addr_t dma,
+ struct module *fbmaster, void *data)
+{
+ struct metronomefb_par *par = data;
+
+ /* try to refcount the caller since we are the consumer after this */
+ if (!try_module_get(fbmaster))
+ return -ENODEV;
+
+ dev_dbg(&am200_device->dev, "mod_get %p\n", fbmaster);
+ am200_board.fbmaster = fbmaster;
+ par->metromem = video_mem;
+ par->metromem_dma = dma;
+
+ return 0;
+}
+
+static void am200_unshare_video_mem(void *data)
+{
+ struct metronomefb_par *par = data;
+
+ dev_dbg(&am200_device->dev, "ENTER %s\n", __func__);
+ par->metromem = NULL;
+ par->metromem_dma = 0;
+ dev_dbg(&am200_device->dev, "mod_put %p\n", am200_board.fbmaster);
+ module_put(am200_board.fbmaster);
+}
+
+static int am200_setup_fb(struct metronomefb_par *par)
+{
+ int ret;
+
+ am200_fb_info.extra_video_mem = par->extra_size;
+ am200_fb_info.extra_data = (void *) par;
+ am200_fb_info.share_video_mem = am200_share_video_mem;
+ am200_fb_info.unshare_video_mem = am200_unshare_video_mem;
+
+ switch (panel_type) {
+ case 6:
+ am200_fb_info.modes = &am200_fb_mode_6inch;
+ break;
+ case 8:
+ am200_fb_info.modes = &am200_fb_mode_8inch;
+ break;
+ case 97:
+ am200_fb_info.modes = &am200_fb_mode_9inch7;
+ break;
+ default:
+ dev_err(&am200_device->dev, "invalid panel_type selection,"
+ " setting to 6\n");
+ am200_fb_info.modes = &am200_fb_mode_6inch;
+ break;
+ }
+
+ ret = am200_pxa_register_device(&pxa_device_fb, &am200_fb_info);
+ return ret;
+}
+
+static int am200_get_panel_type(void)
+{
+ return panel_type;
+}
+
+static irqreturn_t am200_handle_irq(int irq, void *dev_id)
+{
+ struct fb_info *info = dev_id;
+ struct metronomefb_par *par = info->par;
+
+ wake_up_interruptible(&par->waitq);
+ return IRQ_HANDLED;
+}
+
+static int am200_setup_irq(struct fb_info *info)
+{
+ int ret;
+
+ ret = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am200_handle_irq,
+ IRQF_DISABLED, "AM200", info);
+ if (ret) {
+ dev_err(&am200_device->dev, "request_irq failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQT_FALLING);
+ if (ret)
+ dev_err(&am200_device->dev, "set_irq_type failed: %d\n", ret);
+
+ return ret;
+}
+
+static void am200_set_rst(struct metronomefb_par *par, int state)
+{
+ gpio_set_value(RST_GPIO_PIN, state);
+}
+
+static void am200_set_stdby(struct metronomefb_par *par, int state)
+{
+ gpio_set_value(STDBY_GPIO_PIN, state);
+}
+
+static int am200_wait_event(struct metronomefb_par *par)
+{
+ return wait_event_timeout(par->waitq, gpio_get_value(RDY_GPIO_PIN), HZ);
+}
+
+static int am200_wait_event_intr(struct metronomefb_par *par)
+{
+ int ret;
+
+ ret = wait_event_interruptible_timeout(par->waitq,
+ gpio_get_value(RDY_GPIO_PIN), HZ);
+ return ret;
+}
+
+static struct metronome_board am200_board = {
+ .owner = THIS_MODULE,
+ .setup_irq = am200_setup_irq,
+ .setup_io = am200_init_gpio_regs,
+ .setup_fb = am200_setup_fb,
+ .set_rst = am200_set_rst,
+ .set_stdby = am200_set_stdby,
+ .met_wait_event = am200_wait_event,
+ .met_wait_event_intr = am200_wait_event_intr,
+ .get_panel_type = am200_get_panel_type,
+ .cleanup = am200_cleanup,
+};
+
+static int __init am200_init(void)
+{
+ int ret;
+
+ /* request our platform independent driver */
+ request_module("metronomefb");
+
+ am200_device = platform_device_alloc("metronomefb", -1);
+ if (!am200_device)
+ return -ENOMEM;
+
+ platform_device_add_data(am200_device, &am200_board,
+ sizeof(am200_board));
+
+ /* this _add binds metronomefb to am200. metronomefb refcounts am200 */
+ ret = platform_device_add(am200_device);
+
+ if (ret)
+ platform_device_put(am200_device);
+
+ return ret;
+}
+
+static void __exit am200_exit(void)
+{
+ platform_device_unregister(am200_pxa_device_fb);
+ platform_device_unregister(am200_device);
+}
+
+module_param(panel_type, uint, 0);
+MODULE_PARM_DESC(panel_type, "Select the panel type: 6, 8, 97");
+
+module_init(am200_init);
+module_exit(am200_exit);
+
+MODULE_DESCRIPTION("board driver for am200 metronome epd kit");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index b72b73a..fe0eb07 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -127,6 +127,7 @@ struct platform_device pxa_device_fb = {
.num_resources = ARRAY_SIZE(pxafb_resources),
.resource = pxafb_resources,
};
+EXPORT_SYMBOL_GPL(pxa_device_fb);
void __init set_pxa_fb_info(struct pxafb_mach_info *info)
{
diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
index cc4c038..6e1c1eb 100644
--- a/drivers/video/metronomefb.c
+++ b/drivers/video/metronomefb.c
@@ -18,6 +18,8 @@
* is provided as am200epd.c
*
*/
+#define DEBUG 1
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -40,29 +42,63 @@
#include <asm/unaligned.h>
-
-#define DEBUG 1
-#ifdef DEBUG
-#define DPRINTK(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
-#else
-#define DPRINTK(f, a...)
-#endif
-
-
/* Display specific information */
#define DPY_W 832
#define DPY_H 622
+int user_wfm_size;
+
/* frame differs from image. frame includes non-visible pixels */
struct epd_frame {
int fw; /* frame width */
int fh; /* frame height */
+ u16 config[4];
+ int wfm_size;
};
static struct epd_frame epd_frame_table[] = {
{
- .fw = 832,
- .fh = 622
+ .fw = 832,
+ .fh = 622,
+ .config = {
+ 15 /* sdlew */
+ | 2 << 8 /* sdosz */
+ | 0 << 11 /* sdor */
+ | 0 << 12 /* sdces */
+ | 0 << 15, /* sdcer */
+ 42 /* gdspl */
+ | 1 << 8 /* gdr1 */
+ | 1 << 9 /* sdshr */
+ | 0 << 15, /* gdspp */
+ 18 /* gdspw */
+ | 0 << 15, /* dispc */
+ 599 /* vdlc */
+ | 0 << 11 /* dsi */
+ | 0 << 12, /* dsic */
+ },
+ .wfm_size = 47001,
+ },
+ {
+ .fw = 1088,
+ .fh = 791,
+ .config = {
+ 0x0104,
+ 0x031f,
+ 0x0088,
+ 0x02ff,
+ },
+ .wfm_size = 46770,
+ },
+ {
+ .fw = 1200,
+ .fh = 842,
+ .config = {
+ 0x0101,
+ 0x030e,
+ 0x0012,
+ 0x0280,
+ },
+ .wfm_size = 46770,
},
};
@@ -134,9 +170,8 @@ static u16 calc_img_cksum(u16 *start, int length)
}
/* here we decode the incoming waveform file and populate metromem */
-#define EXP_WFORM_SIZE 47001
-static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
- u8 *frame_count)
+static int __devinit load_waveform(u8 *mem, size_t size, int m, int t,
+ struct metronomefb_par *par)
{
int tta;
int wmta;
@@ -148,26 +183,31 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
int wfm_idx, owfm_idx;
int mem_idx = 0;
struct waveform_hdr *wfm_hdr;
+ u8 *metromem = par->metromem_wfm;
+ struct device *dev = par->info->dev;
- if (size != EXP_WFORM_SIZE) {
- printk(KERN_ERR "Error: unexpected size %d != %d\n", size,
- EXP_WFORM_SIZE);
+ if (user_wfm_size)
+ epd_frame_table[par->dt].wfm_size = user_wfm_size;
+
+ if (size != epd_frame_table[par->dt].wfm_size) {
+ dev_err(dev, "Error: unexpected size %d != %d\n", size,
+ epd_frame_table[par->dt].wfm_size);
return -EINVAL;
}
wfm_hdr = (struct waveform_hdr *) mem;
if (wfm_hdr->fvsn != 1) {
- printk(KERN_ERR "Error: bad fvsn %x\n", wfm_hdr->fvsn);
+ dev_err(dev, "Error: bad fvsn %x\n", wfm_hdr->fvsn);
return -EINVAL;
}
if (wfm_hdr->luts != 0) {
- printk(KERN_ERR "Error: bad luts %x\n", wfm_hdr->luts);
+ dev_err(dev, "Error: bad luts %x\n", wfm_hdr->luts);
return -EINVAL;
}
cksum = calc_cksum(32, 47, mem);
if (cksum != wfm_hdr->wfm_cs) {
- printk(KERN_ERR "Error: bad cksum %x != %x\n", cksum,
+ dev_err(dev, "Error: bad cksum %x != %x\n", cksum,
wfm_hdr->wfm_cs);
return -EINVAL;
}
@@ -175,7 +215,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
wfm_hdr->trc += 1;
for (i = 0; i < 5; i++) {
if (*(wfm_hdr->stuff2a + i) != 0) {
- printk(KERN_ERR "Error: unexpected value in padding\n");
+ dev_err(dev, "Error: unexpected value in padding\n");
return -EINVAL;
}
}
@@ -200,7 +240,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
return -EINVAL;
cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
- printk(KERN_ERR "Error: bad temperature range table cksum"
+ dev_err(dev, "Error: bad temperature range table cksum"
" %x != %x\n", cksum, mem[cksum_idx]);
return -EINVAL;
}
@@ -212,7 +252,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
return -EINVAL;
cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
- printk(KERN_ERR "Error: bad mode table address cksum"
+ dev_err(dev, "Error: bad mode table address cksum"
" %x != %x\n", cksum, mem[cksum_idx]);
return -EINVAL;
}
@@ -224,7 +264,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
return -EINVAL;
cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
- printk(KERN_ERR "Error: bad temperature table address cksum"
+ dev_err(dev, "Error: bad temperature table address cksum"
" %x != %x\n", cksum, mem[cksum_idx]);
return -EINVAL;
}
@@ -259,11 +299,11 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
return -EINVAL;
cksum = calc_cksum(owfm_idx, cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
- printk(KERN_ERR "Error: bad waveform data cksum"
+ dev_err(dev, "Error: bad waveform data cksum"
" %x != %x\n", cksum, mem[cksum_idx]);
return -EINVAL;
}
- *frame_count = (mem_idx/64);
+ par->frame_count = (mem_idx/64);
return 0;
}
@@ -335,44 +375,17 @@ static int __devinit metronome_powerup_cmd(struct metronomefb_par *par)
static int __devinit metronome_config_cmd(struct metronomefb_par *par)
{
- int i;
- u16 cs;
-
/* setup config command
we can't immediately set the opcode since the controller
- will try parse the command before we've set it all up
- so we just set cs here and set the opcode at the end */
-
- cs = 0xCC10;
-
- /* set the 12 args ( 8 bytes ) for config. see spec for meanings */
- i = 0;
- par->metromem_cmd->args[i] = 15 /* sdlew */
- | 2 << 8 /* sdosz */
- | 0 << 11 /* sdor */
- | 0 << 12 /* sdces */
- | 0 << 15; /* sdcer */
- cs += par->metromem_cmd->args[i++];
-
- par->metromem_cmd->args[i] = 42 /* gdspl */
- | 1 << 8 /* gdr1 */
- | 1 << 9 /* sdshr */
- | 0 << 15; /* gdspp */
- cs += par->metromem_cmd->args[i++];
-
- par->metromem_cmd->args[i] = 18 /* gdspw */
- | 0 << 15; /* dispc */
- cs += par->metromem_cmd->args[i++];
-
- par->metromem_cmd->args[i] = 599 /* vdlc */
- | 0 << 11 /* dsi */
- | 0 << 12; /* dsic */
- cs += par->metromem_cmd->args[i++];
+ will try parse the command before we've set it all up */
+ memcpy(par->metromem_cmd->args, epd_frame_table[par->dt].config,
+ sizeof(epd_frame_table[par->dt].config));
/* the rest are 0 */
- memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
+ memset((u8 *) (par->metromem_cmd->args + 4), 0, (32-4)*2);
- par->metromem_cmd->csum = cs;
+ par->metromem_cmd->csum = 0xCC10;
+ par->metromem_cmd->csum += calc_img_cksum(par->metromem_cmd->args, 4);
par->metromem_cmd->opcode = 0xCC10; /* config cmd */
return par->board->met_wait_event(par);
@@ -408,12 +421,9 @@ static int __devinit metronome_init_regs(struct metronomefb_par *par)
{
int res;
- par->board->init_gpio_regs(par);
-
- par->board->init_lcdc_regs(par);
-
- /* now that lcd is setup, setup dma descriptor */
- par->board->post_dma_setup(par);
+ res = par->board->setup_io(par);
+ if (res)
+ return res;
res = metronome_powerup_cmd(par);
if (res)
@@ -430,16 +440,16 @@ static int __devinit metronome_init_regs(struct metronomefb_par *par)
static void metronomefb_dpy_update(struct metronomefb_par *par)
{
+ int fbsize;
u16 cksum;
unsigned char *buf = (unsigned char __force *)par->info->screen_base;
+ fbsize = par->info->fix.smem_len;
/* copy from vm to metromem */
- memcpy(par->metromem_img, buf, DPY_W*DPY_H);
+ memcpy(par->metromem_img, buf, fbsize);
- cksum = calc_img_cksum((u16 *) par->metromem_img,
- (epd_frame_table[0].fw * DPY_H)/2);
- *((u16 *)(par->metromem_img) +
- (epd_frame_table[0].fw * DPY_H)/2) = cksum;
+ cksum = calc_img_cksum((u16 *) par->metromem_img, fbsize/2);
+ *((u16 *)(par->metromem_img) + fbsize/2) = cksum;
metronome_display_cmd(par);
}
@@ -569,13 +579,16 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
{
struct fb_info *info;
struct metronome_board *board;
- int retval = -ENOMEM;
+ int ret = -ENOMEM;
int videomemorysize;
unsigned char *videomemory;
struct metronomefb_par *par;
const struct firmware *fw_entry;
int cmd_size, wfm_size, img_size, padding_size, totalsize;
int i;
+ int panel_type;
+ int fw, fh;
+ int epd_dt_index;
/* pick up board specific routines */
board = dev->dev.platform_data;
@@ -591,9 +604,29 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
par->metromem which is physically contiguous memory and
contains the display controller commands, waveform,
processed image data and padding. this is the data pulled
- by the device's LCD controller and pushed to Metronome */
-
- videomemorysize = (DPY_W*DPY_H);
+ by the device's LCD controller and pushed to Metronome.
+ the metromem memory is allocated by the board driver and
+ is provided to us */
+
+ panel_type = board->get_panel_type();
+ switch (panel_type) {
+ case 6:
+ epd_dt_index = 0;
+ break;
+ case 8:
+ epd_dt_index = 1;
+ break;
+ case 97:
+ epd_dt_index = 2;
+ break;
+ default:
+ dev_err(&dev->dev, "Unexpected panel type. Defaulting to 6\n");
+ epd_dt_index = 0;
+ break;
+ }
+ fw = epd_frame_table[epd_dt_index].fw;
+ fh = epd_frame_table[epd_dt_index].fh;
+ videomemorysize = fw * fh;
videomemory = vmalloc(videomemorysize);
if (!videomemory)
return -ENOMEM;
@@ -607,12 +640,18 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
info->screen_base = (char __force __iomem *)videomemory;
info->fbops = &metronomefb_ops;
+ metronomefb_fix.line_length = fw;
+ metronomefb_var.xres = fw;
+ metronomefb_var.yres = fh;
+ metronomefb_var.xres_virtual = fw;
+ metronomefb_var.yres_virtual= fh;
info->var = metronomefb_var;
info->fix = metronomefb_fix;
info->fix.smem_len = videomemorysize;
par = info->par;
par->info = info;
par->board = board;
+ par->dt = epd_dt_index;
init_waitqueue_head(&par->waitq);
/* this table caches per page csum values. */
@@ -628,20 +667,21 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
eg: IW=832 IH=622 WS=128
*/
- cmd_size = 1 * epd_frame_table[0].fw;
- wfm_size = ((16*1024 + 2 + epd_frame_table[0].fw - 1)
- / epd_frame_table[0].fw) * epd_frame_table[0].fw;
- img_size = epd_frame_table[0].fh * epd_frame_table[0].fw;
- padding_size = 4 * epd_frame_table[0].fw;
+ cmd_size = 1 * fw;
+ wfm_size = ((16*1024 + 2 + fw - 1) / fw) * fw;
+ img_size = fh * fw;
+ padding_size = 4 * fw;
+ par->extra_size = cmd_size + wfm_size + padding_size;
totalsize = cmd_size + wfm_size + img_size + padding_size;
par->metromemsize = PAGE_ALIGN(totalsize + 256);
- DPRINTK("desired memory size = %d\n", par->metromemsize);
- dev->dev.coherent_dma_mask = 0xffffffffull;
- par->metromem = dma_alloc_writecombine(&dev->dev, par->metromemsize,
- &par->metromem_dma, GFP_KERNEL);
+ ret = par->board->setup_fb(par);
+ if (ret) {
+ dev_err(&dev->dev, "Failed to setup fb\n");
+ goto err_vfree;
+ }
+ /* after this point we should have a framebuffer */
if (!par->metromem) {
- printk(KERN_ERR
- "metronomefb: unable to allocate dma buffer\n");
+ ret = -EINVAL;
goto err_vfree;
}
@@ -649,36 +689,29 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
par->metromem_cmd = (struct metromem_cmd *) par->metromem;
par->metromem_wfm = par->metromem + cmd_size;
par->metromem_img = par->metromem + cmd_size + wfm_size;
- par->metromem_img_csum = (u16 *) (par->metromem_img +
- (epd_frame_table[0].fw * DPY_H));
- DPRINTK("img offset=0x%x\n", cmd_size + wfm_size);
- par->metromem_desc = (struct metromem_desc *) (par->metromem + cmd_size
- + wfm_size + img_size + padding_size);
- par->metromem_desc_dma = par->metromem_dma + cmd_size + wfm_size
- + img_size + padding_size;
-
+ par->metromem_img_csum = (u16 *) (par->metromem_img + (fw * fh));
/* load the waveform in. assume mode 3, temp 31 for now
a) request the waveform file from userspace
b) process waveform and decode into metromem */
- retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
- if (retval < 0) {
- printk(KERN_ERR "metronomefb: couldn't get waveform\n");
- goto err_dma_free;
+ ret = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
+ if (ret < 0) {
+ dev_err(&dev->dev, "Failed to get waveform\n");
+ goto err_csum_table;
}
- retval = load_waveform((u8 *) fw_entry->data, fw_entry->size,
- par->metromem_wfm, 3, 31, &par->frame_count);
+ ret = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31,
+ par);
release_firmware(fw_entry);
- if (retval < 0) {
- printk(KERN_ERR "metronomefb: couldn't process waveform\n");
- goto err_dma_free;
+ if (ret < 0) {
+ dev_err(&dev->dev, "Failed processing waveform\n");
+ goto err_csum_table;
}
if (board->setup_irq(info))
- goto err_dma_free;
+ goto err_csum_table;
- retval = metronome_init_regs(par);
- if (retval < 0)
+ ret = metronome_init_regs(par);
+ if (ret < 0)
goto err_free_irq;
info->flags = FBINFO_FLAG_DEFAULT;
@@ -686,9 +719,9 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
info->fbdefio = &metronomefb_defio;
fb_deferred_io_init(info);
- retval = fb_alloc_cmap(&info->cmap, 8, 0);
- if (retval < 0) {
- printk(KERN_ERR "Failed to allocate colormap\n");
+ ret = fb_alloc_cmap(&info->cmap, 8, 0);
+ if (ret < 0) {
+ dev_err(&dev->dev, "Failed to allocate colormap\n");
goto err_fb_rel;
}
@@ -698,13 +731,13 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*8);
memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*8);
- retval = register_framebuffer(info);
- if (retval < 0)
+ ret = register_framebuffer(info);
+ if (ret < 0)
goto err_cmap;
platform_set_drvdata(dev, info);
- printk(KERN_INFO
+ dev_dbg(&dev->dev,
"fb%d: Metronome frame buffer device, using %dK of video"
" memory\n", info->node, videomemorysize >> 10);
@@ -715,16 +748,13 @@ err_cmap:
err_fb_rel:
framebuffer_release(info);
err_free_irq:
- board->free_irq(info);
-err_dma_free:
- dma_free_writecombine(&dev->dev, par->metromemsize, par->metromem,
- par->metromem_dma);
+ board->cleanup(par);
err_csum_table:
vfree(par->csum_table);
err_vfree:
vfree(videomemory);
module_put(board->owner);
- return retval;
+ return ret;
}
static int __devexit metronomefb_remove(struct platform_device *dev)
@@ -734,14 +764,13 @@ static int __devexit metronomefb_remove(struct platform_device *dev)
if (info) {
struct metronomefb_par *par = info->par;
fb_deferred_io_cleanup(info);
- dma_free_writecombine(&dev->dev, par->metromemsize,
- par->metromem, par->metromem_dma);
fb_dealloc_cmap(&info->cmap);
vfree(par->csum_table);
unregister_framebuffer(info);
vfree((void __force *)info->screen_base);
- par->board->free_irq(info);
+ par->board->cleanup(par);
module_put(par->board->owner);
+ dev_dbg(&dev->dev, "calling release\n");
framebuffer_release(info);
}
return 0;
@@ -766,6 +795,9 @@ static void __exit metronomefb_exit(void)
platform_driver_unregister(&metronomefb_driver);
}
+module_param(user_wfm_size, uint, 0);
+MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size");
+
module_init(metronomefb_init);
module_exit(metronomefb_exit);
diff --git a/include/video/metronomefb.h b/include/video/metronomefb.h
index dab04b4..7eeddf2 100644
--- a/include/video/metronomefb.h
+++ b/include/video/metronomefb.h
@@ -12,14 +12,6 @@
#ifndef _LINUX_METRONOMEFB_H_
#define _LINUX_METRONOMEFB_H_
-/* address and control descriptors used by metronome controller */
-struct metromem_desc {
- u32 mFDADR0;
- u32 mFSADR0;
- u32 mFIDR0;
- u32 mLDCMD0;
-};
-
/* command structure used by metronome controller */
struct metromem_cmd {
u16 opcode;
@@ -30,7 +22,6 @@ struct metromem_cmd {
/* struct used by metronome. board specific stuff comes from *board */
struct metronomefb_par {
unsigned char *metromem;
- struct metromem_desc *metromem_desc;
struct metromem_cmd *metromem_cmd;
unsigned char *metromem_wfm;
unsigned char *metromem_img;
@@ -38,25 +29,27 @@ struct metronomefb_par {
u16 *csum_table;
int metromemsize;
dma_addr_t metromem_dma;
- dma_addr_t metromem_desc_dma;
struct fb_info *info;
struct metronome_board *board;
wait_queue_head_t waitq;
u8 frame_count;
+ int extra_size;
+ int dt;
};
/* board specific routines */
struct metronome_board {
struct module *owner;
- void (*free_irq)(struct fb_info *);
- void (*init_gpio_regs)(struct metronomefb_par *);
- void (*init_lcdc_regs)(struct metronomefb_par *);
- void (*post_dma_setup)(struct metronomefb_par *);
+ struct module *fbmaster;
void (*set_rst)(struct metronomefb_par *, int);
void (*set_stdby)(struct metronomefb_par *, int);
+ void (*cleanup)(struct metronomefb_par *);
int (*met_wait_event)(struct metronomefb_par *);
int (*met_wait_event_intr)(struct metronomefb_par *);
int (*setup_irq)(struct fb_info *);
+ int (*setup_fb)(struct metronomefb_par *);
+ int (*setup_io)(struct metronomefb_par *);
+ int (*get_panel_type)(void);
};
#endif
--
1.5.3.6
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RFC 2.6.26-rc3 1/5] pxafb: module unloading support
2008-05-30 12:28 ` [RFC 2.6.26-rc3 1/5] pxafb: module unloading support Jaya Kumar
@ 2008-05-30 17:04 ` Krzysztof Helt
2008-05-31 1:02 ` Jaya Kumar
0 siblings, 1 reply; 11+ messages in thread
From: Krzysztof Helt @ 2008-05-30 17:04 UTC (permalink / raw)
To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel
On Fri, 30 May 2008 08:28:46 -0400
Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> This patch to pxafb adds:
> - exit and remove handlers
> - changes to use __devinit/exit for probe functions and __init/exit for
> init/exit functions
> - set g_options to initdata since it is only accessed from pxafb_init
> in order to enable module loading/unloading of pxafb.
>
> Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
> ---
> drivers/video/pxafb.c | 52 ++++++++++++++++++++++++++++++++++++++++--------
> 1 files changed, 43 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
> index 274bc93..a4bb733 100644
> --- a/drivers/video/pxafb.c
> +++ b/drivers/video/pxafb.c
> @@ -1584,10 +1584,10 @@ static int __init pxafb_parse_options(struct device *dev, char *options)
> return 0;
> }
>
> -static char g_options[256] __devinitdata = "";
> +static char g_options[256] __initdata = "";
>
This is not right. The g_options is used by
the pxafb_probe (below) and pxafb_parse_options
which are now __devinit.
> @@ -1611,7 +1611,7 @@ MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
> #define pxafb_setup_options() (0)
> #endif
>
> -static int __init pxafb_probe(struct platform_device *dev)
> +static int __devinit pxafb_probe(struct platform_device *dev)
> {
> struct pxafb_info *fbi;
> struct pxafb_mach_info *inf;
> @@ -1776,16 +1776,44 @@ failed:
> return ret;
> }
>
> +static int __devexit pxafb_remove(struct platform_device *dev)
> +{
> + struct pxafb_info *fbi = platform_get_drvdata(dev);
> + struct resource *r;
> + int irq;
> +
> + if (fbi) {
> + struct fb_info *info = &fbi->fb;
> +
> + irq = platform_get_irq(dev, 0);
> + free_irq(irq, fbi);
> +
> + r = platform_get_resource(dev, IORESOURCE_MEM, 0);
> + release_mem_region(r->start, r->end - r->start + 1);
> +
> + iounmap(fbi->mmio_base);
> +
I can be wrong here, but should not the iounmap be done before
releasing the iomaped region?
Regards,
Krzysztof
----------------------------------------------------------------------
Mucha powraca!
Sprawdz >>> http://link.interia.pl/f1e0d
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface
2008-05-30 12:28 ` [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface Jaya Kumar
@ 2008-05-30 17:10 ` Krzysztof Helt
2008-05-31 0:49 ` Jaya Kumar
0 siblings, 1 reply; 11+ messages in thread
From: Krzysztof Helt @ 2008-05-30 17:10 UTC (permalink / raw)
To: Jaya Kumar; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel
On Fri, 30 May 2008 08:28:47 -0400
Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
> These changes are to make it possible for a secondary driver to share the
> pxafb framebuffer. The changes include:
> - adding clkdev entry in pxafb_mach_info so that a driver can pass in the
> correct struct device owner for the LCDCLK.
> - adding custom_xfer_div entry so that a driver can have custom sized
> transfers. For example, the metronome controller uses 16 bit AMLCD
> transfers but actually has 3 bit pixels in 8 bit containers.
> - adding extra_video_mem entry so that a driver can tell pxafb of its
> additional needs.
> - adding share_video_mem/unshare_video_mem callbacks to notify the secondary
> driver of the framebuffer address, to allow refcounting, and to cleanup on
> completion.
>
> Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
> ---
> arch/arm/mach-pxa/devices.c | 2 +
> drivers/video/pxafb.c | 46 ++++++++++++++++++++++++++++++++-----
> include/asm-arm/arch-pxa/pxafb.h | 9 +++++++
> 3 files changed, 50 insertions(+), 7 deletions(-)
>
> diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
> index d6c05b6..b72b73a 100644
> --- a/arch/arm/mach-pxa/devices.c
> +++ b/arch/arm/mach-pxa/devices.c
> @@ -1297,6 +1318,8 @@ static void pxafb_decode_mode_info(struct pxafb_info *fbi,
> smemlen = modes[i].xres * modes[i].yres * modes[i].bpp / 8;
> if (smemlen > fbi->fb.fix.smem_len)
> fbi->fb.fix.smem_len = smemlen;
> + if (inf->custom_xfer_div)
> + smemlen /= inf->custom_xfer_div;
> }
> }
>
This one should be rather:
+ if (inf->custom_xfer_div)
+ fbi->fb.fix.smem_len /= inf->custom_xfer_div;
Otherwise is does nothing (the function ends here).
Regards,
Krzysztof
----------------------------------------------------------------------
Mucha powraca!
Sprawdz >>> http://link.interia.pl/f1e0d
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface
2008-05-30 17:10 ` Krzysztof Helt
@ 2008-05-31 0:49 ` Jaya Kumar
0 siblings, 0 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-31 0:49 UTC (permalink / raw)
To: Krzysztof Helt; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel
On Fri, May 30, 2008 at 1:10 PM, Krzysztof Helt <krzysztof.h1@poczta.fm> wrote:
>
> This one should be rather:
>
> + if (inf->custom_xfer_div)
> + fbi->fb.fix.smem_len /= inf->custom_xfer_div;
>
> Otherwise is does nothing (the function ends here).
>
Thanks for catching it. Will fix and repost.
jaya
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC 2.6.26-rc3 1/5] pxafb: module unloading support
2008-05-30 17:04 ` Krzysztof Helt
@ 2008-05-31 1:02 ` Jaya Kumar
0 siblings, 0 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-31 1:02 UTC (permalink / raw)
To: Krzysztof Helt; +Cc: ymiao3, linux-fbdev-devel, linux-arm-kernel
On Fri, May 30, 2008 at 1:04 PM, Krzysztof Helt <krzysztof.h1@poczta.fm> wrote:
> On Fri, 30 May 2008 08:28:46 -0400
> Jaya Kumar <jayakumar.lkml@gmail.com> wrote:
>
>> -static char g_options[256] __devinitdata = "";
>> +static char g_options[256] __initdata = "";
>>
>
> This is not right. The g_options is used by
> the pxafb_probe (below) and pxafb_parse_options
> which are now __devinit.
Ah, I see it now. Will fix.
>> +
>> + r = platform_get_resource(dev, IORESOURCE_MEM, 0);
>> + release_mem_region(r->start, r->end - r->start + 1);
>> +
>> + iounmap(fbi->mmio_base);
>> +
>
> I can be wrong here, but should not the iounmap be done before
> releasing the iomaped region?
>
Yes, I agree with you. I used the same sequence I saw in the
pxafb_probe failout path:
failed_free_res:
release_mem_region(r->start, r->end - r->start + 1);
failed_free_io:
iounmap(fbi->mmio_base);
I will reorder both as the correction.
Thanks,
jaya
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC 2.6.26-rc3 3/5] gumstix: conversion to MFP support and add bluetooth support
2008-05-31 4:41 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes v2 Jaya Kumar
@ 2008-05-31 4:41 ` Jaya Kumar
0 siblings, 0 replies; 11+ messages in thread
From: Jaya Kumar @ 2008-05-31 4:41 UTC (permalink / raw)
To: ymiao3; +Cc: Jaya Kumar, linux-fbdev-devel, linux-arm-kernel
This patch converts gumstix over to the MFP configuration system and adds
bluetooth support. Added a CLK_32K clock to enable bluetooth.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
arch/arm/mach-pxa/gumstix.c | 79 ++++++++++++++++++++++++++-------
arch/arm/mach-pxa/pxa25x.c | 31 +++++++++++++
include/asm-arm/arch-pxa/mfp-pxa25x.h | 1 +
3 files changed, 95 insertions(+), 16 deletions(-)
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index bdf2397..3e0a962 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -20,8 +20,12 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/setup.h>
#include <asm/memory.h>
@@ -40,7 +44,7 @@
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
+#include <asm/arch/mfp-pxa25x.h>
#include "generic.h"
@@ -85,21 +89,8 @@ static struct platform_device *devices[] __initdata = {
};
#ifdef CONFIG_MMC_PXA
-static struct pxamci_platform_data gumstix_mci_platform_data;
-
-static int gumstix_mci_init(struct device *dev, irq_handler_t detect_int,
- void *data)
-{
- pxa_gpio_mode(GPIO6_MMCCLK_MD);
- pxa_gpio_mode(GPIO53_MMCCLK_MD);
- pxa_gpio_mode(GPIO8_MMCCS0_MD);
-
- return 0;
-}
-
static struct pxamci_platform_data gumstix_mci_platform_data = {
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
- .init = gumstix_mci_init,
};
static void __init gumstix_mmc_init(void)
@@ -109,7 +100,7 @@ static void __init gumstix_mmc_init(void)
#else
static void __init gumstix_mmc_init(void)
{
- printk(KERN_INFO "Gumstix mmc disabled\n");
+ pr_debug("Gumstix mmc disabled\n");
}
#endif
@@ -126,12 +117,68 @@ static void __init gumstix_udc_init(void)
#else
static void gumstix_udc_init(void)
{
- printk(KERN_INFO "Gumstix udc is disabled\n");
+ pr_debug("Gumstix udc is disabled\n");
+}
+#endif
+
+#ifdef CONFIG_BT
+static void __init gumstix_bluetooth_init(void)
+{
+ int err;
+ struct clk *clk32k;
+
+ clk32k = clk_get(NULL, "CLK_32K");
+ if (IS_ERR(clk32k)) {
+ pr_err("gumstix: failed to find 32kHz clock\n");
+ return;
+ }
+ clk_enable(clk32k);
+
+ err = gpio_direction_output(GPIO_GUMSTIX_BTRESET, 1);
+ if (err) {
+ pr_err("gumstix: can't reset bluetooth\n");
+ return;
+ }
+ gpio_set_value(GPIO_GUMSTIX_BTRESET, 0);
+ udelay(100);
+ gpio_set_value(GPIO_GUMSTIX_BTRESET, 1);
+}
+#else
+static void gumstix_bluetooth_init(void)
+{
+ pr_debug("Gumstix Bluetooth is disabled\n");
}
#endif
+static unsigned long gumstix_pin_config[] __initdata = {
+#ifdef CONFIG_BT
+ GPIO12_32KHz,
+ /* BTUART */
+ GPIO42_HWUART_RXD,
+ GPIO43_HWUART_TXD,
+ GPIO44_HWUART_CTS,
+ GPIO45_HWUART_RTSL,
+#endif
+#ifdef CONFIG_MMC_PXA
+ /* MMC */
+ GPIO6_MMC_CLK,
+ GPIO53_MMC_CLK,
+ GPIO8_MMC_CS0,
+#endif
+ /* these are used by AM200EPD */
+ GPIO51_GPIO,
+ GPIO49_GPIO,
+ GPIO48_GPIO,
+ GPIO32_GPIO,
+ GPIO17_GPIO,
+ GPIO16_GPIO,
+};
+
static void __init gumstix_init(void)
{
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(gumstix_pin_config));
+
+ gumstix_bluetooth_init();
gumstix_udc_init();
gumstix_mmc_init();
(void) platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index e5b417d..1ffe773 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -22,6 +22,7 @@
#include <linux/platform_device.h>
#include <linux/suspend.h>
#include <linux/sysdev.h>
+#include <linux/delay.h>
#include <asm/hardware.h>
#include <asm/arch/irqs.h>
@@ -108,6 +109,30 @@ static const struct clkops clk_pxa25x_lcd_ops = {
.getrate = clk_pxa25x_lcd_getrate,
};
+static void clk_32k_enable(struct clk *clk)
+{
+ int timeout = 500;
+
+ OSCC |= OSCC_OON;
+ do {
+ if (OSCC & OSCC_OOK)
+ break;
+ udelay(1);
+ } while (--timeout);
+ if (!timeout)
+ pr_err("Failed to start 32kHz clock\n");
+}
+
+static void clk_32k_disable(struct clk *clk)
+{
+ OSCC &= ~OSCC_OON;
+}
+
+static const struct clkops clk_32k_ops = {
+ .enable = clk_32k_enable,
+ .disable = clk_32k_disable,
+};
+
/*
* 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz)
* 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
@@ -118,6 +143,12 @@ static struct clk pxa25x_hwuart_clk =
;
static struct clk pxa25x_clks[] = {
+ {
+ .name = "CLK_32K",
+ .ops = &clk_32k_ops,
+ .rate = 32000,
+ .delay = 70,
+ },
INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev),
INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev),
INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
diff --git a/include/asm-arm/arch-pxa/mfp-pxa25x.h b/include/asm-arm/arch-pxa/mfp-pxa25x.h
index 0499323..6c82a74 100644
--- a/include/asm-arm/arch-pxa/mfp-pxa25x.h
+++ b/include/asm-arm/arch-pxa/mfp-pxa25x.h
@@ -79,6 +79,7 @@
#define GPIO43_HWUART_TXD MFP_CFG_OUT(GPIO43, AF3, DRIVE_HIGH)
#define GPIO44_HWUART_CTS MFP_CFG_IN(GPIO44, AF3)
#define GPIO45_HWUART_RTS MFP_CFG_OUT(GPIO45, AF3, DRIVE_HIGH)
+#define GPIO45_HWUART_RTSL MFP_CFG_OUT(GPIO45, AF3, DRIVE_LOW)
#define GPIO48_HWUART_TXD MFP_CFG_OUT(GPIO48, AF1, DRIVE_HIGH)
#define GPIO49_HWUART_RXD MFP_CFG_IN(GPIO49, AF1)
#define GPIO50_HWUART_CTS MFP_CFG_IN(GPIO50, AF1)
--
1.5.3.6
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 11+ messages in thread
end of thread, other threads:[~2008-05-31 5:39 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-30 12:28 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 1/5] pxafb: module unloading support Jaya Kumar
2008-05-30 17:04 ` Krzysztof Helt
2008-05-31 1:02 ` Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 2/5] pxafb: add shared framebuffer interface Jaya Kumar
2008-05-30 17:10 ` Krzysztof Helt
2008-05-31 0:49 ` Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 3/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 4/5] am200epd: remove am200epd platform device driver Jaya Kumar
2008-05-30 12:28 ` [RFC 2.6.26-rc3 5/5] am200epd: add mach-pxa support for am200epd Jaya Kumar
-- strict thread matches above, loose matches on Subject: below --
2008-05-31 4:41 [RFC 2.6.26-rc3 0/5] am200epd, pxafb, metronomefb changes v2 Jaya Kumar
2008-05-31 4:41 ` [RFC 2.6.26-rc3 3/5] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).