summaryrefslogtreecommitdiff
path: root/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2008-11-01 10:29:23 +0000
committerDave Chapman <dave@dchapman.com>2008-11-01 10:29:23 +0000
commit74c75e5c047c772a5539554156f079d2a003fe4a (patch)
tree356c73c00c985c534864a4c9a6e8d3414b2a30fd /firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
parent88806c0b1b3900b2cdcd8c28901bece2b05d4610 (diff)
downloadrockbox-74c75e5c047c772a5539554156f079d2a003fe4a.tar.gz
rockbox-74c75e5c047c772a5539554156f079d2a003fe4a.zip
Add Sansa Fuze to the build system, including a first (untested) attempt at an LCD driver. Lots of things are just copied from the e200v2, so this code needs testing, and then drivers properly merged if they prove to be the same.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18957 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c')
-rw-r--r--firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c449
1 files changed, 449 insertions, 0 deletions
diff --git a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
new file mode 100644
index 0000000000..ff62949dcd
--- /dev/null
+++ b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
@@ -0,0 +1,449 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Dave Chapman
11 *
12 * LCD driver for the Sansa Fuze - controller unknown
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "config.h"
24
25#include "cpu.h"
26#include "lcd.h"
27
28static bool display_on = false; /* is the display turned on? */
29static bool display_flipped = false;
30static int xoffset = 20; /* needed for flip */
31
32/* TODO: Implement this function */
33static void lcd_delay(int x)
34{
35 /* This is just arbitrary - the OF does something more complex */
36 x *= 1024;
37 while (x--);
38}
39
40static void as3525_dbop_init(void)
41{
42 CGU_DBOP = (1<<3) | (4-1);
43
44 DBOP_TIMPOL_01 = 0xe167e167;
45 DBOP_TIMPOL_23 = 0xe167006e;
46 DBOP_CTRL = 0x41008;
47
48 GPIOB_AFSEL = 0xfc;
49 GPIOC_AFSEL = 0xff;
50
51 DBOP_TIMPOL_23 = 0x6000e;
52 DBOP_CTRL = 0x51008;
53 DBOP_TIMPOL_01 = 0x6e167;
54 DBOP_TIMPOL_23 = 0xa167e06f;
55
56 /* TODO: The OF calls some other functions here, but maybe not important */
57}
58
59static void lcd_write_cmd(int cmd)
60{
61 int x;
62
63 /* Write register */
64 DBOP_CTRL &= ~(1<<14);
65
66 DBOP_TIMPOL_23 = 0xa167006e;
67
68 DBOP_DOUT = cmd;
69
70 /* Wait for fifo to empty */
71 while ((DBOP_STAT & (1<<10)) == 0);
72
73 /* This loop is unique to the Fuze */
74 x = 0;
75 do {
76 asm volatile ("nop\n");
77 } while (x++ < 4);
78
79
80 DBOP_TIMPOL_23 = 0xa167e06f;
81}
82
83void lcd_write_data(const fb_data* p_bytes, int count)
84{
85 while (count--)
86 {
87 DBOP_DOUT = *p_bytes++;
88
89 /* Wait for fifo to empty */
90 while ((DBOP_STAT & (1<<10)) == 0);
91 }
92}
93
94static void lcd_write_reg(int reg, int value)
95{
96 unsigned short data = value;
97
98 lcd_write_cmd(reg);
99 lcd_write_data(&data, 1);
100}
101
102/*** hardware configuration ***/
103
104void lcd_set_contrast(int val)
105{
106 (void)val;
107}
108
109void lcd_set_invert_display(bool yesno)
110{
111 (void)yesno;
112}
113
114static void flip_lcd(bool yesno)
115{
116 (void)yesno;
117}
118
119
120/* turn the display upside down (call lcd_update() afterwards) */
121void lcd_set_flip(bool yesno)
122{
123 display_flipped = yesno;
124 xoffset = yesno ? 20 : 0; /* A guess */
125
126 if (display_on)
127 flip_lcd(yesno);
128}
129
130
131static void _display_on(void)
132{
133 /* Initialise in the same way as the original firmare */
134
135 lcd_write_reg(0x07, 0);
136 lcd_write_reg(0x13, 0);
137
138 lcd_delay(10);
139
140 lcd_write_reg(0x11, 0x3704);
141 lcd_write_reg(0x14, 0x1a1b);
142 lcd_write_reg(0x10, 0x3860);
143 lcd_write_reg(0x13, 0x40);
144
145 lcd_delay(10);
146
147 lcd_write_reg(0x13, 0x60);
148
149 lcd_delay(50);
150
151 lcd_write_reg(0x13, 0x70);
152
153 lcd_delay(40);
154
155 lcd_write_reg(0x01, 277);
156 lcd_write_reg(0x02, (7<<8));
157 lcd_write_reg(0x03, 0x30);
158 lcd_write_reg(0x08, 0x01);
159 lcd_write_reg(0x0b, (1<<10));
160 lcd_write_reg(0x0c, 0);
161
162 lcd_write_reg(0x30, 0x40);
163 lcd_write_reg(0x31, 0x0687);
164 lcd_write_reg(0x32, 0x0306);
165 lcd_write_reg(0x33, 0x104);
166 lcd_write_reg(0x34, 0x0585);
167 lcd_write_reg(0x35, 255+66);
168 lcd_write_reg(0x36, 0x0687+128);
169 lcd_write_reg(0x37, 259);
170 lcd_write_reg(0x38, 0);
171 lcd_write_reg(0x39, 0);
172
173 lcd_write_reg(0x42, (LCD_WIDTH - 1));
174 lcd_write_reg(0x43, 0);
175 lcd_write_reg(0x44, (LCD_WIDTH - 1));
176 lcd_write_reg(0x45, 0);
177 lcd_write_reg(0x46, (((LCD_WIDTH - 1) + xoffset) << 8) | xoffset);
178 lcd_write_reg(0x47, (LCD_HEIGHT - 1));
179 lcd_write_reg(0x48, 0x0);
180
181 lcd_write_reg(0x07, 0x11);
182
183 lcd_delay(40);
184
185 lcd_write_reg(0x07, 0x17);
186
187 display_on = true; /* must be done before calling lcd_update() */
188 lcd_update();
189}
190
191/* (e.g. 0, 219) */
192static void lcd_window_x(int r0, int r1)
193{
194 int r2, r3, r4;
195
196 r3 = (LCD_WIDTH - 1);
197 r2 = (LCD_WIDTH - 1);
198
199 if (r0 < LCD_WIDTH)
200 r2 = r0;
201
202 if (r1 < LCD_WIDTH)
203 r3 = r1;
204
205#if 0
206 r1 = 0x1db12;
207
208 [r1] = 1; /* byte */
209#endif
210
211 r3 += xoffset;
212
213 r4 = r2;
214
215 r4 += xoffset;
216
217 r0 = (r3 << 8);
218
219 r0 |= r4;
220
221 r1 = (r0 << 16) >> 16;
222
223 lcd_write_reg(0x46, r1);
224
225 r1 = (r4 << 16) >> 16;
226
227 lcd_write_reg(0x20, r1);
228
229 lcd_write_reg(0x03, 0x30);
230
231#if 0
232 r0 := 0x1e0c4
233 r1 := 0x216a8
234
235 r0 := [r0]
236 r2 := [r1]
237
238 r0 := (r0 >> 2) << 2;
239
240 if (r0 != r2) {
241#endif
242 lcd_write_reg(0x00, 0x0001);
243 lcd_write_reg(0x11, 0x3704);
244 lcd_write_reg(0x14, 0x1a1b);
245 lcd_write_reg(0x10, 0x3860);
246 lcd_write_reg(0x13, 0x0070);
247 lcd_write_reg(0x07, 0x0017);
248 lcd_write_reg(0x01, 277);
249 lcd_write_reg(0x02, (7<<8));
250 lcd_write_reg(0x08, 0x0001);
251 lcd_write_reg(0x0b, (1<<10));
252 lcd_write_reg(0x0c, 0x0000);
253 lcd_write_reg(0x30, 0x0040);
254 lcd_write_reg(0x31, 0x0687);
255 lcd_write_reg(0x32, 0x0306);
256 lcd_write_reg(0x33, 260);
257 lcd_write_reg(0x34, 0x0585);
258 lcd_write_reg(0x35, 255+66);
259 lcd_write_reg(0x36, 0x687+128);
260 lcd_write_reg(0x37, 259);
261 lcd_write_reg(0x38, 0);
262 lcd_write_reg(0x39, 0);
263 lcd_write_reg(0x40, 0);
264 lcd_write_reg(0x41, 0);
265 lcd_write_reg(0x42, (LCD_WIDTH - 1));
266 lcd_write_reg(0x43, 0);
267 lcd_write_reg(0x44, (LCD_WIDTH - 1));
268 lcd_write_reg(0x45, 0);
269 lcd_write_reg(0x15, 0);
270 lcd_write_reg(0x73, 0);
271#if 0
272 }
273#endif
274}
275
276/* - e.g. 0, 175 */
277static void lcd_window_y(int r0, int r1)
278{
279 int r2, r4;
280
281 r2 = (LCD_HEIGHT - 1);
282 r4 = (LCD_HEIGHT - 1);
283
284 if (r0 < LCD_HEIGHT)
285 r4 = r0;
286
287 if (r1 < LCD_HEIGHT)
288 r2 = r1;
289
290 r1 = (r2 << 16) >> 16;
291
292 lcd_write_reg(0x47, r1);
293
294 r1 = (r4 << 16) >> 16;
295
296 lcd_write_reg(0x48, r1);
297
298 /* ??Start address - (x<<8) | y0 */
299 lcd_write_reg(0x21, r1);
300
301 /* Start write to GRAM */
302 lcd_write_cmd(0x22);
303}
304
305/* I'm guessing this function is lcd_enable, but it may not be... */
306void lcd_enable(int r0)
307{
308#if 0
309 r4 = 0x1db12;
310 [r4] = 1;
311#endif
312
313 if (r0 != 0) {
314 lcd_write_reg(0, 1);
315
316 lcd_delay(10);
317
318 lcd_write_reg(0x10, 0);
319 lcd_write_reg(0x11, 0x3704);
320 lcd_write_reg(0x14, 0x1a1b);
321 lcd_write_reg(0x10, 0x3860);
322 lcd_write_reg(0x13, 0x40);
323
324 lcd_delay(10);
325
326 lcd_write_reg(0x13, 0x60);
327
328 lcd_delay(50);
329
330 lcd_write_reg(0x13, 112);
331
332 lcd_delay(40);
333
334 lcd_write_reg(0x07, 0x11);
335
336 lcd_delay(40);
337
338 lcd_write_reg(0x07, 0x17);
339 } else {
340 lcd_write_reg(0x07, 0x22);
341
342 lcd_delay(40);
343
344 lcd_write_reg(0x07, 0);
345
346 lcd_delay(40);
347
348 lcd_write_reg(0x10, 1);
349 }
350
351#if 0
352 [r4] = 0;
353#endif
354}
355
356void lcd_init_device()
357{
358 as3525_dbop_init();
359
360 GPIOA_DIR |= (1<<5);
361 GPIOA_PIN(5) = 0;
362
363 GPIOA_PIN(3) = (1<<3);
364
365 GPIOA_DIR |= (1<<4) | (1<<3);
366
367 GPIOA_PIN(3) = (1<<3);
368
369 GPIOA_PIN(4) = 0;
370
371 GPIOA_DIR |= (1<<7);
372 GPIOA_PIN(7) = 0;
373
374 CCU_IO &= ~4;
375 CCU_IO &= ~8;
376
377 GPIOD_DIR |= (1<<7);
378
379#if 0
380 if (byte[0x21b24] == 0) {
381 GPIOD_PIN(7) = (1<<7);
382 GPIOD_DIR |= (1<<7);
383 }
384#endif
385
386 lcd_delay(1);
387
388 GPIOA_PIN(5) = (1<<5);
389
390 lcd_delay(1);
391
392 _display_on();
393}
394
395/* Update the display.
396 This must be called after all other LCD functions that change the display. */
397void lcd_update(void)
398{
399 if (!display_on)
400 return;
401
402 lcd_window_x(0, (LCD_WIDTH - 1));
403
404 lcd_window_y(0, (LCD_HEIGHT - 1));
405
406 lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT);
407
408}
409
410/* Update a fraction of the display. */
411void lcd_update_rect(int x, int y, int width, int height)
412{
413 int xmax, ymax;
414 const unsigned short *ptr;
415
416 if (!display_on)
417 return;
418
419 xmax = x + width - 1;
420 if (xmax >= LCD_WIDTH)
421 xmax = LCD_WIDTH - 1; /* Clip right */
422 if (x < 0)
423 x = 0; /* Clip left */
424 if (x >= xmax)
425 return; /* nothing left to do */
426
427 ymax = y + height;
428 if (ymax > LCD_HEIGHT)
429 ymax = LCD_HEIGHT - 1; /* Clip bottom */
430 if (y < 0)
431 y = 0; /* Clip top */
432 if (y >= ymax)
433 return; /* nothing left to do */
434
435
436 lcd_window_x(x, xmax);
437 lcd_window_y(y, ymax);
438
439 ptr = (unsigned short *)&lcd_framebuffer[y][x];
440
441 do
442 {
443 lcd_write_data(ptr, width);
444 ptr += LCD_WIDTH;
445 }
446 while (++y < ymax);
447
448 lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT);
449}