diff options
-rw-r--r-- | CREDITS | 10 | ||||
-rw-r--r-- | Documentation/auxdisplay/cfag12864b | 105 | ||||
-rw-r--r-- | Documentation/auxdisplay/cfag12864b-example.c | 282 | ||||
-rw-r--r-- | Documentation/auxdisplay/ks0108 | 55 | ||||
-rw-r--r-- | MAINTAINERS | 24 | ||||
-rw-r--r-- | drivers/Kconfig | 2 | ||||
-rw-r--r-- | drivers/Makefile | 1 | ||||
-rw-r--r-- | drivers/auxdisplay/Kconfig | 109 | ||||
-rw-r--r-- | drivers/auxdisplay/Makefile | 6 | ||||
-rw-r--r-- | drivers/auxdisplay/cfag12864b.c | 383 | ||||
-rw-r--r-- | drivers/auxdisplay/cfag12864bfb.c | 180 | ||||
-rw-r--r-- | drivers/auxdisplay/ks0108.c | 166 | ||||
-rw-r--r-- | include/linux/cfag12864b.h | 77 | ||||
-rw-r--r-- | include/linux/ks0108.h | 46 |
14 files changed, 1446 insertions, 0 deletions
@@ -2571,6 +2571,16 @@ S: Subiaco, 6008 | |||
2571 | S: Perth, Western Australia | 2571 | S: Perth, Western Australia |
2572 | S: Australia | 2572 | S: Australia |
2573 | 2573 | ||
2574 | N: Miguel Ojeda Sandonis | ||
2575 | E: maxextreme@gmail.com | ||
2576 | D: Author: Auxiliary LCD Controller driver (ks0108) | ||
2577 | D: Author: Auxiliary LCD driver (cfag12864b) | ||
2578 | D: Author: Auxiliary LCD framebuffer driver (cfag12864bfb) | ||
2579 | D: Maintainer: Auxiliary display drivers tree (drivers/auxdisplay/*) | ||
2580 | S: C/ Mieses 20, 9-B | ||
2581 | S: Valladolid 47009 | ||
2582 | S: Spain | ||
2583 | |||
2574 | N: Greg Page | 2584 | N: Greg Page |
2575 | E: gpage@sovereign.org | 2585 | E: gpage@sovereign.org |
2576 | D: IPX development and support | 2586 | D: IPX development and support |
diff --git a/Documentation/auxdisplay/cfag12864b b/Documentation/auxdisplay/cfag12864b new file mode 100644 index 00000000000..3572b98f45b --- /dev/null +++ b/Documentation/auxdisplay/cfag12864b | |||
@@ -0,0 +1,105 @@ | |||
1 | =================================== | ||
2 | cfag12864b LCD Driver Documentation | ||
3 | =================================== | ||
4 | |||
5 | License: GPLv2 | ||
6 | Author & Maintainer: Miguel Ojeda Sandonis <maxextreme@gmail.com> | ||
7 | Date: 2006-10-27 | ||
8 | |||
9 | |||
10 | |||
11 | -------- | ||
12 | 0. INDEX | ||
13 | -------- | ||
14 | |||
15 | 1. DRIVER INFORMATION | ||
16 | 2. DEVICE INFORMATION | ||
17 | 3. WIRING | ||
18 | 4. USERSPACE PROGRAMMING | ||
19 | |||
20 | |||
21 | --------------------- | ||
22 | 1. DRIVER INFORMATION | ||
23 | --------------------- | ||
24 | |||
25 | This driver support one cfag12864b display at time. | ||
26 | |||
27 | |||
28 | --------------------- | ||
29 | 2. DEVICE INFORMATION | ||
30 | --------------------- | ||
31 | |||
32 | Manufacturer: Crystalfontz | ||
33 | Device Name: Crystalfontz 12864b LCD Series | ||
34 | Device Code: cfag12864b | ||
35 | Webpage: http://www.crystalfontz.com | ||
36 | Device Webpage: http://www.crystalfontz.com/products/12864b/ | ||
37 | Type: LCD (Liquid Crystal Display) | ||
38 | Width: 128 | ||
39 | Height: 64 | ||
40 | Colors: 2 (B/N) | ||
41 | Controller: ks0108 | ||
42 | Controllers: 2 | ||
43 | Pages: 8 each controller | ||
44 | Addresses: 64 each page | ||
45 | Data size: 1 byte each address | ||
46 | Memory size: 2 * 8 * 64 * 1 = 1024 bytes = 1 Kbyte | ||
47 | |||
48 | |||
49 | --------- | ||
50 | 3. WIRING | ||
51 | --------- | ||
52 | |||
53 | The cfag12864b LCD Series don't have official wiring. | ||
54 | |||
55 | The common wiring is done to the parallel port as shown: | ||
56 | |||
57 | Parallel Port cfag12864b | ||
58 | |||
59 | Name Pin# Pin# Name | ||
60 | |||
61 | Strobe ( 1)------------------------------(17) Enable | ||
62 | Data 0 ( 2)------------------------------( 4) Data 0 | ||
63 | Data 1 ( 3)------------------------------( 5) Data 1 | ||
64 | Data 2 ( 4)------------------------------( 6) Data 2 | ||
65 | Data 3 ( 5)------------------------------( 7) Data 3 | ||
66 | Data 4 ( 6)------------------------------( 8) Data 4 | ||
67 | Data 5 ( 7)------------------------------( 9) Data 5 | ||
68 | Data 6 ( 8)------------------------------(10) Data 6 | ||
69 | Data 7 ( 9)------------------------------(11) Data 7 | ||
70 | (10) [+5v]---( 1) Vdd | ||
71 | (11) [GND]---( 2) Ground | ||
72 | (12) [+5v]---(14) Reset | ||
73 | (13) [GND]---(15) Read / Write | ||
74 | Line (14)------------------------------(13) Controller Select 1 | ||
75 | (15) | ||
76 | Init (16)------------------------------(12) Controller Select 2 | ||
77 | Select (17)------------------------------(16) Data / Instruction | ||
78 | Ground (18)---[GND] [+5v]---(19) LED + | ||
79 | Ground (19)---[GND] | ||
80 | Ground (20)---[GND] E A Values: | ||
81 | Ground (21)---[GND] [GND]---[P1]---(18) Vee · R = Resistor = 22 ohm | ||
82 | Ground (22)---[GND] | · P1 = Preset = 10 Kohm | ||
83 | Ground (23)---[GND] ---- S ------( 3) V0 · P2 = Preset = 1 Kohm | ||
84 | Ground (24)---[GND] | | | ||
85 | Ground (25)---[GND] [GND]---[P2]---[R]---(20) LED - | ||
86 | |||
87 | |||
88 | ------------------------ | ||
89 | 4. USERSPACE PROGRAMMING | ||
90 | ------------------------ | ||
91 | |||
92 | The cfag12864bfb describes a framebuffer device (/dev/fbX). | ||
93 | |||
94 | It has a size of 1024 bytes = 1 Kbyte. | ||
95 | Each bit represents one pixel. If the bit is high, the pixel will | ||
96 | turn on. If the pixel is low, the pixel will turn off. | ||
97 | |||
98 | You can use the framebuffer as a file: fopen, fwrite, fclose... | ||
99 | Although the LCD won't get updated until the next refresh time arrives. | ||
100 | |||
101 | Also, you can mmap the framebuffer: open & mmap, munmap & close... | ||
102 | which is the best option for most uses. | ||
103 | |||
104 | Check Documentation/auxdisplay/cfag12864b-example.c | ||
105 | for a real working userspace complete program with usage examples. | ||
diff --git a/Documentation/auxdisplay/cfag12864b-example.c b/Documentation/auxdisplay/cfag12864b-example.c new file mode 100644 index 00000000000..7bfac354d4c --- /dev/null +++ b/Documentation/auxdisplay/cfag12864b-example.c | |||
@@ -0,0 +1,282 @@ | |||
1 | /* | ||
2 | * Filename: cfag12864b-example.c | ||
3 | * Version: 0.1.0 | ||
4 | * Description: cfag12864b LCD userspace example program | ||
5 | * License: GPLv2 | ||
6 | * | ||
7 | * Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com> | ||
8 | * Date: 2006-10-31 | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * ------------------------ | ||
27 | * start of cfag12864b code | ||
28 | * ------------------------ | ||
29 | */ | ||
30 | |||
31 | #include <string.h> | ||
32 | #include <fcntl.h> | ||
33 | #include <unistd.h> | ||
34 | #include <sys/types.h> | ||
35 | #include <sys/stat.h> | ||
36 | #include <sys/mman.h> | ||
37 | |||
38 | #define CFAG12864B_WIDTH (128) | ||
39 | #define CFAG12864B_HEIGHT (64) | ||
40 | #define CFAG12864B_SIZE (128 * 64 / 8) | ||
41 | #define CFAG12864B_BPB (8) | ||
42 | #define CFAG12864B_ADDRESS(x, y) ((y) * CFAG12864B_WIDTH / \ | ||
43 | CFAG12864B_BPB + (x) / CFAG12864B_BPB) | ||
44 | #define CFAG12864B_BIT(n) (((unsigned char) 1) << (n)) | ||
45 | |||
46 | #undef CFAG12864B_DOCHECK | ||
47 | #ifdef CFAG12864B_DOCHECK | ||
48 | #define CFAG12864B_CHECK(x, y) ((x) < CFAG12864B_WIDTH && \ | ||
49 | (y) < CFAG12864B_HEIGHT) | ||
50 | #else | ||
51 | #define CFAG12864B_CHECK(x, y) (1) | ||
52 | #endif | ||
53 | |||
54 | int cfag12864b_fd; | ||
55 | unsigned char * cfag12864b_mem; | ||
56 | unsigned char cfag12864b_buffer[CFAG12864B_SIZE]; | ||
57 | |||
58 | /* | ||
59 | * init a cfag12864b framebuffer device | ||
60 | * | ||
61 | * No error: return = 0 | ||
62 | * Unable to open: return = -1 | ||
63 | * Unable to mmap: return = -2 | ||
64 | */ | ||
65 | int cfag12864b_init(char *path) | ||
66 | { | ||
67 | cfag12864b_fd = open(path, O_RDWR); | ||
68 | if (cfag12864b_fd == -1) | ||
69 | return -1; | ||
70 | |||
71 | cfag12864b_mem = mmap(0, CFAG12864B_SIZE, PROT_READ | PROT_WRITE, | ||
72 | MAP_SHARED, cfag12864b_fd, 0); | ||
73 | if (cfag12864b_mem == MAP_FAILED) { | ||
74 | close(cfag12864b_fd); | ||
75 | return -2; | ||
76 | } | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * exit a cfag12864b framebuffer device | ||
83 | */ | ||
84 | void cfag12864b_exit(void) | ||
85 | { | ||
86 | munmap(cfag12864b_mem, CFAG12864B_SIZE); | ||
87 | close(cfag12864b_fd); | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * set (x, y) pixel | ||
92 | */ | ||
93 | void cfag12864b_set(unsigned char x, unsigned char y) | ||
94 | { | ||
95 | if (CFAG12864B_CHECK(x, y)) | ||
96 | cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] |= | ||
97 | CFAG12864B_BIT(x % CFAG12864B_BPB); | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * unset (x, y) pixel | ||
102 | */ | ||
103 | void cfag12864b_unset(unsigned char x, unsigned char y) | ||
104 | { | ||
105 | if (CFAG12864B_CHECK(x, y)) | ||
106 | cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] &= | ||
107 | ~CFAG12864B_BIT(x % CFAG12864B_BPB); | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * is set (x, y) pixel? | ||
112 | * | ||
113 | * Pixel off: return = 0 | ||
114 | * Pixel on: return = 1 | ||
115 | */ | ||
116 | unsigned char cfag12864b_isset(unsigned char x, unsigned char y) | ||
117 | { | ||
118 | if (CFAG12864B_CHECK(x, y)) | ||
119 | if (cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] & | ||
120 | CFAG12864B_BIT(x % CFAG12864B_BPB)) | ||
121 | return 1; | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * not (x, y) pixel | ||
128 | */ | ||
129 | void cfag12864b_not(unsigned char x, unsigned char y) | ||
130 | { | ||
131 | if (cfag12864b_isset(x, y)) | ||
132 | cfag12864b_unset(x, y); | ||
133 | else | ||
134 | cfag12864b_set(x, y); | ||
135 | } | ||
136 | |||
137 | /* | ||
138 | * fill (set all pixels) | ||
139 | */ | ||
140 | void cfag12864b_fill(void) | ||
141 | { | ||
142 | unsigned short i; | ||
143 | |||
144 | for (i = 0; i < CFAG12864B_SIZE; i++) | ||
145 | cfag12864b_buffer[i] = 0xFF; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * clear (unset all pixels) | ||
150 | */ | ||
151 | void cfag12864b_clear(void) | ||
152 | { | ||
153 | unsigned short i; | ||
154 | |||
155 | for (i = 0; i < CFAG12864B_SIZE; i++) | ||
156 | cfag12864b_buffer[i] = 0; | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * format a [128*64] matrix | ||
161 | * | ||
162 | * Pixel off: src[i] = 0 | ||
163 | * Pixel on: src[i] > 0 | ||
164 | */ | ||
165 | void cfag12864b_format(unsigned char * matrix) | ||
166 | { | ||
167 | unsigned char i, j, n; | ||
168 | |||
169 | for (i = 0; i < CFAG12864B_HEIGHT; i++) | ||
170 | for (j = 0; j < CFAG12864B_WIDTH / CFAG12864B_BPB; j++) { | ||
171 | cfag12864b_buffer[i * CFAG12864B_WIDTH / CFAG12864B_BPB + | ||
172 | j] = 0; | ||
173 | for (n = 0; n < CFAG12864B_BPB; n++) | ||
174 | if (matrix[i * CFAG12864B_WIDTH + | ||
175 | j * CFAG12864B_BPB + n]) | ||
176 | cfag12864b_buffer[i * CFAG12864B_WIDTH / | ||
177 | CFAG12864B_BPB + j] |= | ||
178 | CFAG12864B_BIT(n); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | /* | ||
183 | * blit buffer to lcd | ||
184 | */ | ||
185 | void cfag12864b_blit(void) | ||
186 | { | ||
187 | memcpy(cfag12864b_mem, cfag12864b_buffer, CFAG12864B_SIZE); | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * ---------------------- | ||
192 | * end of cfag12864b code | ||
193 | * ---------------------- | ||
194 | */ | ||
195 | |||
196 | #include <stdio.h> | ||
197 | #include <string.h> | ||
198 | |||
199 | #define EXAMPLES 6 | ||
200 | |||
201 | void example(unsigned char n) | ||
202 | { | ||
203 | unsigned short i, j; | ||
204 | unsigned char matrix[CFAG12864B_WIDTH * CFAG12864B_HEIGHT]; | ||
205 | |||
206 | if (n > EXAMPLES) | ||
207 | return; | ||
208 | |||
209 | printf("Example %i/%i - ", n, EXAMPLES); | ||
210 | |||
211 | switch (n) { | ||
212 | case 1: | ||
213 | printf("Draw points setting bits"); | ||
214 | cfag12864b_clear(); | ||
215 | for (i = 0; i < CFAG12864B_WIDTH; i += 2) | ||
216 | for (j = 0; j < CFAG12864B_HEIGHT; j += 2) | ||
217 | cfag12864b_set(i, j); | ||
218 | break; | ||
219 | |||
220 | case 2: | ||
221 | printf("Clear the LCD"); | ||
222 | cfag12864b_clear(); | ||
223 | break; | ||
224 | |||
225 | case 3: | ||
226 | printf("Draw rows formatting a [128*64] matrix"); | ||
227 | memset(matrix, 0, CFAG12864B_WIDTH * CFAG12864B_HEIGHT); | ||
228 | for (i = 0; i < CFAG12864B_WIDTH; i++) | ||
229 | for (j = 0; j < CFAG12864B_HEIGHT; j += 2) | ||
230 | matrix[j * CFAG12864B_WIDTH + i] = 1; | ||
231 | cfag12864b_format(matrix); | ||
232 | break; | ||
233 | |||
234 | case 4: | ||
235 | printf("Fill the lcd"); | ||
236 | cfag12864b_fill(); | ||
237 | break; | ||
238 | |||
239 | case 5: | ||
240 | printf("Draw columns unsetting bits"); | ||
241 | for (i = 0; i < CFAG12864B_WIDTH; i += 2) | ||
242 | for (j = 0; j < CFAG12864B_HEIGHT; j++) | ||
243 | cfag12864b_unset(i, j); | ||
244 | break; | ||
245 | |||
246 | case 6: | ||
247 | printf("Do negative not-ing all bits"); | ||
248 | for (i = 0; i < CFAG12864B_WIDTH; i++) | ||
249 | for (j = 0; j < CFAG12864B_HEIGHT; j ++) | ||
250 | cfag12864b_not(i, j); | ||
251 | break; | ||
252 | } | ||
253 | |||
254 | puts(" - [Press Enter]"); | ||
255 | } | ||
256 | |||
257 | int main(int argc, char *argv[]) | ||
258 | { | ||
259 | unsigned char n; | ||
260 | |||
261 | if (argc != 2) { | ||
262 | printf( | ||
263 | "Sintax: %s fbdev\n" | ||
264 | "Usually: /dev/fb0, /dev/fb1...\n", argv[0]); | ||
265 | return -1; | ||
266 | } | ||
267 | |||
268 | if (cfag12864b_init(argv[1])) { | ||
269 | printf("Can't init %s fbdev\n", argv[1]); | ||
270 | return -2; | ||
271 | } | ||
272 | |||
273 | for (n = 1; n <= EXAMPLES; n++) { | ||
274 | example(n); | ||
275 | cfag12864b_blit(); | ||
276 | while (getchar() != '\n'); | ||
277 | } | ||
278 | |||
279 | cfag12864b_exit(); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
diff --git a/Documentation/auxdisplay/ks0108 b/Documentation/auxdisplay/ks0108 new file mode 100644 index 00000000000..92b03b60c61 --- /dev/null +++ b/Documentation/auxdisplay/ks0108 | |||
@@ -0,0 +1,55 @@ | |||
1 | ========================================== | ||
2 | ks0108 LCD Controller Driver Documentation | ||
3 | ========================================== | ||
4 | |||
5 | License: GPLv2 | ||
6 | Author & Maintainer: Miguel Ojeda Sandonis <maxextreme@gmail.com> | ||
7 | Date: 2006-10-27 | ||
8 | |||
9 | |||
10 | |||
11 | -------- | ||
12 | 0. INDEX | ||
13 | -------- | ||
14 | |||
15 | 1. DRIVER INFORMATION | ||
16 | 2. DEVICE INFORMATION | ||
17 | 3. WIRING | ||
18 | |||
19 | |||
20 | --------------------- | ||
21 | 1. DRIVER INFORMATION | ||
22 | --------------------- | ||
23 | |||
24 | This driver support the ks0108 LCD controller. | ||
25 | |||
26 | |||
27 | --------------------- | ||
28 | 2. DEVICE INFORMATION | ||
29 | --------------------- | ||
30 | |||
31 | Manufacturer: Samsung | ||
32 | Device Name: KS0108 LCD Controller | ||
33 | Device Code: ks0108 | ||
34 | Webpage: - | ||
35 | Device Webpage: - | ||
36 | Type: LCD Controller (Liquid Crystal Display Controller) | ||
37 | Width: 64 | ||
38 | Height: 64 | ||
39 | Colors: 2 (B/N) | ||
40 | Pages: 8 | ||
41 | Addresses: 64 each page | ||
42 | Data size: 1 byte each address | ||
43 | Memory size: 8 * 64 * 1 = 512 bytes | ||
44 | |||
45 | |||
46 | --------- | ||
47 | 3. WIRING | ||
48 | --------- | ||
49 | |||
50 | The driver supports data parallel port wiring. | ||
51 | |||
52 | If you aren't building LCD related hardware, you should check | ||
53 | your LCD specific wiring information in the same folder. | ||
54 | |||
55 | For example, check Documentation/auxdisplay/cfag12864b. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index a6c1ebd18d0..9ea954ace2f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -635,6 +635,12 @@ W: http://people.redhat.com/sgrubb/audit/ | |||
635 | T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git | 635 | T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git |
636 | S: Maintained | 636 | S: Maintained |
637 | 637 | ||
638 | AUXILIARY DISPLAY DRIVERS | ||
639 | P: Miguel Ojeda Sandonis | ||
640 | M: maxextreme@gmail.com | ||
641 | L: linux-kernel@vger.kernel.org | ||
642 | S: Maintained | ||
643 | |||
638 | AVR32 ARCHITECTURE | 644 | AVR32 ARCHITECTURE |
639 | P: Haavard Skinnemoen | 645 | P: Haavard Skinnemoen |
640 | M: hskinnemoen@atmel.com | 646 | M: hskinnemoen@atmel.com |
@@ -836,6 +842,18 @@ L: linux-kernel@vger.kernel.org | |||
836 | L: discuss@x86-64.org | 842 | L: discuss@x86-64.org |
837 | S: Maintained | 843 | S: Maintained |
838 | 844 | ||
845 | CFAG12864B LCD DRIVER | ||
846 | P: Miguel Ojeda Sandonis | ||
847 | M: maxextreme@gmail.com | ||
848 | L: linux-kernel@vger.kernel.org | ||
849 | S: Maintained | ||
850 | |||
851 | CFAG12864BFB LCD FRAMEBUFFER DRIVER | ||
852 | P: Miguel Ojeda Sandonis | ||
853 | M: maxextreme@gmail.com | ||
854 | L: linux-kernel@vger.kernel.org | ||
855 | S: Maintained | ||
856 | |||
839 | COMMON INTERNET FILE SYSTEM (CIFS) | 857 | COMMON INTERNET FILE SYSTEM (CIFS) |
840 | P: Steve French | 858 | P: Steve French |
841 | M: sfrench@samba.org | 859 | M: sfrench@samba.org |
@@ -1971,6 +1989,12 @@ M: davem@davemloft.net | |||
1971 | L: linux-kernel@vger.kernel.org | 1989 | L: linux-kernel@vger.kernel.org |
1972 | S: Maintained | 1990 | S: Maintained |
1973 | 1991 | ||
1992 | KS0108 LCD CONTROLLER DRIVER | ||
1993 | P: Miguel Ojeda Sandonis | ||
1994 | M: maxextreme@gmail.com | ||
1995 | L: linux-kernel@vger.kernel.org | ||
1996 | S: Maintained | ||
1997 | |||
1974 | LAPB module | 1998 | LAPB module |
1975 | L: linux-x25@vger.kernel.org | 1999 | L: linux-x25@vger.kernel.org |
1976 | S: Orphan | 2000 | S: Orphan |
diff --git a/drivers/Kconfig b/drivers/Kconfig index e7da9fa724e..050323fd79e 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
@@ -80,6 +80,8 @@ source "drivers/rtc/Kconfig" | |||
80 | 80 | ||
81 | source "drivers/dma/Kconfig" | 81 | source "drivers/dma/Kconfig" |
82 | 82 | ||
83 | source "drivers/auxdisplay/Kconfig" | ||
84 | |||
83 | source "drivers/kvm/Kconfig" | 85 | source "drivers/kvm/Kconfig" |
84 | 86 | ||
85 | endmenu | 87 | endmenu |
diff --git a/drivers/Makefile b/drivers/Makefile index f28dcb4ec8b..3a718f51350 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -38,6 +38,7 @@ obj-$(CONFIG_ATA) += ata/ | |||
38 | obj-$(CONFIG_FUSION) += message/ | 38 | obj-$(CONFIG_FUSION) += message/ |
39 | obj-$(CONFIG_IEEE1394) += ieee1394/ | 39 | obj-$(CONFIG_IEEE1394) += ieee1394/ |
40 | obj-y += cdrom/ | 40 | obj-y += cdrom/ |
41 | obj-y += auxdisplay/ | ||
41 | obj-$(CONFIG_MTD) += mtd/ | 42 | obj-$(CONFIG_MTD) += mtd/ |
42 | obj-$(CONFIG_SPI) += spi/ | 43 | obj-$(CONFIG_SPI) += spi/ |
43 | obj-$(CONFIG_PCCARD) += pcmcia/ | 44 | obj-$(CONFIG_PCCARD) += pcmcia/ |
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig new file mode 100644 index 00000000000..0300e7f54cc --- /dev/null +++ b/drivers/auxdisplay/Kconfig | |||
@@ -0,0 +1,109 @@ | |||
1 | # | ||
2 | # For a description of the syntax of this configuration file, | ||
3 | # see Documentation/kbuild/kconfig-language.txt. | ||
4 | # | ||
5 | # Auxiliary display drivers configuration. | ||
6 | # | ||
7 | |||
8 | menu "Auxiliary Display support" | ||
9 | |||
10 | config KS0108 | ||
11 | tristate "KS0108 LCD Controller" | ||
12 | depends on PARPORT_PC | ||
13 | default n | ||
14 | ---help--- | ||
15 | If you have a LCD controlled by one or more KS0108 | ||
16 | controllers, say Y. You will need also another more specific | ||
17 | driver for your LCD. | ||
18 | |||
19 | Depends on Parallel Port support. If you say Y at | ||
20 | parport, you will be able to compile this as a module (M) | ||
21 | and built-in as well (Y). | ||
22 | |||
23 | To compile this as a module, choose M here: | ||
24 | the module will be called ks0108. | ||
25 | |||
26 | If unsure, say N. | ||
27 | |||
28 | config KS0108_PORT | ||
29 | hex "Parallel port where the LCD is connected" | ||
30 | depends on KS0108 | ||
31 | default 0x378 | ||
32 | ---help--- | ||
33 | The address of the parallel port where the LCD is connected. | ||
34 | |||
35 | The first standard parallel port address is 0x378. | ||
36 | The second standard parallel port address is 0x278. | ||
37 | The third standard parallel port address is 0x3BC. | ||
38 | |||
39 | You can specify a different address if you need. | ||
40 | |||
41 | If you don't know what I'm talking about, load the parport module, | ||
42 | and execute "dmesg" or "cat /proc/ioports". You can see there how | ||
43 | many parallel ports are present and which address each one has. | ||
44 | |||
45 | Usually you only need to use 0x378. | ||
46 | |||
47 | If you compile this as a module, you can still override this | ||
48 | using the module parameters. | ||
49 | |||
50 | config KS0108_DELAY | ||
51 | int "Delay between each control writing (microseconds)" | ||
52 | depends on KS0108 | ||
53 | default "2" | ||
54 | ---help--- | ||
55 | Amount of time the ks0108 should wait between each control write | ||
56 | to the parallel port. | ||
57 | |||
58 | If your driver seems to miss random writings, increment this. | ||
59 | |||
60 | If you don't know what I'm talking about, ignore it. | ||
61 | |||
62 | If you compile this as a module, you can still override this | ||
63 | value using the module parameters. | ||
64 | |||
65 | config CFAG12864B | ||
66 | tristate "CFAG12864B LCD" | ||
67 | depends on X86 | ||
68 | depends on FB | ||
69 | depends on KS0108 | ||
70 | default n | ||
71 | ---help--- | ||
72 | If you have a Crystalfontz 128x64 2-color LCD, cfag12864b Series, | ||
73 | say Y. You also need the ks0108 LCD Controller driver. | ||
74 | |||
75 | For help about how to wire your LCD to the parallel port, | ||
76 | check Documentation/auxdisplay/cfag12864b | ||
77 | |||
78 | Depends on the x86 arch and the framebuffer support. | ||
79 | |||
80 | The LCD framebuffer driver can be attached to a console. | ||
81 | It will work fine. However, you can't attach it to the fbdev driver | ||
82 | of the xorg server. | ||
83 | |||
84 | To compile this as a module, choose M here: | ||
85 | the modules will be called cfag12864b and cfag12864bfb. | ||
86 | |||
87 | If unsure, say N. | ||
88 | |||
89 | config CFAG12864B_RATE | ||
90 | int "Refresh rate (hertz)" | ||
91 | depends on CFAG12864B | ||
92 | default "20" | ||
93 | ---help--- | ||
94 | Refresh rate of the LCD. | ||
95 | |||
96 | As the LCD is not memory mapped, the driver has to make the work by | ||
97 | software. This means you should be careful setting this value higher. | ||
98 | If your CPUs are really slow or you feel the system is slowed down, | ||
99 | decrease the value. | ||
100 | |||
101 | Be careful modifying this value to a very high value: | ||
102 | You can freeze the computer, or the LCD maybe can't draw as fast as you | ||
103 | are requesting. | ||
104 | |||
105 | If you don't know what I'm talking about, ignore it. | ||
106 | |||
107 | If you compile this as a module, you can still override this | ||
108 | value using the module parameters. | ||
109 | endmenu | ||
diff --git a/drivers/auxdisplay/Makefile b/drivers/auxdisplay/Makefile new file mode 100644 index 00000000000..8a8936a468b --- /dev/null +++ b/drivers/auxdisplay/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for the kernel auxiliary displays device drivers. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_KS0108) += ks0108.o | ||
6 | obj-$(CONFIG_CFAG12864B) += cfag12864b.o cfag12864bfb.o | ||
diff --git a/drivers/auxdisplay/cfag12864b.c b/drivers/auxdisplay/cfag12864b.c new file mode 100644 index 00000000000..889583dfc1a --- /dev/null +++ b/drivers/auxdisplay/cfag12864b.c | |||
@@ -0,0 +1,383 @@ | |||
1 | /* | ||
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 | * Module Init & Exit | ||
316 | */ | ||
317 | |||
318 | static int __init cfag12864b_init(void) | ||
319 | { | ||
320 | int ret = -EINVAL; | ||
321 | |||
322 | if (PAGE_SIZE < CFAG12864B_SIZE) { | ||
323 | printk(KERN_ERR CFAG12864B_NAME ": ERROR: " | ||
324 | "page size (%i) < cfag12864b size (%i)\n", | ||
325 | (unsigned int)PAGE_SIZE, CFAG12864B_SIZE); | ||
326 | ret = -ENOMEM; | ||
327 | goto none; | ||
328 | } | ||
329 | |||
330 | cfag12864b_buffer = (unsigned char *) __get_free_page(GFP_KERNEL); | ||
331 | if (cfag12864b_buffer == NULL) { | ||
332 | printk(KERN_ERR CFAG12864B_NAME ": ERROR: " | ||
333 | "can't get a free page\n"); | ||
334 | ret = -ENOMEM; | ||
335 | goto none; | ||
336 | } | ||
337 | |||
338 | cfag12864b_cache = kmalloc(sizeof(unsigned char) * | ||
339 | CFAG12864B_SIZE, GFP_KERNEL); | ||
340 | if (cfag12864b_buffer == NULL) { | ||
341 | printk(KERN_ERR CFAG12864B_NAME ": ERROR: " | ||
342 | "can't alloc cache buffer (%i bytes)\n", | ||
343 | CFAG12864B_SIZE); | ||
344 | ret = -ENOMEM; | ||
345 | goto bufferalloced; | ||
346 | } | ||
347 | |||
348 | cfag12864b_workqueue = create_singlethread_workqueue(CFAG12864B_NAME); | ||
349 | if (cfag12864b_workqueue == NULL) | ||
350 | goto cachealloced; | ||
351 | |||
352 | memset(cfag12864b_buffer, 0, CFAG12864B_SIZE); | ||
353 | |||
354 | cfag12864b_clear(); | ||
355 | cfag12864b_on(); | ||
356 | |||
357 | return 0; | ||
358 | |||
359 | cachealloced: | ||
360 | kfree(cfag12864b_cache); | ||
361 | |||
362 | bufferalloced: | ||
363 | free_page((unsigned long) cfag12864b_buffer); | ||
364 | |||
365 | none: | ||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | static void __exit cfag12864b_exit(void) | ||
370 | { | ||
371 | cfag12864b_disable(); | ||
372 | cfag12864b_off(); | ||
373 | destroy_workqueue(cfag12864b_workqueue); | ||
374 | kfree(cfag12864b_cache); | ||
375 | free_page((unsigned long) cfag12864b_buffer); | ||
376 | } | ||
377 | |||
378 | module_init(cfag12864b_init); | ||
379 | module_exit(cfag12864b_exit); | ||
380 | |||
381 | MODULE_LICENSE("GPL v2"); | ||
382 | MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>"); | ||
383 | MODULE_DESCRIPTION("cfag12864b LCD driver"); | ||
diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c new file mode 100644 index 00000000000..94765e78315 --- /dev/null +++ b/drivers/auxdisplay/cfag12864bfb.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * Filename: cfag12864bfb.c | ||
3 | * Version: 0.1.0 | ||
4 | * Description: cfag12864b LCD framebuffer driver | ||
5 | * License: GPLv2 | ||
6 | * Depends: cfag12864b | ||
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/delay.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <linux/fb.h> | ||
32 | #include <linux/mm.h> | ||
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/string.h> | ||
36 | #include <linux/uaccess.h> | ||
37 | #include <linux/cfag12864b.h> | ||
38 | |||
39 | #define CFAG12864BFB_NAME "cfag12864bfb" | ||
40 | |||
41 | static struct fb_fix_screeninfo cfag12864bfb_fix __initdata = { | ||
42 | .id = "cfag12864b", | ||
43 | .type = FB_TYPE_PACKED_PIXELS, | ||
44 | .visual = FB_VISUAL_MONO10, | ||
45 | .xpanstep = 0, | ||
46 | .ypanstep = 0, | ||
47 | .ywrapstep = 0, | ||
48 | .line_length = CFAG12864B_WIDTH / 8, | ||
49 | .accel = FB_ACCEL_NONE, | ||
50 | }; | ||
51 | |||
52 | static struct fb_var_screeninfo cfag12864bfb_var __initdata = { | ||
53 | .xres = CFAG12864B_WIDTH, | ||
54 | .yres = CFAG12864B_HEIGHT, | ||
55 | .xres_virtual = CFAG12864B_WIDTH, | ||
56 | .yres_virtual = CFAG12864B_HEIGHT, | ||
57 | .bits_per_pixel = 1, | ||
58 | .red = { 0, 1, 0 }, | ||
59 | .green = { 0, 1, 0 }, | ||
60 | .blue = { 0, 1, 0 }, | ||
61 | .left_margin = 0, | ||
62 | .right_margin = 0, | ||
63 | .upper_margin = 0, | ||
64 | .lower_margin = 0, | ||
65 | .vmode = FB_VMODE_NONINTERLACED, | ||
66 | }; | ||
67 | |||
68 | static int cfag12864bfb_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||
69 | { | ||
70 | return vm_insert_page(vma, vma->vm_start, | ||
71 | virt_to_page(cfag12864b_buffer)); | ||
72 | } | ||
73 | |||
74 | static struct fb_ops cfag12864bfb_ops = { | ||
75 | .owner = THIS_MODULE, | ||
76 | .fb_fillrect = cfb_fillrect, | ||
77 | .fb_copyarea = cfb_copyarea, | ||
78 | .fb_imageblit = cfb_imageblit, | ||
79 | .fb_mmap = cfag12864bfb_mmap, | ||
80 | }; | ||
81 | |||
82 | static int __init cfag12864bfb_probe(struct platform_device *device) | ||
83 | { | ||
84 | int ret = -EINVAL; | ||
85 | struct fb_info *info = framebuffer_alloc(0, &device->dev); | ||
86 | |||
87 | if (!info) | ||
88 | goto none; | ||
89 | |||
90 | info->screen_base = (char __iomem *) cfag12864b_buffer; | ||
91 | info->screen_size = CFAG12864B_SIZE; | ||
92 | info->fbops = &cfag12864bfb_ops; | ||
93 | info->fix = cfag12864bfb_fix; | ||
94 | info->var = cfag12864bfb_var; | ||
95 | info->pseudo_palette = NULL; | ||
96 | info->par = NULL; | ||
97 | info->flags = FBINFO_FLAG_DEFAULT; | ||
98 | |||
99 | if (register_framebuffer(info) < 0) | ||
100 | goto fballoced; | ||
101 | |||
102 | platform_set_drvdata(device, info); | ||
103 | |||
104 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, | ||
105 | info->fix.id); | ||
106 | |||
107 | return 0; | ||
108 | |||
109 | fballoced: | ||
110 | framebuffer_release(info); | ||
111 | |||
112 | none: | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | static int cfag12864bfb_remove(struct platform_device *device) | ||
117 | { | ||
118 | struct fb_info *info = platform_get_drvdata(device); | ||
119 | |||
120 | if (info) { | ||
121 | unregister_framebuffer(info); | ||
122 | framebuffer_release(info); | ||
123 | } | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static struct platform_driver cfag12864bfb_driver = { | ||
129 | .probe = cfag12864bfb_probe, | ||
130 | .remove = cfag12864bfb_remove, | ||
131 | .driver = { | ||
132 | .name = CFAG12864BFB_NAME, | ||
133 | }, | ||
134 | }; | ||
135 | |||
136 | static struct platform_device *cfag12864bfb_device; | ||
137 | |||
138 | static int __init cfag12864bfb_init(void) | ||
139 | { | ||
140 | int ret; | ||
141 | |||
142 | if (cfag12864b_enable()) { | ||
143 | printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: " | ||
144 | "can't enable cfag12864b refreshing (being used)\n"); | ||
145 | return -ENODEV; | ||
146 | } | ||
147 | |||
148 | ret = platform_driver_register(&cfag12864bfb_driver); | ||
149 | |||
150 | if (!ret) { | ||
151 | cfag12864bfb_device = | ||
152 | platform_device_alloc(CFAG12864BFB_NAME, 0); | ||
153 | |||
154 | if (cfag12864bfb_device) | ||
155 | ret = platform_device_add(cfag12864bfb_device); | ||
156 | else | ||
157 | ret = -ENOMEM; | ||
158 | |||
159 | if (ret) { | ||
160 | platform_device_put(cfag12864bfb_device); | ||
161 | platform_driver_unregister(&cfag12864bfb_driver); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | static void __exit cfag12864bfb_exit(void) | ||
169 | { | ||
170 | platform_device_unregister(cfag12864bfb_device); | ||
171 | platform_driver_unregister(&cfag12864bfb_driver); | ||
172 | cfag12864b_disable(); | ||
173 | } | ||
174 | |||
175 | module_init(cfag12864bfb_init); | ||
176 | module_exit(cfag12864bfb_exit); | ||
177 | |||
178 | MODULE_LICENSE("GPL v2"); | ||
179 | MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>"); | ||
180 | MODULE_DESCRIPTION("cfag12864b LCD framebuffer driver"); | ||
diff --git a/drivers/auxdisplay/ks0108.c b/drivers/auxdisplay/ks0108.c new file mode 100644 index 00000000000..a637575b910 --- /dev/null +++ b/drivers/auxdisplay/ks0108.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /* | ||
2 | * Filename: ks0108.c | ||
3 | * Version: 0.1.0 | ||
4 | * Description: ks0108 LCD Controller driver | ||
5 | * License: GPLv2 | ||
6 | * Depends: parport | ||
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/delay.h> | ||
30 | #include <linux/fs.h> | ||
31 | #include <linux/io.h> | ||
32 | #include <linux/parport.h> | ||
33 | #include <linux/uaccess.h> | ||
34 | #include <linux/ks0108.h> | ||
35 | |||
36 | #define KS0108_NAME "ks0108" | ||
37 | |||
38 | /* | ||
39 | * Module Parameters | ||
40 | */ | ||
41 | |||
42 | static unsigned int ks0108_port = CONFIG_KS0108_PORT; | ||
43 | module_param(ks0108_port, uint, S_IRUGO); | ||
44 | MODULE_PARM_DESC(ks0108_port, "Parallel port where the LCD is connected"); | ||
45 | |||
46 | static unsigned int ks0108_delay = CONFIG_KS0108_DELAY; | ||
47 | module_param(ks0108_delay, uint, S_IRUGO); | ||
48 | MODULE_PARM_DESC(ks0108_delay, "Delay between each control writing (microseconds)"); | ||
49 | |||
50 | /* | ||
51 | * Device | ||
52 | */ | ||
53 | |||
54 | static struct parport *ks0108_parport; | ||
55 | static struct pardevice *ks0108_pardevice; | ||
56 | |||
57 | /* | ||
58 | * ks0108 Exported Commands (don't lock) | ||
59 | * | ||
60 | * You _should_ lock in the top driver: This functions _should not_ | ||
61 | * get race conditions in any way. Locking for each byte here would be | ||
62 | * so slow and useless. | ||
63 | * | ||
64 | * There are not bit definitions because they are not flags, | ||
65 | * just arbitrary combinations defined by the documentation for each | ||
66 | * function in the ks0108 LCD controller. If you want to know what means | ||
67 | * a specific combination, look at the function's name. | ||
68 | * | ||
69 | * The ks0108_writecontrol bits need to be reverted ^(0,1,3) because | ||
70 | * the parallel port also revert them using a "not" logic gate. | ||
71 | */ | ||
72 | |||
73 | #define bit(n) (((unsigned char)1)<<(n)) | ||
74 | |||
75 | void ks0108_writedata(unsigned char byte) | ||
76 | { | ||
77 | parport_write_data(ks0108_parport, byte); | ||
78 | } | ||
79 | |||
80 | void ks0108_writecontrol(unsigned char byte) | ||
81 | { | ||
82 | udelay(ks0108_delay); | ||
83 | parport_write_control(ks0108_parport, byte ^ (bit(0) | bit(1) | bit(3))); | ||
84 | } | ||
85 | |||
86 | void ks0108_displaystate(unsigned char state) | ||
87 | { | ||
88 | ks0108_writedata((state ? bit(0) : 0) | bit(1) | bit(2) | bit(3) | bit(4) | bit(5)); | ||
89 | } | ||
90 | |||
91 | void ks0108_startline(unsigned char startline) | ||
92 | { | ||
93 | ks0108_writedata(min(startline,(unsigned char)63) | bit(6) | bit(7)); | ||
94 | } | ||
95 | |||
96 | void ks0108_address(unsigned char address) | ||
97 | { | ||
98 | ks0108_writedata(min(address,(unsigned char)63) | bit(6)); | ||
99 | } | ||
100 | |||
101 | void ks0108_page(unsigned char page) | ||
102 | { | ||
103 | ks0108_writedata(min(page,(unsigned char)7) | bit(3) | bit(4) | bit(5) | bit(7)); | ||
104 | } | ||
105 | |||
106 | EXPORT_SYMBOL_GPL(ks0108_writedata); | ||
107 | EXPORT_SYMBOL_GPL(ks0108_writecontrol); | ||
108 | EXPORT_SYMBOL_GPL(ks0108_displaystate); | ||
109 | EXPORT_SYMBOL_GPL(ks0108_startline); | ||
110 | EXPORT_SYMBOL_GPL(ks0108_address); | ||
111 | EXPORT_SYMBOL_GPL(ks0108_page); | ||
112 | |||
113 | /* | ||
114 | * Module Init & Exit | ||
115 | */ | ||
116 | |||
117 | static int __init ks0108_init(void) | ||
118 | { | ||
119 | int result; | ||
120 | int ret = -EINVAL; | ||
121 | |||
122 | ks0108_parport = parport_find_base(ks0108_port); | ||
123 | if (ks0108_parport == NULL) { | ||
124 | printk(KERN_ERR KS0108_NAME ": ERROR: " | ||
125 | "parport didn't find %i port\n", ks0108_port); | ||
126 | goto none; | ||
127 | } | ||
128 | |||
129 | ks0108_pardevice = parport_register_device(ks0108_parport, KS0108_NAME, | ||
130 | NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); | ||
131 | if (ks0108_pardevice == NULL) { | ||
132 | printk(KERN_ERR KS0108_NAME ": ERROR: " | ||
133 | "parport didn't register new device\n"); | ||
134 | goto none; | ||
135 | } | ||
136 | |||
137 | result = parport_claim(ks0108_pardevice); | ||
138 | if (result != 0) { | ||
139 | printk(KERN_ERR KS0108_NAME ": ERROR: " | ||
140 | "can't claim %i parport, maybe in use\n", ks0108_port); | ||
141 | ret = result; | ||
142 | goto registered; | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | |||
147 | registered: | ||
148 | parport_unregister_device(ks0108_pardevice); | ||
149 | |||
150 | none: | ||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | static void __exit ks0108_exit(void) | ||
155 | { | ||
156 | parport_release(ks0108_pardevice); | ||
157 | parport_unregister_device(ks0108_pardevice); | ||
158 | } | ||
159 | |||
160 | module_init(ks0108_init); | ||
161 | module_exit(ks0108_exit); | ||
162 | |||
163 | MODULE_LICENSE("GPL v2"); | ||
164 | MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>"); | ||
165 | MODULE_DESCRIPTION("ks0108 LCD Controller driver"); | ||
166 | |||
diff --git a/include/linux/cfag12864b.h b/include/linux/cfag12864b.h new file mode 100644 index 00000000000..0bc45e69da5 --- /dev/null +++ b/include/linux/cfag12864b.h | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * Filename: cfag12864b.h | ||
3 | * Version: 0.1.0 | ||
4 | * Description: cfag12864b LCD driver header | ||
5 | * License: GPLv2 | ||
6 | * | ||
7 | * Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com> | ||
8 | * Date: 2006-10-12 | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef _CFAG12864B_H_ | ||
26 | #define _CFAG12864B_H_ | ||
27 | |||
28 | #define CFAG12864B_WIDTH (128) | ||
29 | #define CFAG12864B_HEIGHT (64) | ||
30 | #define CFAG12864B_CONTROLLERS (2) | ||
31 | #define CFAG12864B_PAGES (8) | ||
32 | #define CFAG12864B_ADDRESSES (64) | ||
33 | #define CFAG12864B_SIZE ((CFAG12864B_CONTROLLERS) * \ | ||
34 | (CFAG12864B_PAGES) * \ | ||
35 | (CFAG12864B_ADDRESSES)) | ||
36 | |||
37 | /* | ||
38 | * The driver will blit this buffer to the LCD | ||
39 | * | ||
40 | * Its size is CFAG12864B_SIZE. | ||
41 | */ | ||
42 | extern unsigned char * cfag12864b_buffer; | ||
43 | |||
44 | /* | ||
45 | * Get the refresh rate of the LCD | ||
46 | * | ||
47 | * Returns the refresh rate (hertzs). | ||
48 | */ | ||
49 | extern unsigned int cfag12864b_getrate(void); | ||
50 | |||
51 | /* | ||
52 | * Enable refreshing | ||
53 | * | ||
54 | * Returns 0 if successful (anyone was using it), | ||
55 | * or != 0 if failed (someone is using it). | ||
56 | */ | ||
57 | extern unsigned char cfag12864b_enable(void); | ||
58 | |||
59 | /* | ||
60 | * Disable refreshing | ||
61 | * | ||
62 | * You should call this only when you finish using the LCD. | ||
63 | */ | ||
64 | extern void cfag12864b_disable(void); | ||
65 | |||
66 | /* | ||
67 | * Is enabled refreshing? (is anyone using the module?) | ||
68 | * | ||
69 | * Returns 0 if refreshing is not enabled (anyone is using it), | ||
70 | * or != 0 if refreshing is enabled (someone is using it). | ||
71 | * | ||
72 | * Useful for buffer read-only modules. | ||
73 | */ | ||
74 | extern unsigned char cfag12864b_isenabled(void); | ||
75 | |||
76 | #endif /* _CFAG12864B_H_ */ | ||
77 | |||
diff --git a/include/linux/ks0108.h b/include/linux/ks0108.h new file mode 100644 index 00000000000..8047d4b17bf --- /dev/null +++ b/include/linux/ks0108.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * Filename: ks0108.h | ||
3 | * Version: 0.1.0 | ||
4 | * Description: ks0108 LCD Controller driver header | ||
5 | * License: GPLv2 | ||
6 | * | ||
7 | * Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com> | ||
8 | * Date: 2006-10-31 | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef _KS0108_H_ | ||
26 | #define _KS0108_H_ | ||
27 | |||
28 | /* Write a byte to the data port */ | ||
29 | extern void ks0108_writedata(unsigned char byte); | ||
30 | |||
31 | /* Write a byte to the control port */ | ||
32 | extern void ks0108_writecontrol(unsigned char byte); | ||
33 | |||
34 | /* Set the controller's current display state (0..1) */ | ||
35 | extern void ks0108_displaystate(unsigned char state); | ||
36 | |||
37 | /* Set the controller's current startline (0..63) */ | ||
38 | extern void ks0108_startline(unsigned char startline); | ||
39 | |||
40 | /* Set the controller's current address (0..63) */ | ||
41 | extern void ks0108_address(unsigned char address); | ||
42 | |||
43 | /* Set the controller's current page (0..7) */ | ||
44 | extern void ks0108_page(unsigned char page); | ||
45 | |||
46 | #endif /* _KS0108_H_ */ | ||