[PATCH/RFC 2.6.20 2/2] fbdev: Hecuba fb driver

2007-02-24 Thread Jaya Kumar

This patch implements support for the E-Ink/hecuba display device. It uses
deferred IO support.

Thanks,
jaya

Signed-off-by: Jaya Kumar <[EMAIL PROTECTED]>

---

 hecubafb.c |  480 +
 1 file changed, 480 insertions(+)

---

diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c
new file mode 100644
index 000..9944bee
--- /dev/null
+++ b/drivers/video/hecubafb.c
@@ -0,0 +1,480 @@
+/*
+ * linux/drivers/video/hecubafb.c -- FB driver for Hecuba controller
+ *
+ * Copyright (C) 2006, Jaya Kumar 
+ * This work was sponsored by CIS(M) Sdn Bhd
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ * This work was possible because of apollo display code from E-Ink's website
+ * http://support.eink.com/community
+ * All information used to write this code is from public material made
+ * available by E-Ink on its support site. Some commands such as 0xA4
+ * were found by looping through cmd=0x00 thru 0xFF and supplying random
+ * values. There are other commands that the display is capable of,
+ * beyond the 5 used here but they are more complex. 
+ *
+ * This driver is written to be used with the Hecuba display controller
+ * board, and tested with the EInk 800x600 display in 1 bit mode. 
+ * The interface between Hecuba and the host is TTL based GPIO. The
+ * GPIO requirements are 8 writable data lines and 6 lines for control.
+ * Only 4 of the controls are actually used here but 6 for future use.
+ * The driver requires the IO addresses for data and control GPIO at 
+ * load time. It is also possible to use this display with a standard 
+ * PC parallel port. 
+ *
+ * General notes:
+ * - User must set hecubafb_enable=1 to enable it
+ * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR c2io_addr=0xIOADDR
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Apollo controller specific defines */
+#define APOLLO_START_NEW_IMG   0xA0
+#define APOLLO_STOP_IMG_DATA   0xA1
+#define APOLLO_DISPLAY_IMG 0xA2
+#define APOLLO_ERASE_DISPLAY   0xA3
+#define APOLLO_INIT_DISPLAY0xA4
+
+/* Hecuba interface specific defines */
+/* WUP is inverted, CD is inverted, DS is inverted */
+#define HCB_NWUP_BIT   0x01
+#define HCB_NDS_BIT0x02
+#define HCB_RW_BIT 0x04
+#define HCB_NCD_BIT0x08
+#define HCB_ACK_BIT0x80
+
+/* Display specific information */
+#define DPY_W 600
+#define DPY_H 800
+
+struct hecubafb_par {
+   unsigned long dio_addr;
+   unsigned long cio_addr;
+   unsigned long c2io_addr;
+   unsigned char ctl;
+   struct fb_info *info;
+   unsigned int irq;
+};
+
+static struct fb_fix_screeninfo hecubafb_fix __initdata = {
+   .id =   "hecubafb",
+   .type = FB_TYPE_PACKED_PIXELS,
+   .visual =   FB_VISUAL_MONO01,
+   .xpanstep = 0,
+   .ypanstep = 0,
+   .ywrapstep =0,
+   .accel =FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo hecubafb_var __initdata = {
+   .xres   = DPY_W,
+   .yres   = DPY_H,
+   .xres_virtual   = DPY_W,
+   .yres_virtual   = DPY_H,
+   .bits_per_pixel = 1,
+   .nonstd = 1,
+};
+
+static unsigned long dio_addr;
+static unsigned long cio_addr;
+static unsigned long c2io_addr;
+static unsigned long splashval;
+static unsigned int nosplash;
+static unsigned int hecubafb_enable;
+static unsigned int irq;
+
+static DECLARE_WAIT_QUEUE_HEAD(hecubafb_waitq);
+
+static void hcb_set_ctl(struct hecubafb_par *par)
+{
+   outb(par->ctl, par->cio_addr);
+}
+
+static unsigned char hcb_get_ctl(struct hecubafb_par *par)
+{
+   return inb(par->c2io_addr);
+}
+
+static void hcb_set_data(struct hecubafb_par *par, unsigned char value)
+{
+   outb(value, par->dio_addr);
+}
+
+static int __devinit apollo_init_control(struct hecubafb_par *par)
+{
+   unsigned char ctl;
+   /* for init, we want the following setup to be set:
+   WUP = lo
+   ACK = hi
+   DS = hi
+   RW = hi
+   CD = lo 
+   */
+
+   /* write WUP to lo, DS to hi, RW to hi, CD to lo */
+   par->ctl = HCB_NWUP_BIT | HCB_RW_BIT | HCB_NCD_BIT ;
+   par->ctl &= ~HCB_NDS_BIT;
+   hcb_set_ctl(par);
+
+   /* check ACK is not lo */
+   ctl = hcb_get_ctl(par);
+   if ((ctl & HCB_ACK_BIT)) {
+   printk(KERN_ERR "Fail because ACK is already low\n");
+   return -ENXIO;
+   }
+
+   return 0;
+}
+
+void hcb_wait_for_ack(struct hecubafb_par *par)
+{
+
+   int timeout;
+   unsigned char ctl;
+
+   timeout=500;
+   do {
+   ctl = hcb_get_ctl(par);
+   if ((ctl & HCB_ACK_BIT)) 
+ 

[PATCH/RFC 2.6.20 2/2] fbdev: Hecuba fb driver

2007-02-24 Thread Jaya Kumar

This patch implements support for the E-Ink/hecuba display device. It uses
deferred IO support.

Thanks,
jaya

Signed-off-by: Jaya Kumar [EMAIL PROTECTED]

---

 hecubafb.c |  480 +
 1 file changed, 480 insertions(+)

---

diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c
new file mode 100644
index 000..9944bee
--- /dev/null
+++ b/drivers/video/hecubafb.c
@@ -0,0 +1,480 @@
+/*
+ * linux/drivers/video/hecubafb.c -- FB driver for Hecuba controller
+ *
+ * Copyright (C) 2006, Jaya Kumar 
+ * This work was sponsored by CIS(M) Sdn Bhd
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ * This work was possible because of apollo display code from E-Ink's website
+ * http://support.eink.com/community
+ * All information used to write this code is from public material made
+ * available by E-Ink on its support site. Some commands such as 0xA4
+ * were found by looping through cmd=0x00 thru 0xFF and supplying random
+ * values. There are other commands that the display is capable of,
+ * beyond the 5 used here but they are more complex. 
+ *
+ * This driver is written to be used with the Hecuba display controller
+ * board, and tested with the EInk 800x600 display in 1 bit mode. 
+ * The interface between Hecuba and the host is TTL based GPIO. The
+ * GPIO requirements are 8 writable data lines and 6 lines for control.
+ * Only 4 of the controls are actually used here but 6 for future use.
+ * The driver requires the IO addresses for data and control GPIO at 
+ * load time. It is also possible to use this display with a standard 
+ * PC parallel port. 
+ *
+ * General notes:
+ * - User must set hecubafb_enable=1 to enable it
+ * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR c2io_addr=0xIOADDR
+ *
+ */
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/errno.h
+#include linux/string.h
+#include linux/mm.h
+#include linux/slab.h
+#include linux/vmalloc.h
+#include linux/delay.h
+#include linux/interrupt.h
+#include linux/fb.h
+#include linux/init.h
+#include linux/platform_device.h
+#include linux/list.h
+#include asm/uaccess.h
+
+/* Apollo controller specific defines */
+#define APOLLO_START_NEW_IMG   0xA0
+#define APOLLO_STOP_IMG_DATA   0xA1
+#define APOLLO_DISPLAY_IMG 0xA2
+#define APOLLO_ERASE_DISPLAY   0xA3
+#define APOLLO_INIT_DISPLAY0xA4
+
+/* Hecuba interface specific defines */
+/* WUP is inverted, CD is inverted, DS is inverted */
+#define HCB_NWUP_BIT   0x01
+#define HCB_NDS_BIT0x02
+#define HCB_RW_BIT 0x04
+#define HCB_NCD_BIT0x08
+#define HCB_ACK_BIT0x80
+
+/* Display specific information */
+#define DPY_W 600
+#define DPY_H 800
+
+struct hecubafb_par {
+   unsigned long dio_addr;
+   unsigned long cio_addr;
+   unsigned long c2io_addr;
+   unsigned char ctl;
+   struct fb_info *info;
+   unsigned int irq;
+};
+
+static struct fb_fix_screeninfo hecubafb_fix __initdata = {
+   .id =   hecubafb,
+   .type = FB_TYPE_PACKED_PIXELS,
+   .visual =   FB_VISUAL_MONO01,
+   .xpanstep = 0,
+   .ypanstep = 0,
+   .ywrapstep =0,
+   .accel =FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo hecubafb_var __initdata = {
+   .xres   = DPY_W,
+   .yres   = DPY_H,
+   .xres_virtual   = DPY_W,
+   .yres_virtual   = DPY_H,
+   .bits_per_pixel = 1,
+   .nonstd = 1,
+};
+
+static unsigned long dio_addr;
+static unsigned long cio_addr;
+static unsigned long c2io_addr;
+static unsigned long splashval;
+static unsigned int nosplash;
+static unsigned int hecubafb_enable;
+static unsigned int irq;
+
+static DECLARE_WAIT_QUEUE_HEAD(hecubafb_waitq);
+
+static void hcb_set_ctl(struct hecubafb_par *par)
+{
+   outb(par-ctl, par-cio_addr);
+}
+
+static unsigned char hcb_get_ctl(struct hecubafb_par *par)
+{
+   return inb(par-c2io_addr);
+}
+
+static void hcb_set_data(struct hecubafb_par *par, unsigned char value)
+{
+   outb(value, par-dio_addr);
+}
+
+static int __devinit apollo_init_control(struct hecubafb_par *par)
+{
+   unsigned char ctl;
+   /* for init, we want the following setup to be set:
+   WUP = lo
+   ACK = hi
+   DS = hi
+   RW = hi
+   CD = lo 
+   */
+
+   /* write WUP to lo, DS to hi, RW to hi, CD to lo */
+   par-ctl = HCB_NWUP_BIT | HCB_RW_BIT | HCB_NCD_BIT ;
+   par-ctl = ~HCB_NDS_BIT;
+   hcb_set_ctl(par);
+
+   /* check ACK is not lo */
+   ctl = hcb_get_ctl(par);
+   if ((ctl  HCB_ACK_BIT)) {
+   printk(KERN_ERR Fail because ACK is already low\n);
+   return -ENXIO;
+   }
+
+   return 0;
+}
+
+void hcb_wait_for_ack(struct hecubafb_par