broadsheetfb: add multiple panel type support
[linux-2.6.git] / arch / arm / mach-pxa / am300epd.c
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");