From: Jaya Kumar <jayakumar.lkml@gmail.com>
To: ymiao3@marvell.com
Cc: Jaya Kumar <jayakumar.lkml@gmail.com>,
linux-fbdev-devel@lists.sourceforge.net,
linux-arm-kernel@lists.arm.linux.org.uk
Subject: [RFC 2.6.26-rc3 5/7] am200epd: convert to shared fb and use gpio api
Date: Sat, 7 Jun 2008 00:49:24 -0400 [thread overview]
Message-ID: <1212814166-10313-6-git-send-email-jayakumar.lkml@gmail.com> (raw)
In-Reply-To: <1212814166-10313-1-git-send-email-jayakumar.lkml@gmail.com>
This patch converts am200epd to use pxafb's fb and to stop performing
direct access to LCDC registers. It now uses the generic GPIO api.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
---
arch/arm/mach-pxa/am200epd.c | 342 ++++++++++++++++++++++++------------------
arch/arm/mach-pxa/devices.c | 1 +
2 files changed, 198 insertions(+), 145 deletions(-)
diff --git a/arch/arm/mach-pxa/am200epd.c b/arch/arm/mach-pxa/am200epd.c
index 51e26c1..7aeee2c 100644
--- a/arch/arm/mach-pxa/am200epd.c
+++ b/arch/arm/mach-pxa/am200epd.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/video/am200epd.c -- Platform device for AM200 EPD kit
+ * am200epd.c -- Platform device for AM200 EPD kit
*
* Copyright (C) 2008, Jaya Kumar
*
@@ -18,6 +18,8 @@
*
*/
+#define DEBUG 1
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -27,13 +29,72 @@
#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 <linux/gpio.h>
+
+#include <asm/arch/pxafb.h>
#include <video/metronomefb.h>
-#include <asm/arch/pxa-regs.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
@@ -42,163 +103,144 @@
#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" };
-#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)
+static int am200_init_gpio_regs(struct metronomefb_par *par)
{
- u8 index;
+ 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;
+ }
+ }
- index = pin >> 4;
+ gpio_direction_output(LED_GPIO_PIN, 0);
+ gpio_direction_output(STDBY_GPIO_PIN, 0);
+ gpio_direction_output(RST_GPIO_PIN, 0);
- 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");
- }
+ 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 __devinit am200_init_gpio_pin(int pin, int dir)
+static void am200_cleanup(struct metronomefb_par *par)
{
- 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));
+ int i;
- 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));
+ free_irq(IRQ_GPIO(RDY_GPIO_PIN), par->info);
- if (dir)
- GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
- else
- GPDR1 |= (1 << GPDR1_OFFSET(pin));
- break;
- default:
- printk(KERN_ERR "unimplemented\n");
- }
+ for (i = 0; i < ARRAY_SIZE(gpios); i++)
+ gpio_free(gpios[i]);
}
-static void am200_init_gpio_regs(struct metronomefb_par *par)
+static struct platform_device *am200_pxa_device_fb;
+
+static int am200_pxa_register_device(struct platform_device *dev,
+ struct pxafb_mach_info *data)
{
- am200_init_gpio_pin(LED_GPIO_PIN, 0);
- am200_set_gpio_output(LED_GPIO_PIN, 0);
+ int ret;
- am200_init_gpio_pin(STDBY_GPIO_PIN, 0);
- am200_set_gpio_output(STDBY_GPIO_PIN, 0);
+ am200_pxa_device_fb = platform_device_alloc("pxa2xx-fb", -1);
+ if (!am200_pxa_device_fb)
+ return -ENOMEM;
- am200_init_gpio_pin(RST_GPIO_PIN, 0);
- am200_set_gpio_output(RST_GPIO_PIN, 0);
+ platform_device_add_data(am200_pxa_device_fb, data, sizeof(*data));
- am200_init_gpio_pin(RDY_GPIO_PIN, 1);
+ platform_device_add_resources(am200_pxa_device_fb,
+ pxa_device_fb.resource,
+ pxa_device_fb.num_resources);
- am200_init_gpio_pin(ERR_GPIO_PIN, 1);
+ 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;
- am200_init_gpio_pin(PCBPWR_GPIO_PIN, 0);
- am200_set_gpio_output(PCBPWR_GPIO_PIN, 0);
-}
+ ret = platform_device_add(am200_pxa_device_fb);
-static void am200_disable_lcd_controller(struct metronomefb_par *par)
-{
- LCSR = 0xffffffff; /* Clear LCD Status Register */
- LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */
+ if (ret) {
+ dev_err(&am200_device->dev, "failed adding pxafb %d\n", ret);
+ platform_device_put(am200_pxa_device_fb);
+ }
- /* we reset and just wait for things to settle */
- msleep(200);
+ return ret;
}
-static void am200_enable_lcd_controller(struct metronomefb_par *par)
+static int am200_share_video_mem(unsigned char *video_mem, dma_addr_t dma,
+ struct module *fbmaster, void *data)
{
- LCSR = 0xffffffff;
- FDADR0 = par->metromem_desc_dma;
- LCCR0 |= LCCR0_ENB;
+ 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_init_lcdc_regs(struct metronomefb_par *par)
+static void am200_unshare_video_mem(void *data)
{
- /* 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 */
+ 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 void am200_post_dma_setup(struct metronomefb_par *par)
+static int am200_setup_fb(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);
+ 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 void am200_free_irq(struct fb_info *info)
+static int am200_get_panel_type(void)
{
- free_irq(IRQ_GPIO(RDY_GPIO_PIN), info);
+ return panel_type;
}
static irqreturn_t am200_handle_irq(int irq, void *dev_id)
@@ -212,53 +254,59 @@ static irqreturn_t am200_handle_irq(int irq, void *dev_id)
static int am200_setup_irq(struct fb_info *info)
{
- int retval;
+ int ret;
- retval = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am200_handle_irq,
+ ret = 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;
+ if (ret) {
+ dev_err(&am200_device->dev, "request_irq failed: %d\n", ret);
+ return ret;
}
- return set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQT_FALLING);
+ 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)
{
- am200_set_gpio_output(RST_GPIO_PIN, state);
+ gpio_set_value(RST_GPIO_PIN, state);
}
static void am200_set_stdby(struct metronomefb_par *par, int state)
{
- am200_set_gpio_output(STDBY_GPIO_PIN, state);
+ gpio_set_value(STDBY_GPIO_PIN, state);
}
static int am200_wait_event(struct metronomefb_par *par)
{
- return wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ);
+ return wait_event_timeout(par->waitq, gpio_get_value(RDY_GPIO_PIN), HZ);
}
static int am200_wait_event_intr(struct metronomefb_par *par)
{
- return wait_event_interruptible_timeout(par->waitq, (GPLR1 & 0x01), HZ);
+ 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,
- .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,
+ .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 struct platform_device *am200_device;
-
static int __init am200_init(void)
{
int ret;
@@ -284,9 +332,13 @@ static int __init am200_init(void)
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);
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)
{
--
1.5.3.6
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
next prev parent reply other threads:[~2008-06-07 5:47 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-07 4:49 [RFC 2.6.26-rc3 0/7] am200epd, pxafb, metronomefb changes v3 Jaya Kumar
2008-06-07 4:49 ` [RFC 2.6.26-rc3 1/7] pxafb: module unloading support Jaya Kumar
2008-06-07 8:35 ` Krzysztof Helt
2008-06-10 6:25 ` Eric Miao
2008-06-10 6:43 ` Lothar Waßmann
2008-06-10 7:44 ` Eric Miao
2008-06-12 4:36 ` Jaya Kumar
2008-06-12 5:25 ` Krzysztof Helt
2008-06-12 10:20 ` Eric Miao
2008-06-12 14:17 ` Jaya Kumar
2008-06-07 4:49 ` [RFC 2.6.26-rc3 2/7] pxafb: add shared framebuffer interface Jaya Kumar
2008-06-07 8:38 ` Krzysztof Helt
2008-06-07 4:49 ` [RFC 2.6.26-rc3 3/7] gumstix: conversion to MFP support and add bluetooth support Jaya Kumar
2008-06-07 4:49 ` [RFC 2.6.26-rc3 4/7] am200epd: move am200epd to mach-pxa Jaya Kumar
2008-06-07 8:40 ` Krzysztof Helt
2008-06-07 4:49 ` Jaya Kumar [this message]
2008-06-07 8:43 ` [RFC 2.6.26-rc3 5/7] am200epd: convert to shared fb and use gpio api Krzysztof Helt
2008-06-07 4:49 ` [RFC 2.6.26-rc3 6/7] metronomefb: convert printk to dev_dbg/err messages Jaya Kumar
2008-06-07 8:46 ` Krzysztof Helt
2008-06-07 4:49 ` [RFC 2.6.26-rc3 7/7] metronomefb: changes to use separate framebuffer Jaya Kumar
2008-06-07 8:59 ` Krzysztof Helt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1212814166-10313-6-git-send-email-jayakumar.lkml@gmail.com \
--to=jayakumar.lkml@gmail.com \
--cc=linux-arm-kernel@lists.arm.linux.org.uk \
--cc=linux-fbdev-devel@lists.sourceforge.net \
--cc=ymiao3@marvell.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).