PageRenderTime 55ms CodeModel.GetById 11ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/arm/mach-pxa/am300epd.c

https://github.com/AICP/kernel_asus_grouper
C | 296 lines | 214 code | 54 blank | 28 comment | 15 complexity | ac3c49161b7dd91d81337b14b4064a30 MD5 | raw 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>
 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			goto err_req_gpio2;
129		}
130	}
131
132	/* setup the outputs and init values */
133	gpio_direction_output(PWR_GPIO_PIN, 0);
134	gpio_direction_output(CFG_GPIO_PIN, 1);
135	gpio_direction_output(DC_GPIO_PIN, 0);
136	gpio_direction_output(RD_GPIO_PIN, 1);
137	gpio_direction_output(WR_GPIO_PIN, 1);
138	gpio_direction_output(CS_GPIO_PIN, 1);
139	gpio_direction_output(RST_GPIO_PIN, 0);
140
141	/* setup the inputs */
142	gpio_direction_input(RDY_GPIO_PIN);
143	gpio_direction_input(IRQ_GPIO_PIN);
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 */
150	gpio_set_value(CFG_GPIO_PIN, 1);
151	gpio_set_value(RST_GPIO_PIN, 0);
152	msleep(10);
153	gpio_set_value(RST_GPIO_PIN, 1);
154	msleep(10);
155	am300_wait_event(par);
156
157	return 0;
158
159err_req_gpio2:
160	while (--i >= DB0_GPIO_PIN)
161		gpio_free(i);
162	i = ARRAY_SIZE(gpios);
163err_req_gpio:
164	while (--i >= 0)
165		gpio_free(gpios[i]);
166
167	return err;
168}
169
170static int am300_init_board(struct broadsheetfb_par *par)
171{
172	return am300_init_gpio_regs(par);
173}
174
175static void am300_cleanup(struct broadsheetfb_par *par)
176{
177	int i;
178
179	free_irq(IRQ_GPIO(RDY_GPIO_PIN), par);
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
189static 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
200static 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
209static 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
225static int am300_get_panel_type(void)
226{
227	return panel_type;
228}
229
230static 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
238static int am300_setup_irq(struct fb_info *info)
239{
240	int ret;
241	struct broadsheetfb_par *par = info->par;
242
243	ret = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am300_handle_irq,
244				IRQF_DISABLED|IRQF_TRIGGER_RISING,
245				"AM300", par);
246	if (ret)
247		dev_err(&am300_device->dev, "request_irq failed: %d\n", ret);
248
249	return ret;
250}
251
252static 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
264int __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
291module_param(panel_type, uint, 0);
292MODULE_PARM_DESC(panel_type, "Select the panel type: 37, 6, 97");
293
294MODULE_DESCRIPTION("board driver for am300 epd kit");
295MODULE_AUTHOR("Jaya Kumar");
296MODULE_LICENSE("GPL");