Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *    Filename: ks0108.c
0004  *     Version: 0.1.0
0005  * Description: ks0108 LCD Controller driver
0006  *     Depends: parport
0007  *
0008  *      Author: Copyright (C) Miguel Ojeda <ojeda@kernel.org>
0009  *        Date: 2006-10-31
0010  */
0011 
0012 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0013 
0014 #include <linux/init.h>
0015 #include <linux/module.h>
0016 #include <linux/kernel.h>
0017 #include <linux/delay.h>
0018 #include <linux/parport.h>
0019 #include <linux/ks0108.h>
0020 
0021 #define KS0108_NAME "ks0108"
0022 
0023 /*
0024  * Module Parameters
0025  */
0026 
0027 static unsigned int ks0108_port = CONFIG_KS0108_PORT;
0028 module_param(ks0108_port, uint, 0444);
0029 MODULE_PARM_DESC(ks0108_port, "Parallel port where the LCD is connected");
0030 
0031 static unsigned int ks0108_delay = CONFIG_KS0108_DELAY;
0032 module_param(ks0108_delay, uint, 0444);
0033 MODULE_PARM_DESC(ks0108_delay, "Delay between each control writing (microseconds)");
0034 
0035 /*
0036  * Device
0037  */
0038 
0039 static struct parport *ks0108_parport;
0040 static struct pardevice *ks0108_pardevice;
0041 
0042 /*
0043  * ks0108 Exported Commands (don't lock)
0044  *
0045  *   You _should_ lock in the top driver: This functions _should not_
0046  *   get race conditions in any way. Locking for each byte here would be
0047  *   so slow and useless.
0048  *
0049  *   There are not bit definitions because they are not flags,
0050  *   just arbitrary combinations defined by the documentation for each
0051  *   function in the ks0108 LCD controller. If you want to know what means
0052  *   a specific combination, look at the function's name.
0053  *
0054  *   The ks0108_writecontrol bits need to be reverted ^(0,1,3) because
0055  *   the parallel port also revert them using a "not" logic gate.
0056  */
0057 
0058 #define bit(n) (((unsigned char)1)<<(n))
0059 
0060 void ks0108_writedata(unsigned char byte)
0061 {
0062     parport_write_data(ks0108_parport, byte);
0063 }
0064 
0065 void ks0108_writecontrol(unsigned char byte)
0066 {
0067     udelay(ks0108_delay);
0068     parport_write_control(ks0108_parport, byte ^ (bit(0) | bit(1) | bit(3)));
0069 }
0070 
0071 void ks0108_displaystate(unsigned char state)
0072 {
0073     ks0108_writedata((state ? bit(0) : 0) | bit(1) | bit(2) | bit(3) | bit(4) | bit(5));
0074 }
0075 
0076 void ks0108_startline(unsigned char startline)
0077 {
0078     ks0108_writedata(min_t(unsigned char, startline, 63) | bit(6) |
0079              bit(7));
0080 }
0081 
0082 void ks0108_address(unsigned char address)
0083 {
0084     ks0108_writedata(min_t(unsigned char, address, 63) | bit(6));
0085 }
0086 
0087 void ks0108_page(unsigned char page)
0088 {
0089     ks0108_writedata(min_t(unsigned char, page, 7) | bit(3) | bit(4) |
0090              bit(5) | bit(7));
0091 }
0092 
0093 EXPORT_SYMBOL_GPL(ks0108_writedata);
0094 EXPORT_SYMBOL_GPL(ks0108_writecontrol);
0095 EXPORT_SYMBOL_GPL(ks0108_displaystate);
0096 EXPORT_SYMBOL_GPL(ks0108_startline);
0097 EXPORT_SYMBOL_GPL(ks0108_address);
0098 EXPORT_SYMBOL_GPL(ks0108_page);
0099 
0100 /*
0101  * Is the module inited?
0102  */
0103 
0104 static unsigned char ks0108_inited;
0105 unsigned char ks0108_isinited(void)
0106 {
0107     return ks0108_inited;
0108 }
0109 EXPORT_SYMBOL_GPL(ks0108_isinited);
0110 
0111 static void ks0108_parport_attach(struct parport *port)
0112 {
0113     struct pardev_cb ks0108_cb;
0114 
0115     if (port->base != ks0108_port)
0116         return;
0117 
0118     memset(&ks0108_cb, 0, sizeof(ks0108_cb));
0119     ks0108_cb.flags = PARPORT_DEV_EXCL;
0120     ks0108_pardevice = parport_register_dev_model(port, KS0108_NAME,
0121                               &ks0108_cb, 0);
0122     if (!ks0108_pardevice) {
0123         pr_err("ERROR: parport didn't register new device\n");
0124         return;
0125     }
0126     if (parport_claim(ks0108_pardevice)) {
0127         pr_err("could not claim access to parport %i. Aborting.\n",
0128                ks0108_port);
0129         goto err_unreg_device;
0130     }
0131 
0132     ks0108_parport = port;
0133     ks0108_inited = 1;
0134     return;
0135 
0136 err_unreg_device:
0137     parport_unregister_device(ks0108_pardevice);
0138     ks0108_pardevice = NULL;
0139 }
0140 
0141 static void ks0108_parport_detach(struct parport *port)
0142 {
0143     if (port->base != ks0108_port)
0144         return;
0145 
0146     if (!ks0108_pardevice) {
0147         pr_err("%s: already unregistered.\n", KS0108_NAME);
0148         return;
0149     }
0150 
0151     parport_release(ks0108_pardevice);
0152     parport_unregister_device(ks0108_pardevice);
0153     ks0108_pardevice = NULL;
0154     ks0108_parport = NULL;
0155 }
0156 
0157 /*
0158  * Module Init & Exit
0159  */
0160 
0161 static struct parport_driver ks0108_parport_driver = {
0162     .name = "ks0108",
0163     .match_port = ks0108_parport_attach,
0164     .detach = ks0108_parport_detach,
0165     .devmodel = true,
0166 };
0167 module_parport_driver(ks0108_parport_driver);
0168 
0169 MODULE_LICENSE("GPL v2");
0170 MODULE_AUTHOR("Miguel Ojeda <ojeda@kernel.org>");
0171 MODULE_DESCRIPTION("ks0108 LCD Controller driver");
0172