diff options
Diffstat (limited to 'firmware/target/arm/sandisk/sansa-c200/lcd-c200.c')
-rw-r--r-- | firmware/target/arm/sandisk/sansa-c200/lcd-c200.c | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c b/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c new file mode 100644 index 0000000000..6626ea4e6d --- /dev/null +++ b/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c | |||
@@ -0,0 +1,249 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id:$ | ||
9 | * | ||
10 | * Copyright (C) 2007 by Mark Arigo | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include "config.h" | ||
20 | #include "cpu.h" | ||
21 | #include "lcd.h" | ||
22 | #include "kernel.h" | ||
23 | #include "system.h" | ||
24 | |||
25 | #define LCD_BASE (*(volatile unsigned long *)(0x70003000)) | ||
26 | #define LCD_CMD (*(volatile unsigned long *)(0x70003008)) | ||
27 | #define LCD_DATA (*(volatile unsigned long *)(0x70003010)) | ||
28 | |||
29 | #define LCD_BUSY 0x8000 | ||
30 | |||
31 | /* check if number of useconds has past */ | ||
32 | static inline bool timer_check(int clock_start, int usecs) | ||
33 | { | ||
34 | return ((int)(USEC_TIMER - clock_start)) >= usecs; | ||
35 | } | ||
36 | |||
37 | /* wait for LCD with timeout */ | ||
38 | static inline void lcd_wait_write(void) | ||
39 | { | ||
40 | int start = USEC_TIMER; | ||
41 | |||
42 | do { | ||
43 | if ((LCD_BASE & LCD_BUSY) == 0) | ||
44 | break; | ||
45 | } while (timer_check(start, 1000) == 0); | ||
46 | } | ||
47 | |||
48 | /* send LCD data */ | ||
49 | static void lcd_send_data(unsigned data) | ||
50 | { | ||
51 | lcd_wait_write(); | ||
52 | LCD_DATA = (data >> 8) & 0xff; | ||
53 | |||
54 | lcd_wait_write(); | ||
55 | LCD_DATA = data & 0xff; | ||
56 | } | ||
57 | |||
58 | /* send LCD command */ | ||
59 | static void lcd_send_command(unsigned cmd) | ||
60 | { | ||
61 | lcd_wait_write(); | ||
62 | LCD_CMD = cmd; | ||
63 | } | ||
64 | |||
65 | /* LCD init */ | ||
66 | void lcd_init_device(void) | ||
67 | { | ||
68 | /* This is from the c200 of bootloader beginning at offset 0xbbf4 */ | ||
69 | outl(inl(0x70000010) & ~0xfc000000, 0x70000010); | ||
70 | outl(inl(0x70000010), 0x70000010); | ||
71 | |||
72 | DEV_INIT &= ~0x400; | ||
73 | udelay(10000); | ||
74 | |||
75 | LCD_BASE &= ~0x4; | ||
76 | udelay(15); | ||
77 | |||
78 | LCD_BASE |= 0x4; | ||
79 | udelay(10); | ||
80 | |||
81 | LCD_BASE = 0x4687; | ||
82 | udelay(10000); | ||
83 | |||
84 | lcd_send_command(0x2c); | ||
85 | udelay(20000); | ||
86 | |||
87 | lcd_send_command(0x02); | ||
88 | lcd_send_command(0x01); | ||
89 | udelay(20000); | ||
90 | |||
91 | lcd_send_command(0x26); | ||
92 | lcd_send_command(0x01); | ||
93 | udelay(20000); | ||
94 | |||
95 | lcd_send_command(0x26); | ||
96 | lcd_send_command(0x09); | ||
97 | udelay(20000); | ||
98 | |||
99 | lcd_send_command(0x26); | ||
100 | lcd_send_command(0x0b); | ||
101 | udelay(20000); | ||
102 | |||
103 | lcd_send_command(0x26); | ||
104 | lcd_send_command(0x0f); | ||
105 | udelay(20000); | ||
106 | |||
107 | lcd_send_command(0x10); | ||
108 | lcd_send_command(0x07); | ||
109 | |||
110 | lcd_send_command(0x20); | ||
111 | lcd_send_command(0x03); | ||
112 | |||
113 | lcd_send_command(0x24); | ||
114 | lcd_send_command(0x03); | ||
115 | |||
116 | lcd_send_command(0x28); | ||
117 | lcd_send_command(0x01); | ||
118 | |||
119 | lcd_send_command(0x2a); | ||
120 | lcd_send_command(0x55); | ||
121 | |||
122 | lcd_send_command(0x30); | ||
123 | lcd_send_command(0x10); | ||
124 | |||
125 | lcd_send_command(0x32); | ||
126 | lcd_send_command(0x0e); | ||
127 | |||
128 | lcd_send_command(0x34); | ||
129 | lcd_send_command(0x0d); | ||
130 | |||
131 | lcd_send_command(0x36); | ||
132 | lcd_send_command(0); | ||
133 | |||
134 | lcd_send_command(0x40); | ||
135 | lcd_send_command(0x82); | ||
136 | |||
137 | lcd_send_command(0x43); /* vertical dimensions */ | ||
138 | lcd_send_command(0x1a); /* y1 + 0x1a */ | ||
139 | lcd_send_command(LCD_HEIGHT - 1 + 0x1a); /* y2 + 0x1a */ | ||
140 | |||
141 | lcd_send_command(0x42); /* horizontal dimensions */ | ||
142 | lcd_send_command(0); /* x1 */ | ||
143 | lcd_send_command(LCD_WIDTH - 1); /* x2 */ | ||
144 | udelay(100000); | ||
145 | |||
146 | lcd_send_command(0x51); | ||
147 | } | ||
148 | |||
149 | /*** hardware configuration ***/ | ||
150 | int lcd_default_contrast(void) | ||
151 | { | ||
152 | return DEFAULT_CONTRAST_SETTING; | ||
153 | } | ||
154 | |||
155 | void lcd_set_contrast(int val) | ||
156 | { | ||
157 | /* TODO: Implement lcd_set_contrast() */ | ||
158 | (void)val; | ||
159 | } | ||
160 | |||
161 | void lcd_set_invert_display(bool yesno) | ||
162 | { | ||
163 | /* TODO: Implement lcd_set_invert_display() */ | ||
164 | (void)yesno; | ||
165 | } | ||
166 | |||
167 | /* turn the display upside down (call lcd_update() afterwards) */ | ||
168 | void lcd_set_flip(bool yesno) | ||
169 | { | ||
170 | /* TODO: Implement lcd_set_flip() */ | ||
171 | (void)yesno; | ||
172 | } | ||
173 | |||
174 | /*** update functions ***/ | ||
175 | |||
176 | /* Performance function that works with an external buffer | ||
177 | note that by and bheight are in 4-pixel units! */ | ||
178 | void lcd_blit(const fb_data* data, int x, int by, int width, | ||
179 | int bheight, int stride) | ||
180 | { | ||
181 | /* TODO: Implement lcd_blit() */ | ||
182 | (void)data; | ||
183 | (void)x; | ||
184 | (void)by; | ||
185 | (void)width; | ||
186 | (void)bheight; | ||
187 | (void)stride; | ||
188 | } | ||
189 | |||
190 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
191 | void lcd_yuv_blit(unsigned char * const src[3], | ||
192 | int src_x, int src_y, int stride, | ||
193 | int x, int y, int width, int height) | ||
194 | { | ||
195 | (void)src; | ||
196 | (void)src_x; | ||
197 | (void)src_y; | ||
198 | (void)stride; | ||
199 | (void)x; | ||
200 | (void)y; | ||
201 | (void)width; | ||
202 | (void)height; | ||
203 | } | ||
204 | |||
205 | /* Update the display. | ||
206 | This must be called after all other LCD functions that change the display. */ | ||
207 | void lcd_update(void) | ||
208 | { | ||
209 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | ||
210 | } | ||
211 | |||
212 | /* Update a fraction of the display. */ | ||
213 | void lcd_update_rect(int x0, int y0, int width, int height) | ||
214 | { | ||
215 | unsigned short *addr; | ||
216 | int c, r; | ||
217 | int x1 = (x0 + width) - 1; | ||
218 | int y1 = (y0 + height) - 1; | ||
219 | |||
220 | if ((x1 <= 0) || (y1 <= 0)) | ||
221 | return; | ||
222 | |||
223 | if(y1 >= LCD_HEIGHT) | ||
224 | y1 = LCD_HEIGHT - 1; | ||
225 | |||
226 | lcd_send_command(0x43); | ||
227 | lcd_send_command(y0 + 0x1a); | ||
228 | lcd_send_command(y1 + 0x1a); | ||
229 | |||
230 | if(x1 >= LCD_WIDTH) | ||
231 | x1 = LCD_WIDTH - 1; | ||
232 | |||
233 | lcd_send_command(0x42); | ||
234 | lcd_send_command(x0); | ||
235 | lcd_send_command(x1); | ||
236 | |||
237 | addr = (unsigned short*)&lcd_framebuffer[y0][x0]; | ||
238 | |||
239 | /* for each row */ | ||
240 | for (r = 0; r < height; r++) { | ||
241 | /* for each column */ | ||
242 | for (c = 0; c < width; c++) { | ||
243 | /* output 1 pixel */ | ||
244 | lcd_send_data(*(addr++)); | ||
245 | } | ||
246 | |||
247 | addr += LCD_WIDTH - width; | ||
248 | } | ||
249 | } | ||