1 /* 2 * Filename: ks0108.c 3 * Version: 0.1.0 4 * Description: ks0108 LCD Controller driver 5 * License: GPLv2 6 * Depends: parport 7 * 8 * Author: Copyright (C) Miguel Ojeda Sandonis 9 * Date: 2006-10-31 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * 24 */ 25 26 #include <linux/init.h> 27 #include <linux/module.h> 28 #include <linux/kernel.h> 29 #include <linux/delay.h> 30 #include <linux/fs.h> 31 #include <linux/io.h> 32 #include <linux/parport.h> 33 #include <linux/uaccess.h> 34 #include <linux/ks0108.h> 35 36 #define KS0108_NAME "ks0108" 37 38 /* 39 * Module Parameters 40 */ 41 42 static unsigned int ks0108_port = CONFIG_KS0108_PORT; 43 module_param(ks0108_port, uint, S_IRUGO); 44 MODULE_PARM_DESC(ks0108_port, "Parallel port where the LCD is connected"); 45 46 static unsigned int ks0108_delay = CONFIG_KS0108_DELAY; 47 module_param(ks0108_delay, uint, S_IRUGO); 48 MODULE_PARM_DESC(ks0108_delay, "Delay between each control writing (microseconds)"); 49 50 /* 51 * Device 52 */ 53 54 static struct parport *ks0108_parport; 55 static struct pardevice *ks0108_pardevice; 56 57 /* 58 * ks0108 Exported Commands (don't lock) 59 * 60 * You _should_ lock in the top driver: This functions _should not_ 61 * get race conditions in any way. Locking for each byte here would be 62 * so slow and useless. 63 * 64 * There are not bit definitions because they are not flags, 65 * just arbitrary combinations defined by the documentation for each 66 * function in the ks0108 LCD controller. If you want to know what means 67 * a specific combination, look at the function's name. 68 * 69 * The ks0108_writecontrol bits need to be reverted ^(0,1,3) because 70 * the parallel port also revert them using a "not" logic gate. 71 */ 72 73 #define bit(n) (((unsigned char)1)<<(n)) 74 75 void ks0108_writedata(unsigned char byte) 76 { 77 parport_write_data(ks0108_parport, byte); 78 } 79 80 void ks0108_writecontrol(unsigned char byte) 81 { 82 udelay(ks0108_delay); 83 parport_write_control(ks0108_parport, byte ^ (bit(0) | bit(1) | bit(3))); 84 } 85 86 void ks0108_displaystate(unsigned char state) 87 { 88 ks0108_writedata((state ? bit(0) : 0) | bit(1) | bit(2) | bit(3) | bit(4) | bit(5)); 89 } 90 91 void ks0108_startline(unsigned char startline) 92 { 93 ks0108_writedata(min(startline,(unsigned char)63) | bit(6) | bit(7)); 94 } 95 96 void ks0108_address(unsigned char address) 97 { 98 ks0108_writedata(min(address,(unsigned char)63) | bit(6)); 99 } 100 101 void ks0108_page(unsigned char page) 102 { 103 ks0108_writedata(min(page,(unsigned char)7) | bit(3) | bit(4) | bit(5) | bit(7)); 104 } 105 106 EXPORT_SYMBOL_GPL(ks0108_writedata); 107 EXPORT_SYMBOL_GPL(ks0108_writecontrol); 108 EXPORT_SYMBOL_GPL(ks0108_displaystate); 109 EXPORT_SYMBOL_GPL(ks0108_startline); 110 EXPORT_SYMBOL_GPL(ks0108_address); 111 EXPORT_SYMBOL_GPL(ks0108_page); 112 113 /* 114 * Is the module inited? 115 */ 116 117 static unsigned char ks0108_inited; 118 unsigned char ks0108_isinited(void) 119 { 120 return ks0108_inited; 121 } 122 EXPORT_SYMBOL_GPL(ks0108_isinited); 123 124 /* 125 * Module Init & Exit 126 */ 127 128 static int __init ks0108_init(void) 129 { 130 int result; 131 int ret = -EINVAL; 132 133 ks0108_parport = parport_find_base(ks0108_port); 134 if (ks0108_parport == NULL) { 135 printk(KERN_ERR KS0108_NAME ": ERROR: " 136 "parport didn't find %i port\n", ks0108_port); 137 goto none; 138 } 139 140 ks0108_pardevice = parport_register_device(ks0108_parport, KS0108_NAME, 141 NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); 142 if (ks0108_pardevice == NULL) { 143 printk(KERN_ERR KS0108_NAME ": ERROR: " 144 "parport didn't register new device\n"); 145 goto none; 146 } 147 148 result = parport_claim(ks0108_pardevice); 149 if (result != 0) { 150 printk(KERN_ERR KS0108_NAME ": ERROR: " 151 "can't claim %i parport, maybe in use\n", ks0108_port); 152 ret = result; 153 goto registered; 154 } 155 156 ks0108_inited = 1; 157 return 0; 158 159 registered: 160 parport_unregister_device(ks0108_pardevice); 161 162 none: 163 return ret; 164 } 165 166 static void __exit ks0108_exit(void) 167 { 168 parport_release(ks0108_pardevice); 169 parport_unregister_device(ks0108_pardevice); 170 } 171 172 module_init(ks0108_init); 173 module_exit(ks0108_exit); 174 175 MODULE_LICENSE("GPL v2"); 176 MODULE_AUTHOR("Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>"); 177 MODULE_DESCRIPTION("ks0108 LCD Controller driver"); 178 179