Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * am300epd.c -- Platform device for AM300 EPD kit
0003  *
0004  * Copyright (C) 2008, Jaya Kumar
0005  *
0006  * This file is subject to the terms and conditions of the GNU General Public
0007  * License. See the file COPYING in the main directory of this archive for
0008  * more details.
0009  *
0010  * This work was made possible by help and equipment support from E-Ink
0011  * Corporation. http://support.eink.com/community
0012  *
0013  * This driver is written to be used with the Broadsheet display controller.
0014  * on the AM300 EPD prototype kit/development kit with an E-Ink 800x600
0015  * Vizplex EPD on a Gumstix board using the Broadsheet interface board.
0016  *
0017  */
0018 
0019 #include <linux/module.h>
0020 #include <linux/kernel.h>
0021 #include <linux/errno.h>
0022 #include <linux/string.h>
0023 #include <linux/delay.h>
0024 #include <linux/interrupt.h>
0025 #include <linux/fb.h>
0026 #include <linux/init.h>
0027 #include <linux/platform_device.h>
0028 #include <linux/irq.h>
0029 #include <linux/gpio.h>
0030 
0031 #include "gumstix.h"
0032 #include "mfp-pxa25x.h"
0033 #include "irqs.h"
0034 #include <linux/platform_data/video-pxafb.h>
0035 
0036 #include "generic.h"
0037 
0038 #include <video/broadsheetfb.h>
0039 
0040 static unsigned int panel_type = 6;
0041 static struct platform_device *am300_device;
0042 static struct broadsheet_board am300_board;
0043 
0044 static unsigned long am300_pin_config[] __initdata = {
0045     GPIO16_GPIO,
0046     GPIO17_GPIO,
0047     GPIO32_GPIO,
0048     GPIO48_GPIO,
0049     GPIO49_GPIO,
0050     GPIO51_GPIO,
0051     GPIO74_GPIO,
0052     GPIO75_GPIO,
0053     GPIO76_GPIO,
0054     GPIO77_GPIO,
0055 
0056     /* this is the 16-bit hdb bus 58-73 */
0057     GPIO58_GPIO,
0058     GPIO59_GPIO,
0059     GPIO60_GPIO,
0060     GPIO61_GPIO,
0061 
0062     GPIO62_GPIO,
0063     GPIO63_GPIO,
0064     GPIO64_GPIO,
0065     GPIO65_GPIO,
0066 
0067     GPIO66_GPIO,
0068     GPIO67_GPIO,
0069     GPIO68_GPIO,
0070     GPIO69_GPIO,
0071 
0072     GPIO70_GPIO,
0073     GPIO71_GPIO,
0074     GPIO72_GPIO,
0075     GPIO73_GPIO,
0076 };
0077 
0078 /* register offsets for gpio control */
0079 #define PWR_GPIO_PIN    16
0080 #define CFG_GPIO_PIN    17
0081 #define RDY_GPIO_PIN    32
0082 #define DC_GPIO_PIN 48
0083 #define RST_GPIO_PIN    49
0084 #define LED_GPIO_PIN    51
0085 #define RD_GPIO_PIN 74
0086 #define WR_GPIO_PIN 75
0087 #define CS_GPIO_PIN 76
0088 #define IRQ_GPIO_PIN    77
0089 
0090 /* hdb bus */
0091 #define DB0_GPIO_PIN    58
0092 #define DB15_GPIO_PIN   73
0093 
0094 static int gpios[] = { PWR_GPIO_PIN, CFG_GPIO_PIN, RDY_GPIO_PIN, DC_GPIO_PIN,
0095             RST_GPIO_PIN, RD_GPIO_PIN, WR_GPIO_PIN, CS_GPIO_PIN,
0096             IRQ_GPIO_PIN, LED_GPIO_PIN };
0097 static char *gpio_names[] = { "PWR", "CFG", "RDY", "DC", "RST", "RD", "WR",
0098                 "CS", "IRQ", "LED" };
0099 
0100 static int am300_wait_event(struct broadsheetfb_par *par)
0101 {
0102     /* todo: improve err recovery */
0103     wait_event(par->waitq, gpio_get_value(RDY_GPIO_PIN));
0104     return 0;
0105 }
0106 
0107 static int am300_init_gpio_regs(struct broadsheetfb_par *par)
0108 {
0109     int i;
0110     int err;
0111     char dbname[8];
0112 
0113     for (i = 0; i < ARRAY_SIZE(gpios); i++) {
0114         err = gpio_request(gpios[i], gpio_names[i]);
0115         if (err) {
0116             dev_err(&am300_device->dev, "failed requesting "
0117                 "gpio %s, err=%d\n", gpio_names[i], err);
0118             goto err_req_gpio;
0119         }
0120     }
0121 
0122     /* we also need to take care of the hdb bus */
0123     for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++) {
0124         sprintf(dbname, "DB%d", i);
0125         err = gpio_request(i, dbname);
0126         if (err) {
0127             dev_err(&am300_device->dev, "failed requesting "
0128                 "gpio %d, err=%d\n", i, err);
0129             goto err_req_gpio2;
0130         }
0131     }
0132 
0133     /* setup the outputs and init values */
0134     gpio_direction_output(PWR_GPIO_PIN, 0);
0135     gpio_direction_output(CFG_GPIO_PIN, 1);
0136     gpio_direction_output(DC_GPIO_PIN, 0);
0137     gpio_direction_output(RD_GPIO_PIN, 1);
0138     gpio_direction_output(WR_GPIO_PIN, 1);
0139     gpio_direction_output(CS_GPIO_PIN, 1);
0140     gpio_direction_output(RST_GPIO_PIN, 0);
0141 
0142     /* setup the inputs */
0143     gpio_direction_input(RDY_GPIO_PIN);
0144     gpio_direction_input(IRQ_GPIO_PIN);
0145 
0146     /* start the hdb bus as an input */
0147     for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
0148         gpio_direction_output(i, 0);
0149 
0150     /* go into command mode */
0151     gpio_set_value(CFG_GPIO_PIN, 1);
0152     gpio_set_value(RST_GPIO_PIN, 0);
0153     msleep(10);
0154     gpio_set_value(RST_GPIO_PIN, 1);
0155     msleep(10);
0156     am300_wait_event(par);
0157 
0158     return 0;
0159 
0160 err_req_gpio2:
0161     while (--i >= DB0_GPIO_PIN)
0162         gpio_free(i);
0163     i = ARRAY_SIZE(gpios);
0164 err_req_gpio:
0165     while (--i >= 0)
0166         gpio_free(gpios[i]);
0167 
0168     return err;
0169 }
0170 
0171 static int am300_init_board(struct broadsheetfb_par *par)
0172 {
0173     return am300_init_gpio_regs(par);
0174 }
0175 
0176 static void am300_cleanup(struct broadsheetfb_par *par)
0177 {
0178     int i;
0179 
0180     free_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), par);
0181 
0182     for (i = 0; i < ARRAY_SIZE(gpios); i++)
0183         gpio_free(gpios[i]);
0184 
0185     for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
0186         gpio_free(i);
0187 
0188 }
0189 
0190 static u16 am300_get_hdb(struct broadsheetfb_par *par)
0191 {
0192     u16 res = 0;
0193     int i;
0194 
0195     for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
0196         res |= (gpio_get_value(DB0_GPIO_PIN + i)) ? (1 << i) : 0;
0197 
0198     return res;
0199 }
0200 
0201 static void am300_set_hdb(struct broadsheetfb_par *par, u16 data)
0202 {
0203     int i;
0204 
0205     for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
0206         gpio_set_value(DB0_GPIO_PIN + i, (data >> i) & 0x01);
0207 }
0208 
0209 
0210 static void am300_set_ctl(struct broadsheetfb_par *par, unsigned char bit,
0211                 u8 state)
0212 {
0213     switch (bit) {
0214     case BS_CS:
0215         gpio_set_value(CS_GPIO_PIN, state);
0216         break;
0217     case BS_DC:
0218         gpio_set_value(DC_GPIO_PIN, state);
0219         break;
0220     case BS_WR:
0221         gpio_set_value(WR_GPIO_PIN, state);
0222         break;
0223     }
0224 }
0225 
0226 static int am300_get_panel_type(void)
0227 {
0228     return panel_type;
0229 }
0230 
0231 static irqreturn_t am300_handle_irq(int irq, void *dev_id)
0232 {
0233     struct broadsheetfb_par *par = dev_id;
0234 
0235     wake_up(&par->waitq);
0236     return IRQ_HANDLED;
0237 }
0238 
0239 static int am300_setup_irq(struct fb_info *info)
0240 {
0241     int ret;
0242     struct broadsheetfb_par *par = info->par;
0243 
0244     ret = request_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), am300_handle_irq,
0245                 IRQF_TRIGGER_RISING, "AM300", par);
0246     if (ret)
0247         dev_err(&am300_device->dev, "request_irq failed: %d\n", ret);
0248 
0249     return ret;
0250 }
0251 
0252 static struct broadsheet_board am300_board = {
0253     .owner          = THIS_MODULE,
0254     .init           = am300_init_board,
0255     .cleanup        = am300_cleanup,
0256     .set_hdb        = am300_set_hdb,
0257     .get_hdb        = am300_get_hdb,
0258     .set_ctl        = am300_set_ctl,
0259     .wait_for_rdy       = am300_wait_event,
0260     .get_panel_type     = am300_get_panel_type,
0261     .setup_irq      = am300_setup_irq,
0262 };
0263 
0264 int __init am300_init(void)
0265 {
0266     int ret;
0267 
0268     pxa2xx_mfp_config(ARRAY_AND_SIZE(am300_pin_config));
0269 
0270     /* request our platform independent driver */
0271     request_module("broadsheetfb");
0272 
0273     am300_device = platform_device_alloc("broadsheetfb", -1);
0274     if (!am300_device)
0275         return -ENOMEM;
0276 
0277     /* the am300_board that will be seen by broadsheetfb is a copy */
0278     platform_device_add_data(am300_device, &am300_board,
0279                     sizeof(am300_board));
0280 
0281     ret = platform_device_add(am300_device);
0282 
0283     if (ret) {
0284         platform_device_put(am300_device);
0285         return ret;
0286     }
0287 
0288     return 0;
0289 }
0290 
0291 module_param(panel_type, uint, 0);
0292 MODULE_PARM_DESC(panel_type, "Select the panel type: 37, 6, 97");
0293 
0294 MODULE_DESCRIPTION("board driver for am300 epd kit");
0295 MODULE_AUTHOR("Jaya Kumar");
0296 MODULE_LICENSE("GPL");