Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * linux/drivers/video/n411.c -- Platform device for N411 EPD kit
0003  *
0004  * Copyright (C) 2008, Jaya Kumar
0005  *
0006  * This file is subject to the terms and conditions of the GNU General Public
0007  * License. See the file COPYING in the main directory of this archive for
0008  * more details.
0009  *
0010  * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
0011  *
0012  * This driver is written to be used with the Hecuba display controller
0013  * board, and tested with the EInk 800x600 display in 1 bit mode.
0014  * The interface between Hecuba and the host is TTL based GPIO. The
0015  * GPIO requirements are 8 writable data lines and 6 lines for control.
0016  * Only 4 of the controls are actually used here but 6 for future use.
0017  * The driver requires the IO addresses for data and control GPIO at
0018  * load time. It is also possible to use this display with a standard
0019  * PC parallel port.
0020  *
0021  * General notes:
0022  * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR c2io_addr=0xIOADDR
0023  *
0024  */
0025 
0026 #include <linux/module.h>
0027 #include <linux/kernel.h>
0028 #include <linux/errno.h>
0029 #include <linux/string.h>
0030 #include <linux/delay.h>
0031 #include <linux/interrupt.h>
0032 #include <linux/fb.h>
0033 #include <linux/init.h>
0034 #include <linux/platform_device.h>
0035 #include <linux/list.h>
0036 #include <linux/uaccess.h>
0037 #include <linux/irq.h>
0038 
0039 #include <video/hecubafb.h>
0040 
0041 static unsigned long dio_addr;
0042 static unsigned long cio_addr;
0043 static unsigned long c2io_addr;
0044 static unsigned long splashval;
0045 static unsigned int nosplash;
0046 static unsigned char ctl;
0047 
0048 static void n411_set_ctl(struct hecubafb_par *par, unsigned char bit, unsigned
0049                             char state)
0050 {
0051     switch (bit) {
0052     case HCB_CD_BIT:
0053         if (state)
0054             ctl &= ~(HCB_CD_BIT);
0055         else
0056             ctl |= HCB_CD_BIT;
0057         break;
0058     case HCB_DS_BIT:
0059         if (state)
0060             ctl &= ~(HCB_DS_BIT);
0061         else
0062             ctl |= HCB_DS_BIT;
0063         break;
0064     }
0065     outb(ctl, cio_addr);
0066 }
0067 
0068 static unsigned char n411_get_ctl(struct hecubafb_par *par)
0069 {
0070     return inb(c2io_addr);
0071 }
0072 
0073 static void n411_set_data(struct hecubafb_par *par, unsigned char value)
0074 {
0075     outb(value, dio_addr);
0076 }
0077 
0078 static void n411_wait_for_ack(struct hecubafb_par *par, int clear)
0079 {
0080     int timeout;
0081     unsigned char tmp;
0082 
0083     timeout = 500;
0084     do {
0085         tmp = n411_get_ctl(par);
0086         if ((tmp & HCB_ACK_BIT) && (!clear))
0087             return;
0088         else if (!(tmp & HCB_ACK_BIT) && (clear))
0089             return;
0090         udelay(1);
0091     } while (timeout--);
0092     printk(KERN_ERR "timed out waiting for ack\n");
0093 }
0094 
0095 static int n411_init_control(struct hecubafb_par *par)
0096 {
0097     unsigned char tmp;
0098     /* for init, we want the following setup to be set:
0099     WUP = lo
0100     ACK = hi
0101     DS = hi
0102     RW = hi
0103     CD = lo
0104     */
0105 
0106     /* write WUP to lo, DS to hi, RW to hi, CD to lo */
0107     ctl = HCB_WUP_BIT | HCB_RW_BIT | HCB_CD_BIT ;
0108     n411_set_ctl(par, HCB_DS_BIT, 1);
0109 
0110     /* check ACK is not lo */
0111     tmp = n411_get_ctl(par);
0112     if (tmp & HCB_ACK_BIT) {
0113         printk(KERN_ERR "Fail because ACK is already low\n");
0114         return -ENXIO;
0115     }
0116 
0117     return 0;
0118 }
0119 
0120 
0121 static int n411_init_board(struct hecubafb_par *par)
0122 {
0123     int retval;
0124 
0125     retval = n411_init_control(par);
0126     if (retval)
0127         return retval;
0128 
0129     par->send_command(par, APOLLO_INIT_DISPLAY);
0130     par->send_data(par, 0x81);
0131 
0132     /* have to wait while display resets */
0133     udelay(1000);
0134 
0135     /* if we were told to splash the screen, we just clear it */
0136     if (!nosplash) {
0137         par->send_command(par, APOLLO_ERASE_DISPLAY);
0138         par->send_data(par, splashval);
0139     }
0140 
0141     return 0;
0142 }
0143 
0144 static struct hecuba_board n411_board = {
0145     .owner          = THIS_MODULE,
0146     .init           = n411_init_board,
0147     .set_ctl        = n411_set_ctl,
0148     .set_data       = n411_set_data,
0149     .wait_for_ack       = n411_wait_for_ack,
0150 };
0151 
0152 static struct platform_device *n411_device;
0153 static int __init n411_init(void)
0154 {
0155     int ret;
0156     if (!dio_addr || !cio_addr || !c2io_addr) {
0157         printk(KERN_WARNING "no IO addresses supplied\n");
0158         return -EINVAL;
0159     }
0160 
0161     /* request our platform independent driver */
0162     request_module("hecubafb");
0163 
0164     n411_device = platform_device_alloc("hecubafb", -1);
0165     if (!n411_device)
0166         return -ENOMEM;
0167 
0168     ret = platform_device_add_data(n411_device, &n411_board,
0169                        sizeof(n411_board));
0170     if (ret)
0171         goto put_plat_device;
0172 
0173     /* this _add binds hecubafb to n411. hecubafb refcounts n411 */
0174     ret = platform_device_add(n411_device);
0175 
0176     if (ret)
0177         goto put_plat_device;
0178 
0179     return 0;
0180 
0181 put_plat_device:
0182     platform_device_put(n411_device);
0183     return ret;
0184 }
0185 
0186 static void __exit n411_exit(void)
0187 {
0188     platform_device_unregister(n411_device);
0189 }
0190 
0191 module_init(n411_init);
0192 module_exit(n411_exit);
0193 
0194 module_param(nosplash, uint, 0);
0195 MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
0196 module_param_hw(dio_addr, ulong, ioport, 0);
0197 MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
0198 module_param_hw(cio_addr, ulong, ioport, 0);
0199 MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
0200 module_param_hw(c2io_addr, ulong, ioport, 0);
0201 MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
0202 module_param(splashval, ulong, 0);
0203 MODULE_PARM_DESC(splashval, "Splash pattern: 0x00 is black, 0x01 is white");
0204 
0205 MODULE_DESCRIPTION("board driver for n411 hecuba/apollo epd kit");
0206 MODULE_AUTHOR("Jaya Kumar");
0207 MODULE_LICENSE("GPL");
0208