1/* 2 * Picvue PVC160206 display driver 3 * 4 * Brian Murphy <brian@murphy.dk> 5 * 6 */ 7#include <linux/kernel.h> 8#include <linux/delay.h> 9#include <asm/bootinfo.h> 10#include <asm/lasat/lasat.h> 11#include <linux/module.h> 12#include <linux/init.h> 13#include <linux/errno.h> 14 15#include "picvue.h" 16 17#define PVC_BUSY 0x80 18#define PVC_NLINES 2 19#define PVC_DISPMEM 80 20#define PVC_LINELEN PVC_DISPMEM / PVC_NLINES 21 22struct pvc_defs *picvue = NULL; 23 24DECLARE_MUTEX(pvc_sem); 25 26static void pvc_reg_write(u32 val) 27{ 28 *picvue->reg = val; 29} 30 31static u32 pvc_reg_read(void) 32{ 33 u32 tmp = *picvue->reg; 34 return tmp; 35} 36 37static void pvc_write_byte(u32 data, u8 byte) 38{ 39 data |= picvue->e; 40 pvc_reg_write(data); 41 data &= ~picvue->data_mask; 42 data |= byte << picvue->data_shift; 43 pvc_reg_write(data); 44 ndelay(220); 45 pvc_reg_write(data & ~picvue->e); 46 ndelay(220); 47} 48 49static u8 pvc_read_byte(u32 data) 50{ 51 u8 byte; 52 53 data |= picvue->e; 54 pvc_reg_write(data); 55 ndelay(220); 56 byte = (pvc_reg_read() & picvue->data_mask) >> picvue->data_shift; 57 data &= ~picvue->e; 58 pvc_reg_write(data); 59 ndelay(220); 60 return byte; 61} 62 63static u8 pvc_read_data(void) 64{ 65 u32 data = pvc_reg_read(); 66 u8 byte; 67 data |= picvue->rw; 68 data &= ~picvue->rs; 69 pvc_reg_write(data); 70 ndelay(40); 71 byte = pvc_read_byte(data); 72 data |= picvue->rs; 73 pvc_reg_write(data); 74 return byte; 75} 76 77#define TIMEOUT 1000 78static int pvc_wait(void) 79{ 80 int i = TIMEOUT; 81 int err = 0; 82 83 while ((pvc_read_data() & PVC_BUSY) && i) 84 i--; 85 if (i == 0) 86 err = -ETIME; 87 88 return err; 89} 90 91#define MODE_INST 0 92#define MODE_DATA 1 93static void pvc_write(u8 byte, int mode) 94{ 95 u32 data = pvc_reg_read(); 96 data &= ~picvue->rw; 97 if (mode == MODE_DATA) 98 data |= picvue->rs; 99 else 100 data &= ~picvue->rs; 101 pvc_reg_write(data); 102 ndelay(40); 103 pvc_write_byte(data, byte); 104 if (mode == MODE_DATA) 105 data &= ~picvue->rs; 106 else 107 data |= picvue->rs; 108 pvc_reg_write(data); 109 pvc_wait(); 110} 111 112void pvc_write_string(const unsigned char *str, u8 addr, int line) { 113 int i = 0; 114 115 if (line > 0 && (PVC_NLINES > 1)) 116 addr += 0x40 * line; 117 pvc_write(0x80 | addr, MODE_INST); 118 119 while (*str != 0 && i < PVC_LINELEN) { 120 pvc_write(*str++, MODE_DATA); 121 i++; 122 } 123} 124 125#define BM_SIZE 8 126#define MAX_PROGRAMMABLE_CHARS 8 127int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE]) { 128 int i; 129 int addr; 130 131 if (charnum > MAX_PROGRAMMABLE_CHARS) 132 return -ENOENT; 133 134 addr = charnum * 8; 135 pvc_write(0x40 | addr, MODE_INST); 136 137 for (i=0; i<BM_SIZE; i++) 138 pvc_write(bitmap[i], MODE_DATA); 139 return 0; 140} 141 142#define FUNC_SET_CMD 0x20 143#define EIGHT_BYTE (1 << 4) 144#define FOUR_BYTE 0 145#define TWO_LINES (1 << 3) 146#define ONE_LINE 0 147#define LARGE_FONT (1 << 2) 148#define SMALL_FONT 0 149static void pvc_funcset(u8 cmd) { 150 pvc_write(FUNC_SET_CMD | (cmd & (EIGHT_BYTE|TWO_LINES|LARGE_FONT)), MODE_INST); 151} 152 153#define ENTRYMODE_CMD 0x4 154#define AUTO_INC (1 << 1) 155#define AUTO_DEC 0 156#define CURSOR_FOLLOWS_DISP (1 << 0) 157static void pvc_entrymode(u8 cmd) { 158 pvc_write(ENTRYMODE_CMD | (cmd & (AUTO_INC|CURSOR_FOLLOWS_DISP)), MODE_INST); 159} 160 161#define DISP_CNT_CMD 0x08 162#define DISP_OFF 0 163#define DISP_ON (1 << 2) 164#define CUR_ON (1 << 1) 165#define CUR_BLINK (1 << 0) 166void pvc_dispcnt(u8 cmd) { 167 pvc_write(DISP_CNT_CMD | (cmd & (DISP_ON|CUR_ON|CUR_BLINK)), MODE_INST); 168} 169 170#define MOVE_CMD 0x10 171#define DISPLAY (1 << 3) 172#define CURSOR 0 173#define RIGHT (1 << 2) 174#define LEFT 0 175void pvc_move(u8 cmd) { 176 pvc_write(MOVE_CMD | (cmd & (DISPLAY|RIGHT)), MODE_INST); 177} 178 179#define CLEAR_CMD 0x1 180void pvc_clear(void) { 181 pvc_write(CLEAR_CMD, MODE_INST); 182} 183 184#define HOME_CMD 0x2 185void pvc_home(void) { 186 pvc_write(HOME_CMD, MODE_INST); 187} 188 189int pvc_init(void) 190{ 191 u8 cmd = EIGHT_BYTE; 192 193 if (PVC_NLINES == 2) 194 cmd |= (SMALL_FONT|TWO_LINES); 195 else 196 cmd |= (LARGE_FONT|ONE_LINE); 197 pvc_funcset(cmd); 198 pvc_dispcnt(DISP_ON); 199 pvc_entrymode(AUTO_INC); 200 201 return 0; 202} 203 204module_init(pvc_init); 205MODULE_LICENSE("GPL"); 206