OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [auxdisplay/] [cfag12864b.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *    Filename: cfag12864b.c
3
 *     Version: 0.1.0
4
 * Description: cfag12864b LCD driver
5
 *     License: GPLv2
6
 *     Depends: ks0108
7
 *
8
 *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
9
 *        Date: 2006-10-31
10
 *
11
 *  This program is free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License version 2 as
13
 *  published by the Free Software Foundation.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program; if not, write to the Free Software
22
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 *
24
 */
25
 
26
#include <linux/init.h>
27
#include <linux/module.h>
28
#include <linux/kernel.h>
29
#include <linux/fs.h>
30
#include <linux/cdev.h>
31
#include <linux/delay.h>
32
#include <linux/device.h>
33
#include <linux/jiffies.h>
34
#include <linux/mutex.h>
35
#include <linux/uaccess.h>
36
#include <linux/vmalloc.h>
37
#include <linux/workqueue.h>
38
#include <linux/ks0108.h>
39
#include <linux/cfag12864b.h>
40
 
41
 
42
#define CFAG12864B_NAME "cfag12864b"
43
 
44
/*
45
 * Module Parameters
46
 */
47
 
48
static unsigned int cfag12864b_rate = CONFIG_CFAG12864B_RATE;
49
module_param(cfag12864b_rate, uint, S_IRUGO);
50
MODULE_PARM_DESC(cfag12864b_rate,
51
        "Refresh rate (hertzs)");
52
 
53
unsigned int cfag12864b_getrate(void)
54
{
55
        return cfag12864b_rate;
56
}
57
 
58
/*
59
 * cfag12864b Commands
60
 *
61
 *      E = Enable signal
62
 *              Everytime E switch from low to high,
63
 *              cfag12864b/ks0108 reads the command/data.
64
 *
65
 *      CS1 = First ks0108controller.
66
 *              If high, the first ks0108 controller receives commands/data.
67
 *
68
 *      CS2 = Second ks0108 controller
69
 *              If high, the second ks0108 controller receives commands/data.
70
 *
71
 *      DI = Data/Instruction
72
 *              If low, cfag12864b will expect commands.
73
 *              If high, cfag12864b will expect data.
74
 *
75
 */
76
 
77
#define bit(n) (((unsigned char)1)<<(n))
78
 
79
#define CFAG12864B_BIT_E        (0)
80
#define CFAG12864B_BIT_CS1      (2)
81
#define CFAG12864B_BIT_CS2      (1)
82
#define CFAG12864B_BIT_DI       (3)
83
 
84
static unsigned char cfag12864b_state;
85
 
86
static void cfag12864b_set(void)
87
{
88
        ks0108_writecontrol(cfag12864b_state);
89
}
90
 
91
static void cfag12864b_setbit(unsigned char state, unsigned char n)
92
{
93
        if (state)
94
                cfag12864b_state |= bit(n);
95
        else
96
                cfag12864b_state &= ~bit(n);
97
}
98
 
99
static void cfag12864b_e(unsigned char state)
100
{
101
        cfag12864b_setbit(state, CFAG12864B_BIT_E);
102
        cfag12864b_set();
103
}
104
 
105
static void cfag12864b_cs1(unsigned char state)
106
{
107
        cfag12864b_setbit(state, CFAG12864B_BIT_CS1);
108
}
109
 
110
static void cfag12864b_cs2(unsigned char state)
111
{
112
        cfag12864b_setbit(state, CFAG12864B_BIT_CS2);
113
}
114
 
115
static void cfag12864b_di(unsigned char state)
116
{
117
        cfag12864b_setbit(state, CFAG12864B_BIT_DI);
118
}
119
 
120
static void cfag12864b_setcontrollers(unsigned char first,
121
        unsigned char second)
122
{
123
        if (first)
124
                cfag12864b_cs1(0);
125
        else
126
                cfag12864b_cs1(1);
127
 
128
        if (second)
129
                cfag12864b_cs2(0);
130
        else
131
                cfag12864b_cs2(1);
132
}
133
 
134
static void cfag12864b_controller(unsigned char which)
135
{
136
        if (which == 0)
137
                cfag12864b_setcontrollers(1, 0);
138
        else if (which == 1)
139
                cfag12864b_setcontrollers(0, 1);
140
}
141
 
142
static void cfag12864b_displaystate(unsigned char state)
143
{
144
        cfag12864b_di(0);
145
        cfag12864b_e(1);
146
        ks0108_displaystate(state);
147
        cfag12864b_e(0);
148
}
149
 
150
static void cfag12864b_address(unsigned char address)
151
{
152
        cfag12864b_di(0);
153
        cfag12864b_e(1);
154
        ks0108_address(address);
155
        cfag12864b_e(0);
156
}
157
 
158
static void cfag12864b_page(unsigned char page)
159
{
160
        cfag12864b_di(0);
161
        cfag12864b_e(1);
162
        ks0108_page(page);
163
        cfag12864b_e(0);
164
}
165
 
166
static void cfag12864b_startline(unsigned char startline)
167
{
168
        cfag12864b_di(0);
169
        cfag12864b_e(1);
170
        ks0108_startline(startline);
171
        cfag12864b_e(0);
172
}
173
 
174
static void cfag12864b_writebyte(unsigned char byte)
175
{
176
        cfag12864b_di(1);
177
        cfag12864b_e(1);
178
        ks0108_writedata(byte);
179
        cfag12864b_e(0);
180
}
181
 
182
static void cfag12864b_nop(void)
183
{
184
        cfag12864b_startline(0);
185
}
186
 
187
/*
188
 * cfag12864b Internal Commands
189
 */
190
 
191
static void cfag12864b_on(void)
192
{
193
        cfag12864b_setcontrollers(1, 1);
194
        cfag12864b_displaystate(1);
195
}
196
 
197
static void cfag12864b_off(void)
198
{
199
        cfag12864b_setcontrollers(1, 1);
200
        cfag12864b_displaystate(0);
201
}
202
 
203
static void cfag12864b_clear(void)
204
{
205
        unsigned char i, j;
206
 
207
        cfag12864b_setcontrollers(1, 1);
208
        for (i = 0; i < CFAG12864B_PAGES; i++) {
209
                cfag12864b_page(i);
210
                cfag12864b_address(0);
211
                for (j = 0; j < CFAG12864B_ADDRESSES; j++)
212
                        cfag12864b_writebyte(0);
213
        }
214
}
215
 
216
/*
217
 * Update work
218
 */
219
 
220
unsigned char *cfag12864b_buffer;
221
static unsigned char *cfag12864b_cache;
222
static DEFINE_MUTEX(cfag12864b_mutex);
223
static unsigned char cfag12864b_updating;
224
static void cfag12864b_update(struct work_struct *delayed_work);
225
static struct workqueue_struct *cfag12864b_workqueue;
226
static DECLARE_DELAYED_WORK(cfag12864b_work, cfag12864b_update);
227
 
228
static void cfag12864b_queue(void)
229
{
230
        queue_delayed_work(cfag12864b_workqueue, &cfag12864b_work,
231
                HZ / cfag12864b_rate);
232
}
233
 
234
unsigned char cfag12864b_enable(void)
235
{
236
        unsigned char ret;
237
 
238
        mutex_lock(&cfag12864b_mutex);
239
 
240
        if (!cfag12864b_updating) {
241
                cfag12864b_updating = 1;
242
                cfag12864b_queue();
243
                ret = 0;
244
        } else
245
                ret = 1;
246
 
247
        mutex_unlock(&cfag12864b_mutex);
248
 
249
        return ret;
250
}
251
 
252
void cfag12864b_disable(void)
253
{
254
        mutex_lock(&cfag12864b_mutex);
255
 
256
        if (cfag12864b_updating) {
257
                cfag12864b_updating = 0;
258
                cancel_delayed_work(&cfag12864b_work);
259
                flush_workqueue(cfag12864b_workqueue);
260
        }
261
 
262
        mutex_unlock(&cfag12864b_mutex);
263
}
264
 
265
unsigned char cfag12864b_isenabled(void)
266
{
267
        return cfag12864b_updating;
268
}
269
 
270
static void cfag12864b_update(struct work_struct *work)
271
{
272
        unsigned char c;
273
        unsigned short i, j, k, b;
274
 
275
        if (memcmp(cfag12864b_cache, cfag12864b_buffer, CFAG12864B_SIZE)) {
276
                for (i = 0; i < CFAG12864B_CONTROLLERS; i++) {
277
                        cfag12864b_controller(i);
278
                        cfag12864b_nop();
279
                        for (j = 0; j < CFAG12864B_PAGES; j++) {
280
                                cfag12864b_page(j);
281
                                cfag12864b_nop();
282
                                cfag12864b_address(0);
283
                                cfag12864b_nop();
284
                                for (k = 0; k < CFAG12864B_ADDRESSES; k++) {
285
                                        for (c = 0, b = 0; b < 8; b++)
286
                                                if (cfag12864b_buffer
287
                                                        [i * CFAG12864B_ADDRESSES / 8
288
                                                        + k / 8 + (j * 8 + b) *
289
                                                        CFAG12864B_WIDTH / 8]
290
                                                        & bit(k % 8))
291
                                                        c |= bit(b);
292
                                        cfag12864b_writebyte(c);
293
                                }
294
                        }
295
                }
296
 
297
                memcpy(cfag12864b_cache, cfag12864b_buffer, CFAG12864B_SIZE);
298
        }
299
 
300
        if (cfag12864b_updating)
301
                cfag12864b_queue();
302
}
303
 
304
/*
305
 * cfag12864b Exported Symbols
306
 */
307
 
308
EXPORT_SYMBOL_GPL(cfag12864b_buffer);
309
EXPORT_SYMBOL_GPL(cfag12864b_getrate);
310
EXPORT_SYMBOL_GPL(cfag12864b_enable);
311
EXPORT_SYMBOL_GPL(cfag12864b_disable);
312
EXPORT_SYMBOL_GPL(cfag12864b_isenabled);
313
 
314
/*
315
 * Is the module inited?
316
 */
317
 
318
static unsigned char cfag12864b_inited;
319
unsigned char cfag12864b_isinited(void)
320
{
321
        return cfag12864b_inited;
322
}
323
EXPORT_SYMBOL_GPL(cfag12864b_isinited);
324
 
325
/*
326
 * Module Init & Exit
327
 */
328
 
329
static int __init cfag12864b_init(void)
330
{
331
        int ret = -EINVAL;
332
 
333
        /* ks0108_init() must be called first */
334
        if (!ks0108_isinited()) {
335
                printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
336
                        "ks0108 is not initialized\n");
337
                goto none;
338
        }
339
 
340
        if (PAGE_SIZE < CFAG12864B_SIZE) {
341
                printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
342
                        "page size (%i) < cfag12864b size (%i)\n",
343
                        (unsigned int)PAGE_SIZE, CFAG12864B_SIZE);
344
                ret = -ENOMEM;
345
                goto none;
346
        }
