• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/arm/mach-pxa/
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
39static unsigned int panel_type = 6;
40static struct platform_device *am300_device;
41static struct broadsheet_board am300_board;
42
43static 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
93static 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 };
96static char *gpio_names[] = { "PWR", "CFG", "RDY", "DC", "RST", "RD", "WR",
97				"CS", "IRQ", "LED" };
98
99static 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
106static 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
162err_req_gpio:
163	while (i > 0)
164		gpio_free(gpios[i--]);
165
166	return err;
167}
168
169static int am300_init_board(struct broadsheetfb_par *par)
170{
171	return am300_init_gpio_regs(par);
172}
173
174static 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
188static 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
199static 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
208static 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
224static int am300_get_panel_type(void)
225{
226	return panel_type;
227}
228
229static 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
237static 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
251static 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
263int __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
290module_param(panel_type, uint, 0);
291MODULE_PARM_DESC(panel_type, "Select the panel type: 37, 6, 97");
292
293MODULE_DESCRIPTION("board driver for am300 epd kit");
294MODULE_AUTHOR("Jaya Kumar");
295MODULE_LICENSE("GPL");
296