am300epd.c (6597B)
1/* 2 * am300epd.c -- Platform device for AM300 EPD kit 3 * 4 * Copyright (C) 2008, Jaya Kumar 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file COPYING in the main directory of this archive for 8 * more details. 9 * 10 * This work was made possible by help and equipment support from E-Ink 11 * Corporation. http://support.eink.com/community 12 * 13 * This driver is written to be used with the Broadsheet display controller. 14 * on the AM300 EPD prototype kit/development kit with an E-Ink 800x600 15 * Vizplex EPD on a Gumstix board using the Broadsheet interface board. 16 * 17 */ 18 19#include <linux/module.h> 20#include <linux/kernel.h> 21#include <linux/errno.h> 22#include <linux/string.h> 23#include <linux/delay.h> 24#include <linux/interrupt.h> 25#include <linux/fb.h> 26#include <linux/init.h> 27#include <linux/platform_device.h> 28#include <linux/irq.h> 29#include <linux/gpio.h> 30 31#include "gumstix.h" 32#include "mfp-pxa25x.h" 33#include "irqs.h" 34#include <linux/platform_data/video-pxafb.h> 35 36#include "generic.h" 37 38#include <video/broadsheetfb.h> 39 40static unsigned int panel_type = 6; 41static struct platform_device *am300_device; 42static struct broadsheet_board am300_board; 43 44static unsigned long am300_pin_config[] __initdata = { 45 GPIO16_GPIO, 46 GPIO17_GPIO, 47 GPIO32_GPIO, 48 GPIO48_GPIO, 49 GPIO49_GPIO, 50 GPIO51_GPIO, 51 GPIO74_GPIO, 52 GPIO75_GPIO, 53 GPIO76_GPIO, 54 GPIO77_GPIO, 55 56 /* this is the 16-bit hdb bus 58-73 */ 57 GPIO58_GPIO, 58 GPIO59_GPIO, 59 GPIO60_GPIO, 60 GPIO61_GPIO, 61 62 GPIO62_GPIO, 63 GPIO63_GPIO, 64 GPIO64_GPIO, 65 GPIO65_GPIO, 66 67 GPIO66_GPIO, 68 GPIO67_GPIO, 69 GPIO68_GPIO, 70 GPIO69_GPIO, 71 72 GPIO70_GPIO, 73 GPIO71_GPIO, 74 GPIO72_GPIO, 75 GPIO73_GPIO, 76}; 77 78/* register offsets for gpio control */ 79#define PWR_GPIO_PIN 16 80#define CFG_GPIO_PIN 17 81#define RDY_GPIO_PIN 32 82#define DC_GPIO_PIN 48 83#define RST_GPIO_PIN 49 84#define LED_GPIO_PIN 51 85#define RD_GPIO_PIN 74 86#define WR_GPIO_PIN 75 87#define CS_GPIO_PIN 76 88#define IRQ_GPIO_PIN 77 89 90/* hdb bus */ 91#define DB0_GPIO_PIN 58 92#define DB15_GPIO_PIN 73 93 94static int gpios[] = { PWR_GPIO_PIN, CFG_GPIO_PIN, RDY_GPIO_PIN, DC_GPIO_PIN, 95 RST_GPIO_PIN, RD_GPIO_PIN, WR_GPIO_PIN, CS_GPIO_PIN, 96 IRQ_GPIO_PIN, LED_GPIO_PIN }; 97static char *gpio_names[] = { "PWR", "CFG", "RDY", "DC", "RST", "RD", "WR", 98 "CS", "IRQ", "LED" }; 99 100static int am300_wait_event(struct broadsheetfb_par *par) 101{ 102 /* todo: improve err recovery */ 103 wait_event(par->waitq, gpio_get_value(RDY_GPIO_PIN)); 104 return 0; 105} 106 107static int am300_init_gpio_regs(struct broadsheetfb_par *par) 108{ 109 int i; 110 int err; 111 char dbname[8]; 112 113 for (i = 0; i < ARRAY_SIZE(gpios); i++) { 114 err = gpio_request(gpios[i], gpio_names[i]); 115 if (err) { 116 dev_err(&am300_device->dev, "failed requesting " 117 "gpio %s, err=%d\n", gpio_names[i], err); 118 goto err_req_gpio; 119 } 120 } 121 122 /* we also need to take care of the hdb bus */ 123 for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++) { 124 sprintf(dbname, "DB%d", i); 125 err = gpio_request(i, dbname); 126 if (err) { 127 dev_err(&am300_device->dev, "failed requesting " 128 "gpio %d, err=%d\n", i, err); 129 goto err_req_gpio2; 130 } 131 } 132 133 /* setup the outputs and init values */ 134 gpio_direction_output(PWR_GPIO_PIN, 0); 135 gpio_direction_output(CFG_GPIO_PIN, 1); 136 gpio_direction_output(DC_GPIO_PIN, 0); 137 gpio_direction_output(RD_GPIO_PIN, 1); 138 gpio_direction_output(WR_GPIO_PIN, 1); 139 gpio_direction_output(CS_GPIO_PIN, 1); 140 gpio_direction_output(RST_GPIO_PIN, 0); 141 142 /* setup the inputs */ 143 gpio_direction_input(RDY_GPIO_PIN); 144 gpio_direction_input(IRQ_GPIO_PIN); 145 146 /* start the hdb bus as an input */ 147 for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++) 148 gpio_direction_output(i, 0); 149 150 /* go into command mode */ 151 gpio_set_value(CFG_GPIO_PIN, 1); 152 gpio_set_value(RST_GPIO_PIN, 0); 153 msleep(10); 154 gpio_set_value(RST_GPIO_PIN, 1); 155 msleep(10); 156 am300_wait_event(par); 157 158 return 0; 159 160err_req_gpio2: 161 while (--i >= DB0_GPIO_PIN) 162 gpio_free(i); 163 i = ARRAY_SIZE(gpios); 164err_req_gpio: 165 while (--i >= 0) 166 gpio_free(gpios[i]); 167 168 return err; 169} 170 171static int am300_init_board(struct broadsheetfb_par *par) 172{ 173 return am300_init_gpio_regs(par); 174} 175 176static void am300_cleanup(struct broadsheetfb_par *par) 177{ 178 int i; 179 180 free_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), par); 181 182 for (i = 0; i < ARRAY_SIZE(gpios); i++) 183 gpio_free(gpios[i]); 184 185 for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++) 186 gpio_free(i); 187 188} 189 190static u16 am300_get_hdb(struct broadsheetfb_par *par) 191{ 192 u16 res = 0; 193 int i; 194 195 for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++) 196 res |= (gpio_get_value(DB0_GPIO_PIN + i)) ? (1 << i) : 0; 197 198 return res; 199} 200 201static void am300_set_hdb(struct broadsheetfb_par *par, u16 data) 202{ 203 int i; 204 205 for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++) 206 gpio_set_value(DB0_GPIO_PIN + i, (data >> i) & 0x01); 207} 208 209 210static void am300_set_ctl(struct broadsheetfb_par *par, unsigned char bit, 211 u8 state) 212{ 213 switch (bit) { 214 case BS_CS: 215 gpio_set_value(CS_GPIO_PIN, state); 216 break; 217 case BS_DC: 218 gpio_set_value(DC_GPIO_PIN, state); 219 break; 220 case BS_WR: 221 gpio_set_value(WR_GPIO_PIN, state); 222 break; 223 } 224} 225 226static int am300_get_panel_type(void) 227{ 228 return panel_type; 229} 230 231static irqreturn_t am300_handle_irq(int irq, void *dev_id) 232{ 233 struct broadsheetfb_par *par = dev_id; 234 235 wake_up(&par->waitq); 236 return IRQ_HANDLED; 237} 238 239static int am300_setup_irq(struct fb_info *info) 240{ 241 int ret; 242 struct broadsheetfb_par *par = info->par; 243 244 ret = request_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), am300_handle_irq, 245 IRQF_TRIGGER_RISING, "AM300", par); 246 if (ret) 247 dev_err(&am300_device->dev, "request_irq failed: %d\n", ret); 248 249 return ret; 250} 251 252static struct broadsheet_board am300_board = { 253 .owner = THIS_MODULE, 254 .init = am300_init_board, 255 .cleanup = am300_cleanup, 256 .set_hdb = am300_set_hdb, 257 .get_hdb = am300_get_hdb, 258 .set_ctl = am300_set_ctl, 259 .wait_for_rdy = am300_wait_event, 260 .get_panel_type = am300_get_panel_type, 261 .setup_irq = am300_setup_irq, 262}; 263 264int __init am300_init(void) 265{ 266 int ret; 267 268 pxa2xx_mfp_config(ARRAY_AND_SIZE(am300_pin_config)); 269 270 /* request our platform independent driver */ 271 request_module("broadsheetfb"); 272 273 am300_device = platform_device_alloc("broadsheetfb", -1); 274 if (!am300_device) 275 return -ENOMEM; 276 277 /* the am300_board that will be seen by broadsheetfb is a copy */ 278 platform_device_add_data(am300_device, &am300_board, 279 sizeof(am300_board)); 280 281 ret = platform_device_add(am300_device); 282 283 if (ret) { 284 platform_device_put(am300_device); 285 return ret; 286 } 287 288 return 0; 289} 290 291module_param(panel_type, uint, 0); 292MODULE_PARM_DESC(panel_type, "Select the panel type: 37, 6, 97"); 293 294MODULE_DESCRIPTION("board driver for am300 epd kit"); 295MODULE_AUTHOR("Jaya Kumar"); 296MODULE_LICENSE("GPL");