347
 
348
        cfag12864b_buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
349
        if (cfag12864b_buffer == NULL) {
350
                printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
351
                        "can't get a free page\n");
352
                ret = -ENOMEM;
353
                goto none;
354
        }
355
 
356
        cfag12864b_cache = kmalloc(sizeof(unsigned char) *
357
                CFAG12864B_SIZE, GFP_KERNEL);
358
        if (cfag12864b_cache == NULL) {
359
                printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
360
                        "can't alloc cache buffer (%i bytes)\n",
361
                        CFAG12864B_SIZE);
362
                ret = -ENOMEM;
363
                goto bufferalloced;
364
        }
365
 
366
        cfag12864b_workqueue = create_singlethread_workqueue(CFAG12864B_NAME);
367
        if (cfag12864b_workqueue == NULL)
368
                goto cachealloced;
369
 
370
        memset(cfag12864b_buffer, 0, CFAG12864B_SIZE);
371
 
372
        cfag12864b_clear();
373
        cfag12864b_on();
374
 
375
        cfag12864b_inited = 1;
376
        return 0;
377
 
378
cachealloced:
379
        kfree(cfag12864b_cache);
380
 
381
bufferalloced:
382
        free_page((unsigned long) cfag12864b_buffer);
383
 
384
none:
385
        return ret;
386
}
387
 
388
static void __exit cfag12864b_exit(void)
389
{
390
        cfag12864b_disable();
391
        cfag12864b_off();
392
        destroy_workqueue(cfag12864b_workqueue);
393
        kfree(cfag12864b_cache);
394
        free_page((unsigned long) cfag12864b_buffer);
395
}
396
 
397
module_init(cfag12864b_init);
398
module_exit(cfag12864b_exit);
399
 
400
MODULE_LICENSE("GPL v2");
401
MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>");
402
MODULE_DESCRIPTION("cfag12864b LCD driver");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.