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