2007-02-10 12:44:32 +03:00
/*
* Filename : ks0108 . c
* Version : 0.1 .0
* Description : ks0108 LCD Controller driver
* License : GPLv2
* Depends : parport
*
2008-07-04 20:59:33 +04:00
* Author : Copyright ( C ) Miguel Ojeda Sandonis
2007-02-10 12:44:32 +03:00
* Date : 2006 - 10 - 31
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
2015-07-20 14:57:22 +03:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2007-02-10 12:44:32 +03:00
# include <linux/init.h>
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/delay.h>
# include <linux/fs.h>
# include <linux/io.h>
# include <linux/parport.h>
# include <linux/uaccess.h>
# include <linux/ks0108.h>
# define KS0108_NAME "ks0108"
/*
* Module Parameters
*/
static unsigned int ks0108_port = CONFIG_KS0108_PORT ;
module_param ( ks0108_port , uint , S_IRUGO ) ;
MODULE_PARM_DESC ( ks0108_port , " Parallel port where the LCD is connected " ) ;
static unsigned int ks0108_delay = CONFIG_KS0108_DELAY ;
module_param ( ks0108_delay , uint , S_IRUGO ) ;
MODULE_PARM_DESC ( ks0108_delay , " Delay between each control writing (microseconds) " ) ;
/*
* Device
*/
static struct parport * ks0108_parport ;
static struct pardevice * ks0108_pardevice ;
/*
* ks0108 Exported Commands ( don ' t lock )
*
* You _should_ lock in the top driver : This functions _should not_
* get race conditions in any way . Locking for each byte here would be
* so slow and useless .
*
* There are not bit definitions because they are not flags ,
* just arbitrary combinations defined by the documentation for each
* function in the ks0108 LCD controller . If you want to know what means
* a specific combination , look at the function ' s name .
*
* The ks0108_writecontrol bits need to be reverted ^ ( 0 , 1 , 3 ) because
* the parallel port also revert them using a " not " logic gate .
*/
# define bit(n) (((unsigned char)1)<<(n))
void ks0108_writedata ( unsigned char byte )
{
parport_write_data ( ks0108_parport , byte ) ;
}
void ks0108_writecontrol ( unsigned char byte )
{
udelay ( ks0108_delay ) ;
parport_write_control ( ks0108_parport , byte ^ ( bit ( 0 ) | bit ( 1 ) | bit ( 3 ) ) ) ;
}
void ks0108_displaystate ( unsigned char state )
{
ks0108_writedata ( ( state ? bit ( 0 ) : 0 ) | bit ( 1 ) | bit ( 2 ) | bit ( 3 ) | bit ( 4 ) | bit ( 5 ) ) ;
}
void ks0108_startline ( unsigned char startline )
{
2015-07-20 14:57:23 +03:00
ks0108_writedata ( min_t ( unsigned char , startline , 63 ) | bit ( 6 ) |
bit ( 7 ) ) ;
2007-02-10 12:44:32 +03:00
}
void ks0108_address ( unsigned char address )
{
2015-07-20 14:57:23 +03:00
ks0108_writedata ( min_t ( unsigned char , address , 63 ) | bit ( 6 ) ) ;
2007-02-10 12:44:32 +03:00
}
void ks0108_page ( unsigned char page )
{
2015-07-20 14:57:23 +03:00
ks0108_writedata ( min_t ( unsigned char , page , 7 ) | bit ( 3 ) | bit ( 4 ) |
bit ( 5 ) | bit ( 7 ) ) ;
2007-02-10 12:44:32 +03:00
}
EXPORT_SYMBOL_GPL ( ks0108_writedata ) ;
EXPORT_SYMBOL_GPL ( ks0108_writecontrol ) ;
EXPORT_SYMBOL_GPL ( ks0108_displaystate ) ;
EXPORT_SYMBOL_GPL ( ks0108_startline ) ;
EXPORT_SYMBOL_GPL ( ks0108_address ) ;
EXPORT_SYMBOL_GPL ( ks0108_page ) ;
2007-02-21 00:58:00 +03:00
/*
* Is the module inited ?
*/
static unsigned char ks0108_inited ;
unsigned char ks0108_isinited ( void )
{
return ks0108_inited ;
}
EXPORT_SYMBOL_GPL ( ks0108_isinited ) ;
2015-07-20 14:57:24 +03:00
static void ks0108_parport_attach ( struct parport * port )
2007-02-10 12:44:32 +03:00
{
2015-07-20 14:57:24 +03:00
struct pardev_cb ks0108_cb ;
2007-02-10 12:44:32 +03:00
2015-07-20 14:57:24 +03:00
if ( port - > base ! = ks0108_port )
return ;
2007-02-10 12:44:32 +03:00
2015-07-20 14:57:24 +03:00
memset ( & ks0108_cb , 0 , sizeof ( ks0108_cb ) ) ;
ks0108_cb . flags = PARPORT_DEV_EXCL ;
ks0108_pardevice = parport_register_dev_model ( port , KS0108_NAME ,
& ks0108_cb , 0 ) ;
if ( ! ks0108_pardevice ) {
2015-07-20 14:57:22 +03:00
pr_err ( " ERROR: parport didn't register new device \n " ) ;
2015-07-20 14:57:24 +03:00
return ;
2007-02-10 12:44:32 +03:00
}
2015-07-20 14:57:24 +03:00
if ( parport_claim ( ks0108_pardevice ) ) {
pr_err ( " could not claim access to parport %i. Aborting. \n " ,
2015-07-20 14:57:22 +03:00
ks0108_port ) ;
2015-07-20 14:57:24 +03:00
goto err_unreg_device ;
2007-02-10 12:44:32 +03:00
}
2015-08-13 16:36:05 +03:00
ks0108_parport = port ;
2007-02-21 00:58:00 +03:00
ks0108_inited = 1 ;
2015-07-20 14:57:24 +03:00
return ;
2007-02-10 12:44:32 +03:00
2015-07-20 14:57:24 +03:00
err_unreg_device :
2007-02-10 12:44:32 +03:00
parport_unregister_device ( ks0108_pardevice ) ;
2015-07-20 14:57:24 +03:00
ks0108_pardevice = NULL ;
2007-02-10 12:44:32 +03:00
}
2015-07-20 14:57:24 +03:00
static void ks0108_parport_detach ( struct parport * port )
2007-02-10 12:44:32 +03:00
{
2015-07-20 14:57:24 +03:00
if ( port - > base ! = ks0108_port )
return ;
if ( ! ks0108_pardevice ) {
pr_err ( " %s: already unregistered. \n " , KS0108_NAME ) ;
return ;
}
2007-02-10 12:44:32 +03:00
parport_release ( ks0108_pardevice ) ;
parport_unregister_device ( ks0108_pardevice ) ;
2015-07-20 14:57:24 +03:00
ks0108_pardevice = NULL ;
2015-08-13 16:36:05 +03:00
ks0108_parport = NULL ;
2015-07-20 14:57:24 +03:00
}
/*
* Module Init & Exit
*/
static struct parport_driver ks0108_parport_driver = {
. name = " ks0108 " ,
. match_port = ks0108_parport_attach ,
. detach = ks0108_parport_detach ,
. devmodel = true ,
} ;
static int __init ks0108_init ( void )
{
return parport_register_driver ( & ks0108_parport_driver ) ;
}
static void __exit ks0108_exit ( void )
{
parport_unregister_driver ( & ks0108_parport_driver ) ;
2007-02-10 12:44:32 +03:00
}
module_init ( ks0108_init ) ;
module_exit ( ks0108_exit ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
2008-07-04 20:59:33 +04:00
MODULE_AUTHOR ( " Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com> " ) ;
2007-02-10 12:44:32 +03:00
MODULE_DESCRIPTION ( " ks0108 LCD Controller driver " ) ;