• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <mach/irqs.h>
34 #include <linux/platform_data/video-pxafb.h>
35 
36 #include "generic.h"
37 
38 #include <video/broadsheetfb.h>
39 
40 static unsigned int panel_type = 6;
41 static struct platform_device *am300_device;
42 static struct broadsheet_board am300_board;
43 
44 static 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 
94 static 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 };
97 static char *gpio_names[] = { "PWR", "CFG", "RDY", "DC", "RST", "RD", "WR",
98 				"CS", "IRQ", "LED" };
99 
am300_wait_event(struct broadsheetfb_par * par)100 static 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 
am300_init_gpio_regs(struct broadsheetfb_par * par)107 static 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 
160 err_req_gpio2:
161 	while (--i >= DB0_GPIO_PIN)
162 		gpio_free(i);
163 	i = ARRAY_SIZE(gpios);
164 err_req_gpio:
165 	while (--i >= 0)
166 		gpio_free(gpios[i]);
167 
168 	return err;
169 }
170 
am300_init_board(struct broadsheetfb_par * par)171 static int am300_init_board(struct broadsheetfb_par *par)
172 {
173 	return am300_init_gpio_regs(par);
174 }
175 
am300_cleanup(struct broadsheetfb_par * par)176 static 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 
am300_get_hdb(struct broadsheetfb_par * par)190 static 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 
am300_set_hdb(struct broadsheetfb_par * par,u16 data)201 static 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 
am300_set_ctl(struct broadsheetfb_par * par,unsigned char bit,u8 state)210 static 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 
am300_get_panel_type(void)226 static int am300_get_panel_type(void)
227 {
228 	return panel_type;
229 }
230 
am300_handle_irq(int irq,void * dev_id)231 static 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 
am300_setup_irq(struct fb_info * info)239 static 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 
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 
am300_init(void)264 int __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 
291 module_param(panel_type, uint, 0);
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");
297