2007-08-21 22:34:16 +02:00
/*
* Picvue PVC160206 display driver
*
* Brian Murphy < brian @ murphy . dk >
*
*/
# include <linux/kernel.h>
# include <linux/delay.h>
# include <asm/bootinfo.h>
# include <asm/lasat/lasat.h>
# include <linux/module.h>
# include <linux/errno.h>
# include <linux/string.h>
# include "picvue.h"
# define PVC_BUSY 0x80
# define PVC_NLINES 2
# define PVC_DISPMEM 80
# define PVC_LINELEN PVC_DISPMEM / PVC_NLINES
struct pvc_defs * picvue ;
static void pvc_reg_write ( u32 val )
{
* picvue - > reg = val ;
}
static u32 pvc_reg_read ( void )
{
u32 tmp = * picvue - > reg ;
return tmp ;
}
static void pvc_write_byte ( u32 data , u8 byte )
{
data | = picvue - > e ;
pvc_reg_write ( data ) ;
data & = ~ picvue - > data_mask ;
data | = byte < < picvue - > data_shift ;
pvc_reg_write ( data ) ;
ndelay ( 220 ) ;
pvc_reg_write ( data & ~ picvue - > e ) ;
ndelay ( 220 ) ;
}
static u8 pvc_read_byte ( u32 data )
{
u8 byte ;
data | = picvue - > e ;
pvc_reg_write ( data ) ;
ndelay ( 220 ) ;
byte = ( pvc_reg_read ( ) & picvue - > data_mask ) > > picvue - > data_shift ;
data & = ~ picvue - > e ;
pvc_reg_write ( data ) ;
ndelay ( 220 ) ;
return byte ;
}
static u8 pvc_read_data ( void )
{
u32 data = pvc_reg_read ( ) ;
u8 byte ;
data | = picvue - > rw ;
data & = ~ picvue - > rs ;
pvc_reg_write ( data ) ;
ndelay ( 40 ) ;
byte = pvc_read_byte ( data ) ;
data | = picvue - > rs ;
pvc_reg_write ( data ) ;
return byte ;
}
# define TIMEOUT 1000
static int pvc_wait ( void )
{
int i = TIMEOUT ;
int err = 0 ;
while ( ( pvc_read_data ( ) & PVC_BUSY ) & & i )
i - - ;
if ( i = = 0 )
err = - ETIME ;
return err ;
}
# define MODE_INST 0
# define MODE_DATA 1
static void pvc_write ( u8 byte , int mode )
{
u32 data = pvc_reg_read ( ) ;
data & = ~ picvue - > rw ;
if ( mode = = MODE_DATA )
data | = picvue - > rs ;
else
data & = ~ picvue - > rs ;
pvc_reg_write ( data ) ;
ndelay ( 40 ) ;
pvc_write_byte ( data , byte ) ;
if ( mode = = MODE_DATA )
data & = ~ picvue - > rs ;
else
data | = picvue - > rs ;
pvc_reg_write ( data ) ;
pvc_wait ( ) ;
}
void pvc_write_string ( const unsigned char * str , u8 addr , int line )
{
int i = 0 ;
if ( line > 0 & & ( PVC_NLINES > 1 ) )
addr + = 0x40 * line ;
pvc_write ( 0x80 | addr , MODE_INST ) ;
while ( * str ! = 0 & & i < PVC_LINELEN ) {
pvc_write ( * str + + , MODE_DATA ) ;
i + + ;
}
}
void pvc_write_string_centered ( const unsigned char * str , int line )
{
int len = strlen ( str ) ;
u8 addr ;
if ( len > PVC_VISIBLE_CHARS )
addr = 0 ;
else
addr = ( PVC_VISIBLE_CHARS - strlen ( str ) ) / 2 ;
pvc_write_string ( str , addr , line ) ;
}
void pvc_dump_string ( const unsigned char * str )
{
int len = strlen ( str ) ;
pvc_write_string ( str , 0 , 0 ) ;
if ( len > PVC_VISIBLE_CHARS )
pvc_write_string ( & str [ PVC_VISIBLE_CHARS ] , 0 , 1 ) ;
}
# define BM_SIZE 8
# define MAX_PROGRAMMABLE_CHARS 8
int pvc_program_cg ( int charnum , u8 bitmap [ BM_SIZE ] )
{
int i ;
int addr ;
if ( charnum > MAX_PROGRAMMABLE_CHARS )
return - ENOENT ;
addr = charnum * 8 ;
pvc_write ( 0x40 | addr , MODE_INST ) ;
for ( i = 0 ; i < BM_SIZE ; i + + )
pvc_write ( bitmap [ i ] , MODE_DATA ) ;
return 0 ;
}
# define FUNC_SET_CMD 0x20
2013-01-22 12:59:30 +01:00
# define EIGHT_BYTE (1 << 4)
# define FOUR_BYTE 0
# define TWO_LINES (1 << 3)
# define ONE_LINE 0
# define LARGE_FONT (1 << 2)
# define SMALL_FONT 0
2007-08-21 22:34:16 +02:00
static void pvc_funcset ( u8 cmd )
{
pvc_write ( FUNC_SET_CMD | ( cmd & ( EIGHT_BYTE | TWO_LINES | LARGE_FONT ) ) ,
MODE_INST ) ;
}
# define ENTRYMODE_CMD 0x4
2013-01-22 12:59:30 +01:00
# define AUTO_INC (1 << 1)
# define AUTO_DEC 0
# define CURSOR_FOLLOWS_DISP (1 << 0)
2007-08-21 22:34:16 +02:00
static void pvc_entrymode ( u8 cmd )
{
pvc_write ( ENTRYMODE_CMD | ( cmd & ( AUTO_INC | CURSOR_FOLLOWS_DISP ) ) ,
MODE_INST ) ;
}
# define DISP_CNT_CMD 0x08
2013-01-22 12:59:30 +01:00
# define DISP_OFF 0
# define DISP_ON (1 << 2)
# define CUR_ON (1 << 1)
# define CUR_BLINK (1 << 0)
2007-08-21 22:34:16 +02:00
void pvc_dispcnt ( u8 cmd )
{
pvc_write ( DISP_CNT_CMD | ( cmd & ( DISP_ON | CUR_ON | CUR_BLINK ) ) , MODE_INST ) ;
}
# define MOVE_CMD 0x10
2013-01-22 12:59:30 +01:00
# define DISPLAY (1 << 3)
# define CURSOR 0
# define RIGHT (1 << 2)
# define LEFT 0
2007-08-21 22:34:16 +02:00
void pvc_move ( u8 cmd )
{
pvc_write ( MOVE_CMD | ( cmd & ( DISPLAY | RIGHT ) ) , MODE_INST ) ;
}
# define CLEAR_CMD 0x1
void pvc_clear ( void )
{
pvc_write ( CLEAR_CMD , MODE_INST ) ;
}
# define HOME_CMD 0x2
void pvc_home ( void )
{
pvc_write ( HOME_CMD , MODE_INST ) ;
}
int pvc_init ( void )
{
u8 cmd = EIGHT_BYTE ;
if ( PVC_NLINES = = 2 )
cmd | = ( SMALL_FONT | TWO_LINES ) ;
else
cmd | = ( LARGE_FONT | ONE_LINE ) ;
pvc_funcset ( cmd ) ;
pvc_dispcnt ( DISP_ON ) ;
pvc_entrymode ( AUTO_INC ) ;
pvc_clear ( ) ;
pvc_write_string_centered ( " Display " , 0 ) ;
pvc_write_string_centered ( " Initialized " , 1 ) ;
return 0 ;
}
module_init ( pvc_init ) ;
MODULE_LICENSE ( " GPL " ) ;