Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
am300epd.c
Go to the documentation of this file.
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>
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 = {
54 
55  /* this is the 16-bit hdb bus 58-73 */
60 
65 
70 
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,
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 */
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  goto err_req_gpio2;
129  }
130  }
131 
132  /* setup the outputs and init values */
140 
141  /* setup the inputs */
144 
145  /* start the hdb bus as an input */
146  for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
147  gpio_direction_output(i, 0);
148 
149  /* go into command mode */
152  msleep(10);
154  msleep(10);
155  am300_wait_event(par);
156 
157  return 0;
158 
159 err_req_gpio2:
160  while (--i >= DB0_GPIO_PIN)
161  gpio_free(i);
162  i = ARRAY_SIZE(gpios);
163 err_req_gpio:
164  while (--i >= 0)
165  gpio_free(gpios[i]);
166 
167  return err;
168 }
169 
170 static int am300_init_board(struct broadsheetfb_par *par)
171 {
172  return am300_init_gpio_regs(par);
173 }
174 
175 static void am300_cleanup(struct broadsheetfb_par *par)
176 {
177  int i;
178 
180 
181  for (i = 0; i < ARRAY_SIZE(gpios); i++)
182  gpio_free(gpios[i]);
183 
184  for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
185  gpio_free(i);
186 
187 }
188 
189 static u16 am300_get_hdb(struct broadsheetfb_par *par)
190 {
191  u16 res = 0;
192  int i;
193 
194  for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
195  res |= (gpio_get_value(DB0_GPIO_PIN + i)) ? (1 << i) : 0;
196 
197  return res;
198 }
199 
200 static void am300_set_hdb(struct broadsheetfb_par *par, u16 data)
201 {
202  int i;
203 
204  for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
205  gpio_set_value(DB0_GPIO_PIN + i, (data >> i) & 0x01);
206 }
207 
208 
209 static void am300_set_ctl(struct broadsheetfb_par *par, unsigned char bit,
210  u8 state)
211 {
212  switch (bit) {
213  case BS_CS:
214  gpio_set_value(CS_GPIO_PIN, state);
215  break;
216  case BS_DC:
217  gpio_set_value(DC_GPIO_PIN, state);
218  break;
219  case BS_WR:
220  gpio_set_value(WR_GPIO_PIN, state);
221  break;
222  }
223 }
224 
225 static int am300_get_panel_type(void)
226 {
227  return panel_type;
228 }
229 
230 static irqreturn_t am300_handle_irq(int irq, void *dev_id)
231 {
232  struct broadsheetfb_par *par = dev_id;
233 
234  wake_up(&par->waitq);
235  return IRQ_HANDLED;
236 }
237 
238 static int am300_setup_irq(struct fb_info *info)
239 {
240  int ret;
241  struct broadsheetfb_par *par = info->par;
242 
243  ret = request_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), am300_handle_irq,
245  "AM300", par);
246  if (ret)
247  dev_err(&am300_device->dev, "request_irq failed: %d\n", ret);
248 
249  return ret;
250 }
251 
252 static 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 
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 
292 MODULE_PARM_DESC(panel_type, "Select the panel type: 37, 6, 97");
293 
294 MODULE_DESCRIPTION("board driver for am300 epd kit");
295 MODULE_AUTHOR("Jaya Kumar");
296 MODULE_LICENSE("GPL");