1351f683bSMiguel Ojeda // SPDX-License-Identifier: GPL-2.0
270e84049SMiguel Ojeda Sandonis /*
370e84049SMiguel Ojeda Sandonis * Filename: cfag12864b.c
470e84049SMiguel Ojeda Sandonis * Version: 0.1.0
570e84049SMiguel Ojeda Sandonis * Description: cfag12864b LCD driver
670e84049SMiguel Ojeda Sandonis * Depends: ks0108
770e84049SMiguel Ojeda Sandonis *
8c131bd0bSMiguel Ojeda * Author: Copyright (C) Miguel Ojeda <ojeda@kernel.org>
970e84049SMiguel Ojeda Sandonis * Date: 2006-10-31
1070e84049SMiguel Ojeda Sandonis */
1170e84049SMiguel Ojeda Sandonis
1270e84049SMiguel Ojeda Sandonis #include <linux/init.h>
1370e84049SMiguel Ojeda Sandonis #include <linux/module.h>
1470e84049SMiguel Ojeda Sandonis #include <linux/kernel.h>
1570e84049SMiguel Ojeda Sandonis #include <linux/fs.h>
165a0e3ad6STejun Heo #include <linux/slab.h>
1770e84049SMiguel Ojeda Sandonis #include <linux/cdev.h>
1870e84049SMiguel Ojeda Sandonis #include <linux/delay.h>
1970e84049SMiguel Ojeda Sandonis #include <linux/device.h>
2070e84049SMiguel Ojeda Sandonis #include <linux/jiffies.h>
2170e84049SMiguel Ojeda Sandonis #include <linux/mutex.h>
2270e84049SMiguel Ojeda Sandonis #include <linux/uaccess.h>
2370e84049SMiguel Ojeda Sandonis #include <linux/vmalloc.h>
2470e84049SMiguel Ojeda Sandonis #include <linux/workqueue.h>
2570e84049SMiguel Ojeda Sandonis #include <linux/ks0108.h>
2670e84049SMiguel Ojeda Sandonis #include <linux/cfag12864b.h>
2770e84049SMiguel Ojeda Sandonis
2870e84049SMiguel Ojeda Sandonis
2970e84049SMiguel Ojeda Sandonis #define CFAG12864B_NAME "cfag12864b"
3070e84049SMiguel Ojeda Sandonis
3170e84049SMiguel Ojeda Sandonis /*
3270e84049SMiguel Ojeda Sandonis * Module Parameters
3370e84049SMiguel Ojeda Sandonis */
3470e84049SMiguel Ojeda Sandonis
3570e84049SMiguel Ojeda Sandonis static unsigned int cfag12864b_rate = CONFIG_CFAG12864B_RATE;
36*24ebc044SJinchao Wang module_param(cfag12864b_rate, uint, 0444);
3770e84049SMiguel Ojeda Sandonis MODULE_PARM_DESC(cfag12864b_rate,
3825985edcSLucas De Marchi "Refresh rate (hertz)");
3970e84049SMiguel Ojeda Sandonis
cfag12864b_getrate(void)4070e84049SMiguel Ojeda Sandonis unsigned int cfag12864b_getrate(void)
4170e84049SMiguel Ojeda Sandonis {
4270e84049SMiguel Ojeda Sandonis return cfag12864b_rate;
4370e84049SMiguel Ojeda Sandonis }
4470e84049SMiguel Ojeda Sandonis
4570e84049SMiguel Ojeda Sandonis /*
4670e84049SMiguel Ojeda Sandonis * cfag12864b Commands
4770e84049SMiguel Ojeda Sandonis *
4870e84049SMiguel Ojeda Sandonis * E = Enable signal
4970e84049SMiguel Ojeda Sandonis * Every time E switch from low to high,
5070e84049SMiguel Ojeda Sandonis * cfag12864b/ks0108 reads the command/data.
5170e84049SMiguel Ojeda Sandonis *
5270e84049SMiguel Ojeda Sandonis * CS1 = First ks0108controller.
5370e84049SMiguel Ojeda Sandonis * If high, the first ks0108 controller receives commands/data.
5470e84049SMiguel Ojeda Sandonis *
5570e84049SMiguel Ojeda Sandonis * CS2 = Second ks0108 controller
5670e84049SMiguel Ojeda Sandonis * If high, the second ks0108 controller receives commands/data.
5770e84049SMiguel Ojeda Sandonis *
5870e84049SMiguel Ojeda Sandonis * DI = Data/Instruction
5970e84049SMiguel Ojeda Sandonis * If low, cfag12864b will expect commands.
6070e84049SMiguel Ojeda Sandonis * If high, cfag12864b will expect data.
6170e84049SMiguel Ojeda Sandonis *
6270e84049SMiguel Ojeda Sandonis */
6370e84049SMiguel Ojeda Sandonis
6470e84049SMiguel Ojeda Sandonis #define bit(n) (((unsigned char)1)<<(n))
6570e84049SMiguel Ojeda Sandonis
6670e84049SMiguel Ojeda Sandonis #define CFAG12864B_BIT_E (0)
6770e84049SMiguel Ojeda Sandonis #define CFAG12864B_BIT_CS1 (2)
6870e84049SMiguel Ojeda Sandonis #define CFAG12864B_BIT_CS2 (1)
6970e84049SMiguel Ojeda Sandonis #define CFAG12864B_BIT_DI (3)
7070e84049SMiguel Ojeda Sandonis
7170e84049SMiguel Ojeda Sandonis static unsigned char cfag12864b_state;
7270e84049SMiguel Ojeda Sandonis
cfag12864b_set(void)7370e84049SMiguel Ojeda Sandonis static void cfag12864b_set(void)
7470e84049SMiguel Ojeda Sandonis {
7570e84049SMiguel Ojeda Sandonis ks0108_writecontrol(cfag12864b_state);
7670e84049SMiguel Ojeda Sandonis }
7770e84049SMiguel Ojeda Sandonis
cfag12864b_setbit(unsigned char state,unsigned char n)7870e84049SMiguel Ojeda Sandonis static void cfag12864b_setbit(unsigned char state, unsigned char n)
7970e84049SMiguel Ojeda Sandonis {
8070e84049SMiguel Ojeda Sandonis if (state)
8170e84049SMiguel Ojeda Sandonis cfag12864b_state |= bit(n);
8270e84049SMiguel Ojeda Sandonis else
8370e84049SMiguel Ojeda Sandonis cfag12864b_state &= ~bit(n);
8470e84049SMiguel Ojeda Sandonis }
8570e84049SMiguel Ojeda Sandonis
cfag12864b_e(unsigned char state)8670e84049SMiguel Ojeda Sandonis static void cfag12864b_e(unsigned char state)
8770e84049SMiguel Ojeda Sandonis {
8870e84049SMiguel Ojeda Sandonis cfag12864b_setbit(state, CFAG12864B_BIT_E);
8970e84049SMiguel Ojeda Sandonis cfag12864b_set();
9070e84049SMiguel Ojeda Sandonis }
9170e84049SMiguel Ojeda Sandonis
cfag12864b_cs1(unsigned char state)9270e84049SMiguel Ojeda Sandonis static void cfag12864b_cs1(unsigned char state)
9370e84049SMiguel Ojeda Sandonis {
9470e84049SMiguel Ojeda Sandonis cfag12864b_setbit(state, CFAG12864B_BIT_CS1);
9570e84049SMiguel Ojeda Sandonis }
9670e84049SMiguel Ojeda Sandonis
cfag12864b_cs2(unsigned char state)9770e84049SMiguel Ojeda Sandonis static void cfag12864b_cs2(unsigned char state)
9870e84049SMiguel Ojeda Sandonis {
9970e84049SMiguel Ojeda Sandonis cfag12864b_setbit(state, CFAG12864B_BIT_CS2);
10070e84049SMiguel Ojeda Sandonis }
10170e84049SMiguel Ojeda Sandonis
cfag12864b_di(unsigned char state)10270e84049SMiguel Ojeda Sandonis static void cfag12864b_di(unsigned char state)
10370e84049SMiguel Ojeda Sandonis {
10470e84049SMiguel Ojeda Sandonis cfag12864b_setbit(state, CFAG12864B_BIT_DI);
10570e84049SMiguel Ojeda Sandonis }
10670e84049SMiguel Ojeda Sandonis
cfag12864b_setcontrollers(unsigned char first,unsigned char second)10770e84049SMiguel Ojeda Sandonis static void cfag12864b_setcontrollers(unsigned char first,
10870e84049SMiguel Ojeda Sandonis unsigned char second)
10970e84049SMiguel Ojeda Sandonis {
11070e84049SMiguel Ojeda Sandonis if (first)
11170e84049SMiguel Ojeda Sandonis cfag12864b_cs1(0);
11270e84049SMiguel Ojeda Sandonis else
11370e84049SMiguel Ojeda Sandonis cfag12864b_cs1(1);
11470e84049SMiguel Ojeda Sandonis
11570e84049SMiguel Ojeda Sandonis if (second)
11670e84049SMiguel Ojeda Sandonis cfag12864b_cs2(0);
11770e84049SMiguel Ojeda Sandonis else
11870e84049SMiguel Ojeda Sandonis cfag12864b_cs2(1);
11970e84049SMiguel Ojeda Sandonis }
12070e84049SMiguel Ojeda Sandonis
cfag12864b_controller(unsigned char which)12170e84049SMiguel Ojeda Sandonis static void cfag12864b_controller(unsigned char which)
12270e84049SMiguel Ojeda Sandonis {
12370e84049SMiguel Ojeda Sandonis if (which == 0)
12470e84049SMiguel Ojeda Sandonis cfag12864b_setcontrollers(1, 0);
12570e84049SMiguel Ojeda Sandonis else if (which == 1)
12670e84049SMiguel Ojeda Sandonis cfag12864b_setcontrollers(0, 1);
12770e84049SMiguel Ojeda Sandonis }
12870e84049SMiguel Ojeda Sandonis
cfag12864b_displaystate(unsigned char state)12970e84049SMiguel Ojeda Sandonis static void cfag12864b_displaystate(unsigned char state)
13070e84049SMiguel Ojeda Sandonis {
13170e84049SMiguel Ojeda Sandonis cfag12864b_di(0);
13270e84049SMiguel Ojeda Sandonis cfag12864b_e(1);
13370e84049SMiguel Ojeda Sandonis ks0108_displaystate(state);
13470e84049SMiguel Ojeda Sandonis cfag12864b_e(0);
13570e84049SMiguel Ojeda Sandonis }
13670e84049SMiguel Ojeda Sandonis
cfag12864b_address(unsigned char address)13770e84049SMiguel Ojeda Sandonis static void cfag12864b_address(unsigned char address)
13870e84049SMiguel Ojeda Sandonis {
13970e84049SMiguel Ojeda Sandonis cfag12864b_di(0);
14070e84049SMiguel Ojeda Sandonis cfag12864b_e(1);
14170e84049SMiguel Ojeda Sandonis ks0108_address(address);
14270e84049SMiguel Ojeda Sandonis cfag12864b_e(0);
14370e84049SMiguel Ojeda Sandonis }
14470e84049SMiguel Ojeda Sandonis
cfag12864b_page(unsigned char page)14570e84049SMiguel Ojeda Sandonis static void cfag12864b_page(unsigned char page)
14670e84049SMiguel Ojeda Sandonis {
14770e84049SMiguel Ojeda Sandonis cfag12864b_di(0);
14870e84049SMiguel Ojeda Sandonis cfag12864b_e(1);
14970e84049SMiguel Ojeda Sandonis ks0108_page(page);
15070e84049SMiguel Ojeda Sandonis cfag12864b_e(0);
15170e84049SMiguel Ojeda Sandonis }
15270e84049SMiguel Ojeda Sandonis
cfag12864b_startline(unsigned char startline)15370e84049SMiguel Ojeda Sandonis static void cfag12864b_startline(unsigned char startline)
15470e84049SMiguel Ojeda Sandonis {
15570e84049SMiguel Ojeda Sandonis cfag12864b_di(0);
15670e84049SMiguel Ojeda Sandonis cfag12864b_e(1);
15770e84049SMiguel Ojeda Sandonis ks0108_startline(startline);
15870e84049SMiguel Ojeda Sandonis cfag12864b_e(0);
15970e84049SMiguel Ojeda Sandonis }
16070e84049SMiguel Ojeda Sandonis
cfag12864b_writebyte(unsigned char byte)16170e84049SMiguel Ojeda Sandonis static void cfag12864b_writebyte(unsigned char byte)
16270e84049SMiguel Ojeda Sandonis {
16370e84049SMiguel Ojeda Sandonis cfag12864b_di(1);
16470e84049SMiguel Ojeda Sandonis cfag12864b_e(1);
16570e84049SMiguel Ojeda Sandonis ks0108_writedata(byte);
16670e84049SMiguel Ojeda Sandonis cfag12864b_e(0);
16770e84049SMiguel Ojeda Sandonis }
16870e84049SMiguel Ojeda Sandonis
cfag12864b_nop(void)16970e84049SMiguel Ojeda Sandonis static void cfag12864b_nop(void)
17070e84049SMiguel Ojeda Sandonis {
17170e84049SMiguel Ojeda Sandonis cfag12864b_startline(0);
17270e84049SMiguel Ojeda Sandonis }
17370e84049SMiguel Ojeda Sandonis
17470e84049SMiguel Ojeda Sandonis /*
17570e84049SMiguel Ojeda Sandonis * cfag12864b Internal Commands
17670e84049SMiguel Ojeda Sandonis */
17770e84049SMiguel Ojeda Sandonis
cfag12864b_on(void)17870e84049SMiguel Ojeda Sandonis static void cfag12864b_on(void)
17970e84049SMiguel Ojeda Sandonis {
18070e84049SMiguel Ojeda Sandonis cfag12864b_setcontrollers(1, 1);
18170e84049SMiguel Ojeda Sandonis cfag12864b_displaystate(1);
18270e84049SMiguel Ojeda Sandonis }
18370e84049SMiguel Ojeda Sandonis
cfag12864b_off(void)18470e84049SMiguel Ojeda Sandonis static void cfag12864b_off(void)
18570e84049SMiguel Ojeda Sandonis {
18670e84049SMiguel Ojeda Sandonis cfag12864b_setcontrollers(1, 1);
18770e84049SMiguel Ojeda Sandonis cfag12864b_displaystate(0);
18870e84049SMiguel Ojeda Sandonis }
18970e84049SMiguel Ojeda Sandonis
cfag12864b_clear(void)19070e84049SMiguel Ojeda Sandonis static void cfag12864b_clear(void)
19170e84049SMiguel Ojeda Sandonis {
19270e84049SMiguel Ojeda Sandonis unsigned char i, j;
19370e84049SMiguel Ojeda Sandonis
19470e84049SMiguel Ojeda Sandonis cfag12864b_setcontrollers(1, 1);
19570e84049SMiguel Ojeda Sandonis for (i = 0; i < CFAG12864B_PAGES; i++) {
19670e84049SMiguel Ojeda Sandonis cfag12864b_page(i);
19770e84049SMiguel Ojeda Sandonis cfag12864b_address(0);
19870e84049SMiguel Ojeda Sandonis for (j = 0; j < CFAG12864B_ADDRESSES; j++)
19970e84049SMiguel Ojeda Sandonis cfag12864b_writebyte(0);
20070e84049SMiguel Ojeda Sandonis }
20170e84049SMiguel Ojeda Sandonis }
20270e84049SMiguel Ojeda Sandonis
20370e84049SMiguel Ojeda Sandonis /*
20470e84049SMiguel Ojeda Sandonis * Update work
20570e84049SMiguel Ojeda Sandonis */
20670e84049SMiguel Ojeda Sandonis
20770e84049SMiguel Ojeda Sandonis unsigned char *cfag12864b_buffer;
20870e84049SMiguel Ojeda Sandonis static unsigned char *cfag12864b_cache;
20970e84049SMiguel Ojeda Sandonis static DEFINE_MUTEX(cfag12864b_mutex);
21070e84049SMiguel Ojeda Sandonis static unsigned char cfag12864b_updating;
21170e84049SMiguel Ojeda Sandonis static void cfag12864b_update(struct work_struct *delayed_work);
21270e84049SMiguel Ojeda Sandonis static struct workqueue_struct *cfag12864b_workqueue;
21370e84049SMiguel Ojeda Sandonis static DECLARE_DELAYED_WORK(cfag12864b_work, cfag12864b_update);
21470e84049SMiguel Ojeda Sandonis
cfag12864b_queue(void)21570e84049SMiguel Ojeda Sandonis static void cfag12864b_queue(void)
21670e84049SMiguel Ojeda Sandonis {
21770e84049SMiguel Ojeda Sandonis queue_delayed_work(cfag12864b_workqueue, &cfag12864b_work,
21870e84049SMiguel Ojeda Sandonis HZ / cfag12864b_rate);
21970e84049SMiguel Ojeda Sandonis }
22070e84049SMiguel Ojeda Sandonis
cfag12864b_enable(void)22170e84049SMiguel Ojeda Sandonis unsigned char cfag12864b_enable(void)
22270e84049SMiguel Ojeda Sandonis {
22370e84049SMiguel Ojeda Sandonis unsigned char ret;
22470e84049SMiguel Ojeda Sandonis
22570e84049SMiguel Ojeda Sandonis mutex_lock(&cfag12864b_mutex);
22670e84049SMiguel Ojeda Sandonis
22770e84049SMiguel Ojeda Sandonis if (!cfag12864b_updating) {
22870e84049SMiguel Ojeda Sandonis cfag12864b_updating = 1;
22970e84049SMiguel Ojeda Sandonis cfag12864b_queue();
23070e84049SMiguel Ojeda Sandonis ret = 0;
23170e84049SMiguel Ojeda Sandonis } else
23270e84049SMiguel Ojeda Sandonis ret = 1;
23370e84049SMiguel Ojeda Sandonis
23470e84049SMiguel Ojeda Sandonis mutex_unlock(&cfag12864b_mutex);
23570e84049SMiguel Ojeda Sandonis
23670e84049SMiguel Ojeda Sandonis return ret;
23770e84049SMiguel Ojeda Sandonis }
23870e84049SMiguel Ojeda Sandonis
cfag12864b_disable(void)23970e84049SMiguel Ojeda Sandonis void cfag12864b_disable(void)
24070e84049SMiguel Ojeda Sandonis {
24170e84049SMiguel Ojeda Sandonis mutex_lock(&cfag12864b_mutex);
24270e84049SMiguel Ojeda Sandonis
24370e84049SMiguel Ojeda Sandonis if (cfag12864b_updating) {
24470e84049SMiguel Ojeda Sandonis cfag12864b_updating = 0;
24570e84049SMiguel Ojeda Sandonis cancel_delayed_work(&cfag12864b_work);
24670e84049SMiguel Ojeda Sandonis flush_workqueue(cfag12864b_workqueue);
24770e84049SMiguel Ojeda Sandonis }
24870e84049SMiguel Ojeda Sandonis
24970e84049SMiguel Ojeda Sandonis mutex_unlock(&cfag12864b_mutex);
25070e84049SMiguel Ojeda Sandonis }
25170e84049SMiguel Ojeda Sandonis
cfag12864b_isenabled(void)25270e84049SMiguel Ojeda Sandonis unsigned char cfag12864b_isenabled(void)
25370e84049SMiguel Ojeda Sandonis {
25470e84049SMiguel Ojeda Sandonis return cfag12864b_updating;
25570e84049SMiguel Ojeda Sandonis }
25670e84049SMiguel Ojeda Sandonis
cfag12864b_update(struct work_struct * work)25770e84049SMiguel Ojeda Sandonis static void cfag12864b_update(struct work_struct *work)
25870e84049SMiguel Ojeda Sandonis {
25970e84049SMiguel Ojeda Sandonis unsigned char c;
26070e84049SMiguel Ojeda Sandonis unsigned short i, j, k, b;
26170e84049SMiguel Ojeda Sandonis
26270e84049SMiguel Ojeda Sandonis if (memcmp(cfag12864b_cache, cfag12864b_buffer, CFAG12864B_SIZE)) {
26370e84049SMiguel Ojeda Sandonis for (i = 0; i < CFAG12864B_CONTROLLERS; i++) {
26470e84049SMiguel Ojeda Sandonis cfag12864b_controller(i);
26570e84049SMiguel Ojeda Sandonis cfag12864b_nop();
26670e84049SMiguel Ojeda Sandonis for (j = 0; j < CFAG12864B_PAGES; j++) {
26770e84049SMiguel Ojeda Sandonis cfag12864b_page(j);
26870e84049SMiguel Ojeda Sandonis cfag12864b_nop();
26970e84049SMiguel Ojeda Sandonis cfag12864b_address(0);
27070e84049SMiguel Ojeda Sandonis cfag12864b_nop();
27170e84049SMiguel Ojeda Sandonis for (k = 0; k < CFAG12864B_ADDRESSES; k++) {
27270e84049SMiguel Ojeda Sandonis for (c = 0, b = 0; b < 8; b++)
27370e84049SMiguel Ojeda Sandonis if (cfag12864b_buffer
27470e84049SMiguel Ojeda Sandonis [i * CFAG12864B_ADDRESSES / 8
27570e84049SMiguel Ojeda Sandonis + k / 8 + (j * 8 + b) *
27670e84049SMiguel Ojeda Sandonis CFAG12864B_WIDTH / 8]
27770e84049SMiguel Ojeda Sandonis & bit(k % 8))
27870e84049SMiguel Ojeda Sandonis c |= bit(b);
27970e84049SMiguel Ojeda Sandonis cfag12864b_writebyte(c);
28070e84049SMiguel Ojeda Sandonis }
28170e84049SMiguel Ojeda Sandonis }
28270e84049SMiguel Ojeda Sandonis }
28370e84049SMiguel Ojeda Sandonis
28470e84049SMiguel Ojeda Sandonis memcpy(cfag12864b_cache, cfag12864b_buffer, CFAG12864B_SIZE);
28570e84049SMiguel Ojeda Sandonis }
28670e84049SMiguel Ojeda Sandonis
28770e84049SMiguel Ojeda Sandonis if (cfag12864b_updating)
28870e84049SMiguel Ojeda Sandonis cfag12864b_queue();
28970e84049SMiguel Ojeda Sandonis }
29070e84049SMiguel Ojeda Sandonis
29170e84049SMiguel Ojeda Sandonis /*
29270e84049SMiguel Ojeda Sandonis * cfag12864b Exported Symbols
29370e84049SMiguel Ojeda Sandonis */
29470e84049SMiguel Ojeda Sandonis
29570e84049SMiguel Ojeda Sandonis EXPORT_SYMBOL_GPL(cfag12864b_buffer);
29670e84049SMiguel Ojeda Sandonis EXPORT_SYMBOL_GPL(cfag12864b_getrate);
29770e84049SMiguel Ojeda Sandonis EXPORT_SYMBOL_GPL(cfag12864b_enable);
29870e84049SMiguel Ojeda Sandonis EXPORT_SYMBOL_GPL(cfag12864b_disable);
29970e84049SMiguel Ojeda Sandonis EXPORT_SYMBOL_GPL(cfag12864b_isenabled);
30070e84049SMiguel Ojeda Sandonis
30170e84049SMiguel Ojeda Sandonis /*
30234173a4aSMiguel Ojeda * Is the module inited?
30334173a4aSMiguel Ojeda */
30434173a4aSMiguel Ojeda
30534173a4aSMiguel Ojeda static unsigned char cfag12864b_inited;
cfag12864b_isinited(void)30634173a4aSMiguel Ojeda unsigned char cfag12864b_isinited(void)
30734173a4aSMiguel Ojeda {
30834173a4aSMiguel Ojeda return cfag12864b_inited;
30934173a4aSMiguel Ojeda }
31034173a4aSMiguel Ojeda EXPORT_SYMBOL_GPL(cfag12864b_isinited);
31134173a4aSMiguel Ojeda
31234173a4aSMiguel Ojeda /*
31370e84049SMiguel Ojeda Sandonis * Module Init & Exit
31470e84049SMiguel Ojeda Sandonis */
31570e84049SMiguel Ojeda Sandonis
cfag12864b_init(void)31670e84049SMiguel Ojeda Sandonis static int __init cfag12864b_init(void)
31770e84049SMiguel Ojeda Sandonis {
31870e84049SMiguel Ojeda Sandonis int ret = -EINVAL;
31970e84049SMiguel Ojeda Sandonis
32034173a4aSMiguel Ojeda /* ks0108_init() must be called first */
32134173a4aSMiguel Ojeda if (!ks0108_isinited()) {
32234173a4aSMiguel Ojeda printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
32334173a4aSMiguel Ojeda "ks0108 is not initialized\n");
32434173a4aSMiguel Ojeda goto none;
32534173a4aSMiguel Ojeda }
326b340e8a5SAkinobu Mita BUILD_BUG_ON(PAGE_SIZE < CFAG12864B_SIZE);
32734173a4aSMiguel Ojeda
328b340e8a5SAkinobu Mita cfag12864b_buffer = (unsigned char *) get_zeroed_page(GFP_KERNEL);
32970e84049SMiguel Ojeda Sandonis if (cfag12864b_buffer == NULL) {
33070e84049SMiguel Ojeda Sandonis printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
33170e84049SMiguel Ojeda Sandonis "can't get a free page\n");
33270e84049SMiguel Ojeda Sandonis ret = -ENOMEM;
33370e84049SMiguel Ojeda Sandonis goto none;
33470e84049SMiguel Ojeda Sandonis }
33570e84049SMiguel Ojeda Sandonis
3366da2ec56SKees Cook cfag12864b_cache = kmalloc(CFAG12864B_SIZE,
3376da2ec56SKees Cook GFP_KERNEL);
338fe58103aSMiguel Ojeda if (cfag12864b_cache == NULL) {
33970e84049SMiguel Ojeda Sandonis printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
34070e84049SMiguel Ojeda Sandonis "can't alloc cache buffer (%i bytes)\n",
34170e84049SMiguel Ojeda Sandonis CFAG12864B_SIZE);
34270e84049SMiguel Ojeda Sandonis ret = -ENOMEM;
34370e84049SMiguel Ojeda Sandonis goto bufferalloced;
34470e84049SMiguel Ojeda Sandonis }
34570e84049SMiguel Ojeda Sandonis
34670e84049SMiguel Ojeda Sandonis cfag12864b_workqueue = create_singlethread_workqueue(CFAG12864B_NAME);
34770e84049SMiguel Ojeda Sandonis if (cfag12864b_workqueue == NULL)
34870e84049SMiguel Ojeda Sandonis goto cachealloced;
34970e84049SMiguel Ojeda Sandonis
35070e84049SMiguel Ojeda Sandonis cfag12864b_clear();
35170e84049SMiguel Ojeda Sandonis cfag12864b_on();
35270e84049SMiguel Ojeda Sandonis
35334173a4aSMiguel Ojeda cfag12864b_inited = 1;
35470e84049SMiguel Ojeda Sandonis return 0;
35570e84049SMiguel Ojeda Sandonis
35670e84049SMiguel Ojeda Sandonis cachealloced:
35770e84049SMiguel Ojeda Sandonis kfree(cfag12864b_cache);
35870e84049SMiguel Ojeda Sandonis
35970e84049SMiguel Ojeda Sandonis bufferalloced:
36070e84049SMiguel Ojeda Sandonis free_page((unsigned long) cfag12864b_buffer);
36170e84049SMiguel Ojeda Sandonis
36270e84049SMiguel Ojeda Sandonis none:
36370e84049SMiguel Ojeda Sandonis return ret;
36470e84049SMiguel Ojeda Sandonis }
36570e84049SMiguel Ojeda Sandonis
cfag12864b_exit(void)36670e84049SMiguel Ojeda Sandonis static void __exit cfag12864b_exit(void)
36770e84049SMiguel Ojeda Sandonis {
36870e84049SMiguel Ojeda Sandonis cfag12864b_disable();
36970e84049SMiguel Ojeda Sandonis cfag12864b_off();
37070e84049SMiguel Ojeda Sandonis destroy_workqueue(cfag12864b_workqueue);
37170e84049SMiguel Ojeda Sandonis kfree(cfag12864b_cache);
37270e84049SMiguel Ojeda Sandonis free_page((unsigned long) cfag12864b_buffer);
37370e84049SMiguel Ojeda Sandonis }
37470e84049SMiguel Ojeda Sandonis
37570e84049SMiguel Ojeda Sandonis module_init(cfag12864b_init);
37670e84049SMiguel Ojeda Sandonis module_exit(cfag12864b_exit);
37770e84049SMiguel Ojeda Sandonis
37870e84049SMiguel Ojeda Sandonis MODULE_LICENSE("GPL v2");
379c131bd0bSMiguel Ojeda MODULE_AUTHOR("Miguel Ojeda <ojeda@kernel.org>");
38070e84049SMiguel Ojeda Sandonis MODULE_DESCRIPTION("cfag12864b LCD driver");
381