Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arm/mach-pxa/am300epd.c
29266 views
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 "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
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
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
171
static int am300_init_board(struct broadsheetfb_par *par)
172
{
173
return am300_init_gpio_regs(par);
174
}
175
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
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
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
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
226
static int am300_get_panel_type(void)
227
{
228
return panel_type;
229
}
230
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
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
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
298