Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/lasat/picvue.c
10817 views
1
/*
2
* Picvue PVC160206 display driver
3
*
4
* Brian Murphy <[email protected]>
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
#include <linux/string.h>
15
16
#include "picvue.h"
17
18
#define PVC_BUSY 0x80
19
#define PVC_NLINES 2
20
#define PVC_DISPMEM 80
21
#define PVC_LINELEN PVC_DISPMEM / PVC_NLINES
22
23
struct pvc_defs *picvue;
24
25
static void pvc_reg_write(u32 val)
26
{
27
*picvue->reg = val;
28
}
29
30
static u32 pvc_reg_read(void)
31
{
32
u32 tmp = *picvue->reg;
33
return tmp;
34
}
35
36
static void pvc_write_byte(u32 data, u8 byte)
37
{
38
data |= picvue->e;
39
pvc_reg_write(data);
40
data &= ~picvue->data_mask;
41
data |= byte << picvue->data_shift;
42
pvc_reg_write(data);
43
ndelay(220);
44
pvc_reg_write(data & ~picvue->e);
45
ndelay(220);
46
}
47
48
static u8 pvc_read_byte(u32 data)
49
{
50
u8 byte;
51
52
data |= picvue->e;
53
pvc_reg_write(data);
54
ndelay(220);
55
byte = (pvc_reg_read() & picvue->data_mask) >> picvue->data_shift;
56
data &= ~picvue->e;
57
pvc_reg_write(data);
58
ndelay(220);
59
return byte;
60
}
61
62
static u8 pvc_read_data(void)
63
{
64
u32 data = pvc_reg_read();
65
u8 byte;
66
data |= picvue->rw;
67
data &= ~picvue->rs;
68
pvc_reg_write(data);
69
ndelay(40);
70
byte = pvc_read_byte(data);
71
data |= picvue->rs;
72
pvc_reg_write(data);
73
return byte;
74
}
75
76
#define TIMEOUT 1000
77
static int pvc_wait(void)
78
{
79
int i = TIMEOUT;
80
int err = 0;
81
82
while ((pvc_read_data() & PVC_BUSY) && i)
83
i--;
84
if (i == 0)
85
err = -ETIME;
86
87
return err;
88
}
89
90
#define MODE_INST 0
91
#define MODE_DATA 1
92
static void pvc_write(u8 byte, int mode)
93
{
94
u32 data = pvc_reg_read();
95
data &= ~picvue->rw;
96
if (mode == MODE_DATA)
97
data |= picvue->rs;
98
else
99
data &= ~picvue->rs;
100
pvc_reg_write(data);
101
ndelay(40);
102
pvc_write_byte(data, byte);
103
if (mode == MODE_DATA)
104
data &= ~picvue->rs;
105
else
106
data |= picvue->rs;
107
pvc_reg_write(data);
108
pvc_wait();
109
}
110
111
void pvc_write_string(const unsigned char *str, u8 addr, int line)
112
{
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
void pvc_write_string_centered(const unsigned char *str, int line)
126
{
127
int len = strlen(str);
128
u8 addr;
129
130
if (len > PVC_VISIBLE_CHARS)
131
addr = 0;
132
else
133
addr = (PVC_VISIBLE_CHARS - strlen(str))/2;
134
135
pvc_write_string(str, addr, line);
136
}
137
138
void pvc_dump_string(const unsigned char *str)
139
{
140
int len = strlen(str);
141
142
pvc_write_string(str, 0, 0);
143
if (len > PVC_VISIBLE_CHARS)
144
pvc_write_string(&str[PVC_VISIBLE_CHARS], 0, 1);
145
}
146
147
#define BM_SIZE 8
148
#define MAX_PROGRAMMABLE_CHARS 8
149
int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE])
150
{
151
int i;
152
int addr;
153
154
if (charnum > MAX_PROGRAMMABLE_CHARS)
155
return -ENOENT;
156
157
addr = charnum * 8;
158
pvc_write(0x40 | addr, MODE_INST);
159
160
for (i = 0; i < BM_SIZE; i++)
161
pvc_write(bitmap[i], MODE_DATA);
162
return 0;
163
}
164
165
#define FUNC_SET_CMD 0x20
166
#define EIGHT_BYTE (1 << 4)
167
#define FOUR_BYTE 0
168
#define TWO_LINES (1 << 3)
169
#define ONE_LINE 0
170
#define LARGE_FONT (1 << 2)
171
#define SMALL_FONT 0
172
173
static void pvc_funcset(u8 cmd)
174
{
175
pvc_write(FUNC_SET_CMD | (cmd & (EIGHT_BYTE|TWO_LINES|LARGE_FONT)),
176
MODE_INST);
177
}
178
179
#define ENTRYMODE_CMD 0x4
180
#define AUTO_INC (1 << 1)
181
#define AUTO_DEC 0
182
#define CURSOR_FOLLOWS_DISP (1 << 0)
183
184
static void pvc_entrymode(u8 cmd)
185
{
186
pvc_write(ENTRYMODE_CMD | (cmd & (AUTO_INC|CURSOR_FOLLOWS_DISP)),
187
MODE_INST);
188
}
189
190
#define DISP_CNT_CMD 0x08
191
#define DISP_OFF 0
192
#define DISP_ON (1 << 2)
193
#define CUR_ON (1 << 1)
194
#define CUR_BLINK (1 << 0)
195
void pvc_dispcnt(u8 cmd)
196
{
197
pvc_write(DISP_CNT_CMD | (cmd & (DISP_ON|CUR_ON|CUR_BLINK)), MODE_INST);
198
}
199
200
#define MOVE_CMD 0x10
201
#define DISPLAY (1 << 3)
202
#define CURSOR 0
203
#define RIGHT (1 << 2)
204
#define LEFT 0
205
void pvc_move(u8 cmd)
206
{
207
pvc_write(MOVE_CMD | (cmd & (DISPLAY|RIGHT)), MODE_INST);
208
}
209
210
#define CLEAR_CMD 0x1
211
void pvc_clear(void)
212
{
213
pvc_write(CLEAR_CMD, MODE_INST);
214
}
215
216
#define HOME_CMD 0x2
217
void pvc_home(void)
218
{
219
pvc_write(HOME_CMD, MODE_INST);
220
}
221
222
int pvc_init(void)
223
{
224
u8 cmd = EIGHT_BYTE;
225
226
if (PVC_NLINES == 2)
227
cmd |= (SMALL_FONT|TWO_LINES);
228
else
229
cmd |= (LARGE_FONT|ONE_LINE);
230
pvc_funcset(cmd);
231
pvc_dispcnt(DISP_ON);
232
pvc_entrymode(AUTO_INC);
233
234
pvc_clear();
235
pvc_write_string_centered("Display", 0);
236
pvc_write_string_centered("Initialized", 1);
237
238
return 0;
239
}
240
241
module_init(pvc_init);
242
MODULE_LICENSE("GPL");
243
244