aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaya Kumar <jayakumar.lkml@gmail.com>2008-04-28 05:15:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:41 -0400
commit0e27aa3dabb541edee9f23b37114856a528de01e (patch)
tree5516f7e6445f0bd95a1e4bbca2c3c678643b28a4
parent2422fbba0684ddf08898ec2f3cf23cb16a54b3f5 (diff)
fbdev: platforming hecubafb and n411
This patch splits hecubafb into the platform independent hecubafb and the platform dependent n411. Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com> Cc: "Antonino A. Daplas" <adaplas@pol.net> Cc: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/video/Kconfig17
-rw-r--r--drivers/video/hecubafb.c250
-rw-r--r--drivers/video/n411.c202
-rw-r--r--include/video/hecubafb.h51
4 files changed, 314 insertions, 206 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index ff6ea9a9be22..73d3afad7c50 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -178,6 +178,11 @@ config FB_METRONOME
178 depends on FB 178 depends on FB
179 depends on FB_DEFERRED_IO 179 depends on FB_DEFERRED_IO
180 180
181config FB_HECUBA
182 tristate
183 depends on FB
184 depends on FB_DEFERRED_IO
185
181config FB_SVGALIB 186config FB_SVGALIB
182 tristate 187 tristate
183 depends on FB 188 depends on FB
@@ -703,20 +708,18 @@ config FB_IMAC
703 help 708 help
704 This is the frame buffer device driver for the Intel-based Macintosh 709 This is the frame buffer device driver for the Intel-based Macintosh
705 710
706config FB_HECUBA 711config FB_N411
707 tristate "Hecuba board support" 712 tristate "N411 Apollo/Hecuba devkit support"
708 depends on FB && X86 && MMU 713 depends on FB && X86 && MMU
709 select FB_SYS_FILLRECT 714 select FB_SYS_FILLRECT
710 select FB_SYS_COPYAREA 715 select FB_SYS_COPYAREA
711 select FB_SYS_IMAGEBLIT 716 select FB_SYS_IMAGEBLIT
712 select FB_SYS_FOPS 717 select FB_SYS_FOPS
713 select FB_DEFERRED_IO 718 select FB_DEFERRED_IO
719 select FB_HECUBA
714 help 720 help
715 This enables support for the Hecuba board. This driver was tested 721 This enables support for the Apollo display controller in its
716 with an E-Ink 800x600 display and x86 SBCs through a 16 bit GPIO 722 Hecuba form using the n411 devkit.
717 interface (8 bit data, 4 bit control). If you anticipate using
718 this driver, say Y or M; otherwise say N. You must specify the
719 GPIO IO address to be used for setting control and data.
720 723
721config FB_HGA 724config FB_HGA
722 tristate "Hercules mono graphics support" 725 tristate "Hercules mono graphics support"
diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c
index b77d033665da..0b4bffbe67c8 100644
--- a/drivers/video/hecubafb.c
+++ b/drivers/video/hecubafb.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/drivers/video/hecubafb.c -- FB driver for Hecuba controller 2 * linux/drivers/video/hecubafb.c -- FB driver for Hecuba/Apollo controller
3 * 3 *
4 * Copyright (C) 2006, Jaya Kumar 4 * Copyright (C) 2006, Jaya Kumar
5 * This work was sponsored by CIS(M) Sdn Bhd 5 * This work was sponsored by CIS(M) Sdn Bhd
@@ -17,18 +17,13 @@
17 * values. There are other commands that the display is capable of, 17 * values. There are other commands that the display is capable of,
18 * beyond the 5 used here but they are more complex. 18 * beyond the 5 used here but they are more complex.
19 * 19 *
20 * This driver is written to be used with the Hecuba display controller 20 * This driver is written to be used with the Hecuba display architecture.
21 * board, and tested with the EInk 800x600 display in 1 bit mode. 21 * The actual display chip is called Apollo and the interface electronics
22 * The interface between Hecuba and the host is TTL based GPIO. The 22 * it needs is called Hecuba.
23 * GPIO requirements are 8 writable data lines and 6 lines for control.
24 * Only 4 of the controls are actually used here but 6 for future use.
25 * The driver requires the IO addresses for data and control GPIO at
26 * load time. It is also possible to use this display with a standard
27 * PC parallel port.
28 * 23 *
29 * General notes: 24 * It is intended to be architecture independent. A board specific driver
30 * - User must set hecubafb_enable=1 to enable it 25 * must be used to perform all the physical IO interactions. An example
31 * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR c2io_addr=0xIOADDR 26 * is provided as n411.c
32 * 27 *
33 */ 28 */
34 29
@@ -47,34 +42,12 @@
47#include <linux/list.h> 42#include <linux/list.h>
48#include <linux/uaccess.h> 43#include <linux/uaccess.h>
49 44
50/* Apollo controller specific defines */ 45#include <video/hecubafb.h>
51#define APOLLO_START_NEW_IMG 0xA0
52#define APOLLO_STOP_IMG_DATA 0xA1
53#define APOLLO_DISPLAY_IMG 0xA2
54#define APOLLO_ERASE_DISPLAY 0xA3
55#define APOLLO_INIT_DISPLAY 0xA4
56
57/* Hecuba interface specific defines */
58/* WUP is inverted, CD is inverted, DS is inverted */
59#define HCB_NWUP_BIT 0x01
60#define HCB_NDS_BIT 0x02
61#define HCB_RW_BIT 0x04
62#define HCB_NCD_BIT 0x08
63#define HCB_ACK_BIT 0x80
64 46
65/* Display specific information */ 47/* Display specific information */
66#define DPY_W 600 48#define DPY_W 600
67#define DPY_H 800 49#define DPY_H 800
68 50
69struct hecubafb_par {
70 unsigned long dio_addr;
71 unsigned long cio_addr;
72 unsigned long c2io_addr;
73 unsigned char ctl;
74 struct fb_info *info;
75 unsigned int irq;
76};
77
78static struct fb_fix_screeninfo hecubafb_fix __devinitdata = { 51static struct fb_fix_screeninfo hecubafb_fix __devinitdata = {
79 .id = "hecubafb", 52 .id = "hecubafb",
80 .type = FB_TYPE_PACKED_PIXELS, 53 .type = FB_TYPE_PACKED_PIXELS,
@@ -82,6 +55,7 @@ static struct fb_fix_screeninfo hecubafb_fix __devinitdata = {
82 .xpanstep = 0, 55 .xpanstep = 0,
83 .ypanstep = 0, 56 .ypanstep = 0,
84 .ywrapstep = 0, 57 .ywrapstep = 0,
58 .line_length = DPY_W,
85 .accel = FB_ACCEL_NONE, 59 .accel = FB_ACCEL_NONE,
86}; 60};
87 61
@@ -94,136 +68,51 @@ static struct fb_var_screeninfo hecubafb_var __devinitdata = {
94 .nonstd = 1, 68 .nonstd = 1,
95}; 69};
96 70
97static unsigned long dio_addr; 71/* main hecubafb functions */
98static unsigned long cio_addr;
99static unsigned long c2io_addr;
100static unsigned long splashval;
101static unsigned int nosplash;
102static unsigned int hecubafb_enable;
103static unsigned int irq;
104
105static DECLARE_WAIT_QUEUE_HEAD(hecubafb_waitq);
106
107static void hcb_set_ctl(struct hecubafb_par *par)
108{
109 outb(par->ctl, par->cio_addr);
110}
111
112static unsigned char hcb_get_ctl(struct hecubafb_par *par)
113{
114 return inb(par->c2io_addr);
115}
116
117static void hcb_set_data(struct hecubafb_par *par, unsigned char value)
118{
119 outb(value, par->dio_addr);
120}
121
122static int __devinit apollo_init_control(struct hecubafb_par *par)
123{
124 unsigned char ctl;
125 /* for init, we want the following setup to be set:
126 WUP = lo
127 ACK = hi
128 DS = hi
129 RW = hi
130 CD = lo
131 */
132
133 /* write WUP to lo, DS to hi, RW to hi, CD to lo */
134 par->ctl = HCB_NWUP_BIT | HCB_RW_BIT | HCB_NCD_BIT ;
135 par->ctl &= ~HCB_NDS_BIT;
136 hcb_set_ctl(par);
137
138 /* check ACK is not lo */
139 ctl = hcb_get_ctl(par);
140 if ((ctl & HCB_ACK_BIT)) {
141 printk(KERN_ERR "Fail because ACK is already low\n");
142 return -ENXIO;
143 }
144
145 return 0;
146}
147
148static void hcb_wait_for_ack(struct hecubafb_par *par)
149{
150
151 int timeout;
152 unsigned char ctl;
153
154 timeout=500;
155 do {
156 ctl = hcb_get_ctl(par);
157 if ((ctl & HCB_ACK_BIT))
158 return;
159 udelay(1);
160 } while (timeout--);
161 printk(KERN_ERR "timed out waiting for ack\n");
162}
163
164static void hcb_wait_for_ack_clear(struct hecubafb_par *par)
165{
166
167 int timeout;
168 unsigned char ctl;
169
170 timeout=500;
171 do {
172 ctl = hcb_get_ctl(par);
173 if (!(ctl & HCB_ACK_BIT))
174 return;
175 udelay(1);
176 } while (timeout--);
177 printk(KERN_ERR "timed out waiting for clear\n");
178}
179 72
180static void apollo_send_data(struct hecubafb_par *par, unsigned char data) 73static void apollo_send_data(struct hecubafb_par *par, unsigned char data)
181{ 74{
182 /* set data */ 75 /* set data */
183 hcb_set_data(par, data); 76 par->board->set_data(par, data);
184 77
185 /* set DS low */ 78 /* set DS low */
186 par->ctl |= HCB_NDS_BIT; 79 par->board->set_ctl(par, HCB_DS_BIT, 0);
187 hcb_set_ctl(par);
188 80
189 hcb_wait_for_ack(par); 81 /* wait for ack */
82 par->board->wait_for_ack(par, 0);
190 83
191 /* set DS hi */ 84 /* set DS hi */
192 par->ctl &= ~(HCB_NDS_BIT); 85 par->board->set_ctl(par, HCB_DS_BIT, 1);
193 hcb_set_ctl(par);
194 86
195 hcb_wait_for_ack_clear(par); 87 /* wait for ack to clear */
88 par->board->wait_for_ack(par, 1);
196} 89}
197 90
198static void apollo_send_command(struct hecubafb_par *par, unsigned char data) 91static void apollo_send_command(struct hecubafb_par *par, unsigned char data)
199{ 92{
200 /* command so set CD to high */ 93 /* command so set CD to high */
201 par->ctl &= ~(HCB_NCD_BIT); 94 par->board->set_ctl(par, HCB_CD_BIT, 1);
202 hcb_set_ctl(par);
203 95
204 /* actually strobe with command */ 96 /* actually strobe with command */
205 apollo_send_data(par, data); 97 apollo_send_data(par, data);
206 98
207 /* clear CD back to low */ 99 /* clear CD back to low */
208 par->ctl |= (HCB_NCD_BIT); 100 par->board->set_ctl(par, HCB_CD_BIT, 0);
209 hcb_set_ctl(par);
210} 101}
211 102
212/* main hecubafb functions */
213
214static void hecubafb_dpy_update(struct hecubafb_par *par) 103static void hecubafb_dpy_update(struct hecubafb_par *par)
215{ 104{
216 int i; 105 int i;
217 unsigned char *buf = (unsigned char __force *)par->info->screen_base; 106 unsigned char *buf = (unsigned char __force *)par->info->screen_base;
218 107
219 apollo_send_command(par, 0xA0); 108 apollo_send_command(par, APOLLO_START_NEW_IMG);
220 109
221 for (i=0; i < (DPY_W*DPY_H/8); i++) { 110 for (i=0; i < (DPY_W*DPY_H/8); i++) {
222 apollo_send_data(par, *(buf++)); 111 apollo_send_data(par, *(buf++));
223 } 112 }
224 113
225 apollo_send_command(par, 0xA1); 114 apollo_send_command(par, APOLLO_STOP_IMG_DATA);
226 apollo_send_command(par, 0xA2); 115 apollo_send_command(par, APOLLO_DISPLAY_IMG);
227} 116}
228 117
229/* this is called back from the deferred io workqueue */ 118/* this is called back from the deferred io workqueue */
@@ -326,11 +215,21 @@ static struct fb_deferred_io hecubafb_defio = {
326static int __devinit hecubafb_probe(struct platform_device *dev) 215static int __devinit hecubafb_probe(struct platform_device *dev)
327{ 216{
328 struct fb_info *info; 217 struct fb_info *info;
218 struct hecuba_board *board;
329 int retval = -ENOMEM; 219 int retval = -ENOMEM;
330 int videomemorysize; 220 int videomemorysize;
331 unsigned char *videomemory; 221 unsigned char *videomemory;
332 struct hecubafb_par *par; 222 struct hecubafb_par *par;
333 223
224 /* pick up board specific routines */
225 board = dev->dev.platform_data;
226 if (!board)
227 return -EINVAL;
228
229 /* try to count device specific driver, if can't, platform recalls */
230 if (!try_module_get(board->owner))
231 return -ENODEV;
232
334 videomemorysize = (DPY_W*DPY_H)/8; 233 videomemorysize = (DPY_W*DPY_H)/8;
335 234
336 if (!(videomemory = vmalloc(videomemorysize))) 235 if (!(videomemory = vmalloc(videomemorysize)))
@@ -340,9 +239,9 @@ static int __devinit hecubafb_probe(struct platform_device *dev)
340 239
341 info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev); 240 info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev);
342 if (!info) 241 if (!info)
343 goto err; 242 goto err_fballoc;
344 243
345 info->screen_base = (char __iomem *) videomemory; 244 info->screen_base = (char __force __iomem *)videomemory;
346 info->fbops = &hecubafb_ops; 245 info->fbops = &hecubafb_ops;
347 246
348 info->var = hecubafb_var; 247 info->var = hecubafb_var;
@@ -350,14 +249,10 @@ static int __devinit hecubafb_probe(struct platform_device *dev)
350 info->fix.smem_len = videomemorysize; 249 info->fix.smem_len = videomemorysize;
351 par = info->par; 250 par = info->par;
352 par->info = info; 251 par->info = info;
252 par->board = board;
253 par->send_command = apollo_send_command;
254 par->send_data = apollo_send_data;
353 255
354 if (!dio_addr || !cio_addr || !c2io_addr) {
355 printk(KERN_WARNING "no IO addresses supplied\n");
356 goto err1;
357 }
358 par->dio_addr = dio_addr;
359 par->cio_addr = cio_addr;
360 par->c2io_addr = c2io_addr;
361 info->flags = FBINFO_FLAG_DEFAULT; 256 info->flags = FBINFO_FLAG_DEFAULT;
362 257
363 info->fbdefio = &hecubafb_defio; 258 info->fbdefio = &hecubafb_defio;
@@ -365,7 +260,7 @@ static int __devinit hecubafb_probe(struct platform_device *dev)
365 260
366 retval = register_framebuffer(info); 261 retval = register_framebuffer(info);
367 if (retval < 0) 262 if (retval < 0)
368 goto err1; 263 goto err_fbreg;
369 platform_set_drvdata(dev, info); 264 platform_set_drvdata(dev, info);
370 265
371 printk(KERN_INFO 266 printk(KERN_INFO
@@ -373,25 +268,16 @@ static int __devinit hecubafb_probe(struct platform_device *dev)
373 info->node, videomemorysize >> 10); 268 info->node, videomemorysize >> 10);
374 269
375 /* this inits the dpy */ 270 /* this inits the dpy */
376 apollo_init_control(par); 271 retval = par->board->init(par);
377 272 if (retval < 0)
378 apollo_send_command(par, APOLLO_INIT_DISPLAY); 273 goto err_fbreg;
379 apollo_send_data(par, 0x81);
380
381 /* have to wait while display resets */
382 udelay(1000);
383
384 /* if we were told to splash the screen, we just clear it */
385 if (!nosplash) {
386 apollo_send_command(par, APOLLO_ERASE_DISPLAY);
387 apollo_send_data(par, splashval);
388 }
389 274
390 return 0; 275 return 0;
391err1: 276err_fbreg:
392 framebuffer_release(info); 277 framebuffer_release(info);
393err: 278err_fballoc:
394 vfree(videomemory); 279 vfree(videomemory);
280 module_put(board->owner);
395 return retval; 281 return retval;
396} 282}
397 283
@@ -400,9 +286,13 @@ static int __devexit hecubafb_remove(struct platform_device *dev)
400 struct fb_info *info = platform_get_drvdata(dev); 286 struct fb_info *info = platform_get_drvdata(dev);
401 287
402 if (info) { 288 if (info) {
289 struct hecubafb_par *par = info->par;
403 fb_deferred_io_cleanup(info); 290 fb_deferred_io_cleanup(info);
404 unregister_framebuffer(info); 291 unregister_framebuffer(info);
405 vfree((void __force *)info->screen_base); 292 vfree((void __force *)info->screen_base);
293 if (par->board->remove)
294 par->board->remove(par);
295 module_put(par->board->owner);
406 framebuffer_release(info); 296 framebuffer_release(info);
407 } 297 }
408 return 0; 298 return 0;
@@ -412,62 +302,24 @@ static struct platform_driver hecubafb_driver = {
412 .probe = hecubafb_probe, 302 .probe = hecubafb_probe,
413 .remove = hecubafb_remove, 303 .remove = hecubafb_remove,
414 .driver = { 304 .driver = {
305 .owner = THIS_MODULE,
415 .name = "hecubafb", 306 .name = "hecubafb",
416 }, 307 },
417}; 308};
418 309
419static struct platform_device *hecubafb_device;
420
421static int __init hecubafb_init(void) 310static int __init hecubafb_init(void)
422{ 311{
423 int ret; 312 return platform_driver_register(&hecubafb_driver);
424
425 if (!hecubafb_enable) {
426 printk(KERN_ERR "Use hecubafb_enable to enable the device\n");
427 return -ENXIO;
428 }
429
430 ret = platform_driver_register(&hecubafb_driver);
431 if (!ret) {
432 hecubafb_device = platform_device_alloc("hecubafb", 0);
433 if (hecubafb_device)
434 ret = platform_device_add(hecubafb_device);
435 else
436 ret = -ENOMEM;
437
438 if (ret) {
439 platform_device_put(hecubafb_device);
440 platform_driver_unregister(&hecubafb_driver);
441 }
442 }
443 return ret;
444
445} 313}
446 314
447static void __exit hecubafb_exit(void) 315static void __exit hecubafb_exit(void)
448{ 316{
449 platform_device_unregister(hecubafb_device);
450 platform_driver_unregister(&hecubafb_driver); 317 platform_driver_unregister(&hecubafb_driver);
451} 318}
452 319
453module_param(nosplash, uint, 0);
454MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
455module_param(hecubafb_enable, uint, 0);
456MODULE_PARM_DESC(hecubafb_enable, "Enable communication with Hecuba board");
457module_param(dio_addr, ulong, 0);
458MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
459module_param(cio_addr, ulong, 0);
460MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
461module_param(c2io_addr, ulong, 0);
462MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
463module_param(splashval, ulong, 0);
464MODULE_PARM_DESC(splashval, "Splash pattern: 0x00 is black, 0x01 is white");
465module_param(irq, uint, 0);
466MODULE_PARM_DESC(irq, "IRQ for the Hecuba board");
467
468module_init(hecubafb_init); 320module_init(hecubafb_init);
469module_exit(hecubafb_exit); 321module_exit(hecubafb_exit);
470 322
471MODULE_DESCRIPTION("fbdev driver for Hecuba board"); 323MODULE_DESCRIPTION("fbdev driver for Hecuba/Apollo controller");
472MODULE_AUTHOR("Jaya Kumar"); 324MODULE_AUTHOR("Jaya Kumar");
473MODULE_LICENSE("GPL"); 325MODULE_LICENSE("GPL");
diff --git a/drivers/video/n411.c b/drivers/video/n411.c
new file mode 100644
index 000000000000..935830fea7b6
--- /dev/null
+++ b/drivers/video/n411.c
@@ -0,0 +1,202 @@
1/*
2 * linux/drivers/video/n411.c -- Platform device for N411 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 * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
11 *
12 * This driver is written to be used with the Hecuba display controller
13 * board, and tested with the EInk 800x600 display in 1 bit mode.
14 * The interface between Hecuba and the host is TTL based GPIO. The
15 * GPIO requirements are 8 writable data lines and 6 lines for control.
16 * Only 4 of the controls are actually used here but 6 for future use.
17 * The driver requires the IO addresses for data and control GPIO at
18 * load time. It is also possible to use this display with a standard
19 * PC parallel port.
20 *
21 * General notes:
22 * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR c2io_addr=0xIOADDR
23 *
24 */
25
26#include <linux/module.h>
27#include <linux/kernel.h>
28#include <linux/errno.h>
29#include <linux/string.h>
30#include <linux/delay.h>
31#include <linux/interrupt.h>
32#include <linux/fb.h>
33#include <linux/init.h>
34#include <linux/platform_device.h>
35#include <linux/list.h>
36#include <linux/uaccess.h>
37#include <linux/irq.h>
38
39#include <video/hecubafb.h>
40
41static unsigned long dio_addr;
42static unsigned long cio_addr;
43static unsigned long c2io_addr;
44static unsigned long splashval;
45static unsigned int nosplash;
46static unsigned char ctl;
47
48static void n411_set_ctl(struct hecubafb_par *par, unsigned char bit, unsigned
49 char state)
50{
51 switch (bit) {
52 case HCB_CD_BIT:
53 if (state)
54 ctl &= ~(HCB_CD_BIT);
55 else
56 ctl |= HCB_CD_BIT;
57 break;
58 case HCB_DS_BIT:
59 if (state)
60 ctl &= ~(HCB_DS_BIT);
61 else
62 ctl |= HCB_DS_BIT;
63 break;
64 }
65 outb(ctl, cio_addr);
66}
67
68static unsigned char n411_get_ctl(struct hecubafb_par *par)
69{
70 return inb(c2io_addr);
71}
72
73static void n411_set_data(struct hecubafb_par *par, unsigned char value)
74{
75 outb(value, dio_addr);
76}
77
78static void n411_wait_for_ack(struct hecubafb_par *par, int clear)
79{
80 int timeout;
81 unsigned char tmp;
82
83 timeout = 500;
84 do {
85 tmp = n411_get_ctl(par);
86 if ((tmp & HCB_ACK_BIT) && (!clear))
87 return;
88 else if (!(tmp & HCB_ACK_BIT) && (clear))
89 return;
90 udelay(1);
91 } while (timeout--);
92 printk(KERN_ERR "timed out waiting for ack\n");
93}
94
95static int n411_init_control(struct hecubafb_par *par)
96{
97 unsigned char tmp;
98 /* for init, we want the following setup to be set:
99 WUP = lo
100 ACK = hi
101 DS = hi
102 RW = hi
103 CD = lo
104 */
105
106 /* write WUP to lo, DS to hi, RW to hi, CD to lo */
107 ctl = HCB_WUP_BIT | HCB_RW_BIT | HCB_CD_BIT ;
108 n411_set_ctl(par, HCB_DS_BIT, 1);
109
110 /* check ACK is not lo */
111 tmp = n411_get_ctl(par);
112 if (tmp & HCB_ACK_BIT) {
113 printk(KERN_ERR "Fail because ACK is already low\n");
114 return -ENXIO;
115 }
116
117 return 0;
118}
119
120
121static int n411_init_board(struct hecubafb_par *par)
122{
123 int retval;
124
125 retval = n411_init_control(par);
126 if (retval)
127 return retval;
128
129 par->send_command(par, APOLLO_INIT_DISPLAY);
130 par->send_data(par, 0x81);
131
132 /* have to wait while display resets */
133 udelay(1000);
134
135 /* if we were told to splash the screen, we just clear it */
136 if (!nosplash) {
137 par->send_command(par, APOLLO_ERASE_DISPLAY);
138 par->send_data(par, splashval);
139 }
140
141 return 0;
142}
143
144static struct hecuba_board n411_board = {
145 .owner = THIS_MODULE,
146 .init = n411_init_board,
147 .set_ctl = n411_set_ctl,
148 .set_data = n411_set_data,
149 .wait_for_ack = n411_wait_for_ack,
150};
151
152static struct platform_device *n411_device;
153static int __init n411_init(void)
154{
155 int ret;
156 if (!dio_addr || !cio_addr || !c2io_addr) {
157 printk(KERN_WARNING "no IO addresses supplied\n");
158 return -EINVAL;
159 }
160
161 /* request our platform independent driver */
162 request_module("hecubafb");
163
164 n411_device = platform_device_alloc("hecubafb", -1);
165 if (!n411_device)
166 return -ENOMEM;
167
168 platform_device_add_data(n411_device, &n411_board, sizeof(n411_board));
169
170 /* this _add binds hecubafb to n411. hecubafb refcounts n411 */
171 ret = platform_device_add(n411_device);
172
173 if (ret)
174 platform_device_put(n411_device);
175
176 return ret;
177
178}
179
180static void __exit n411_exit(void)
181{
182 platform_device_unregister(n411_device);
183}
184
185module_init(n411_init);
186module_exit(n411_exit);
187
188module_param(nosplash, uint, 0);
189MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
190module_param(dio_addr, ulong, 0);
191MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
192module_param(cio_addr, ulong, 0);
193MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
194module_param(c2io_addr, ulong, 0);
195MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
196module_param(splashval, ulong, 0);
197MODULE_PARM_DESC(splashval, "Splash pattern: 0x00 is black, 0x01 is white");
198
199MODULE_DESCRIPTION("board driver for n411 hecuba/apollo epd kit");
200MODULE_AUTHOR("Jaya Kumar");
201MODULE_LICENSE("GPL");
202
diff --git a/include/video/hecubafb.h b/include/video/hecubafb.h
new file mode 100644
index 000000000000..7b9952339762
--- /dev/null
+++ b/include/video/hecubafb.h
@@ -0,0 +1,51 @@
1/*
2 * hecubafb.h - definitions for the hecuba framebuffer driver
3 *
4 * Copyright (C) 2008 by 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 */
11
12#ifndef _LINUX_HECUBAFB_H_
13#define _LINUX_HECUBAFB_H_
14
15/* Apollo controller specific defines */
16#define APOLLO_START_NEW_IMG 0xA0
17#define APOLLO_STOP_IMG_DATA 0xA1
18#define APOLLO_DISPLAY_IMG 0xA2
19#define APOLLO_ERASE_DISPLAY 0xA3
20#define APOLLO_INIT_DISPLAY 0xA4
21
22/* Hecuba interface specific defines */
23#define HCB_WUP_BIT 0x01
24#define HCB_DS_BIT 0x02
25#define HCB_RW_BIT 0x04
26#define HCB_CD_BIT 0x08
27#define HCB_ACK_BIT 0x80
28
29/* struct used by hecuba. board specific stuff comes from *board */
30struct hecubafb_par {
31 struct fb_info *info;
32 struct hecuba_board *board;
33 void (*send_command)(struct hecubafb_par *, unsigned char);
34 void (*send_data)(struct hecubafb_par *, unsigned char);
35};
36
37/* board specific routines
38board drivers can implement wait_for_ack with interrupts if desired. if
39wait_for_ack is called with clear=0, then go to sleep and return when ack
40goes hi or if wait_for_ack with clear=1, then return when ack goes lo */
41struct hecuba_board {
42 struct module *owner;
43 void (*remove)(struct hecubafb_par *);
44 void (*set_ctl)(struct hecubafb_par *, unsigned char, unsigned char);
45 void (*set_data)(struct hecubafb_par *, unsigned char);
46 void (*wait_for_ack)(struct hecubafb_par *, int);
47 int (*init)(struct hecubafb_par *);
48};
49
50
51#endif