-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 94196 b: refs/heads/master c: 03c33a4 h: refs/heads/master v: v3
- Loading branch information
Jaya Kumar
authored and
Linus Torvalds
committed
Apr 28, 2008
1 parent
525c4a7
commit 4f986fa
Showing
7 changed files
with
423 additions
and
283 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: 963654a9c919d18f8b9137f8ffd9d2d30a139269 | ||
refs/heads/master: 03c33a4f002b2521debf1efc269cade983b6e86a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,295 @@ | ||
/* | ||
* 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"); |
Oops, something went wrong.