summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c314
1 files changed, 276 insertions, 38 deletions
diff --git a/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c b/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
index 8efbdf77b9..dd815df05e 100644
--- a/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
+++ b/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
@@ -26,78 +26,316 @@
26#include "system.h" 26#include "system.h"
27#include "cpu.h" 27#include "cpu.h"
28 28
29static int display_type; 29#define CLAMP(x,min,max) \
30 if ((x)<(min)) (x)=(min);\
31 if ((x)>(max)) (x)=(max);
30 32
33/* the detected lcd type (0 or 1) */
34static int lcd_type;
35
36/* initialises the host lcd hardware, returns the lcd type */
31int lcd_hw_init(void) 37int lcd_hw_init(void)
32{ 38{
39 /* configure SSP */
33 bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE); 40 bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE);
41 SSP_CPSR = 8; /* TODO: use AS3525_SSP_PRESCALER, OF uses 8 */
42 SSP_CR0 = (0 << 8) | /* SCR, serial clock rate divider = 1 */
43 (1 << 7) | /* SPH, phase = 1 */
44 (1 << 6) | /* SPO, polarity = 1 */
45 (0 << 4) | /* FRF, frame format = motorola SPI */
46 (7 << 0); /* DSS, data size select = 8 bits */
47 SSP_CR1 = (1 << 3) | /* SOD, slave output disable = 1 */
48 (0 << 2) | /* MS, master/slave = master */
49 (1 << 1) | /* SSE, synchronous serial port enabled = true */
50 (0 << 0); /* LBM, loopback mode = normal */
51 SSP_IMSC &= ~0xF; /* disable interrupts */
52 SSP_DMACR &= ~0x3; /* disable DMA */
34 53
35 SSP_CPSR = AS3525_SSP_PRESCALER; /* OF = 0x10 */ 54 /* configure GPIO B2 (lcd D/C#) as output */
36 SSP_CR0 = (1<<7) | (1<<6) | 7; /* Motorola SPI frame format, 8 bits */
37 SSP_CR1 = (1<<3) | (1<<1); /* SSP Operation enabled */
38 SSP_IMSC = 0; /* No interrupts */
39
40 /* configure GPIO B2 (display D/C#) as output */
41 GPIOB_DIR |= (1<<2); 55 GPIOB_DIR |= (1<<2);
42 56
43 /* configure GPIO B3 (display type detect) as input */ 57 /* configure GPIO B3 (lcd type detect) as input */
44 GPIOB_DIR &= ~(1<<3); 58 GPIOB_DIR &= ~(1<<3);
45 59
46 /* set GPIO A5 (display RESET# ?) */ 60 /* configure GPIO A5 (lcd reset# ?) as output and set low */
47 GPIOA_DIR |= (1<<5); 61 GPIOA_DIR |= (1 << 5);
48 GPIOA_PIN(5) = (1<<5); 62 GPIOA_PIN(5) = 0;
49 63
50 /* detect display type on GPIO B3 */ 64 /* detect lcd type on GPIO B3 */
51 return GPIOB_PIN(3) ? 1 : 0; 65 return GPIOB_PIN(3) ? 1 : 0;
52} 66}
53 67
54void lcd_write_command(int byte) 68/* writes a command byte to the LCD */
69static void lcd_write_cmd(uint8_t byte)
55{ 70{
56 while(SSP_SR & (1<<4)) /* BSY flag */ 71 /* wait until not busy */
57 ; 72 while (SSP_SR & (1<<4));
58 73
59 /* LCD command mode */ 74 /* LCD command mode */
60 GPIOB_PIN(2) = 0; 75 GPIOB_PIN(2) = 0;
61 76
77 /* write data */
62 SSP_DATA = byte; 78 SSP_DATA = byte;
63 while(SSP_SR & (1<<4)) /* BSY flag */ 79
64 ; 80 /* wait until not busy */
81 while (SSP_SR & (1<<4));
82
83 /* LCD data mode */
84 GPIOB_PIN(2) = (1 << 2);
65} 85}
66 86
67void lcd_write_data(const fb_data* p_bytes, int count) 87/* writes a data byte to the LCD */
88static void lcd_write_dat(uint8_t data)
68{ 89{
69 /* LCD data mode */ 90 /* wait while transmit FIFO */
70 GPIOB_PIN(2) = (1<<2); 91 while (!(SSP_SR & (1<<1)));
71 92
72 while (count--) 93 /* write data */
73 { 94 SSP_DATA = data;
74 while(!(SSP_SR & (1<<1))) /* wait until transmit FIFO is not full */ 95}
75 ;
76 96
77 SSP_DATA = *p_bytes++; 97/* writes both a command and data value to the lcd */
78 } 98static void lcd_write(uint8_t cmd, uint8_t data)
99{
100 lcd_write_cmd(cmd);
101 lcd_write_dat(data);
79} 102}
80 103
81void lcd_update(void) 104/* delays during lcd initialisation (for type 0 LCDs) */
105static void lcd_delay(int us)
106{
107 udelay(us);
108}
109
110/* initialises lcd type 0 */
111static void lcd_init_type0(void)
82{ 112{
83 /* TODO */ 113 lcd_write(0x01, 0x00);
114 lcd_write(0x14, 0x01);
115 lcd_delay(5);
116
117 lcd_write(0x14, 0x00);
118 lcd_delay(5);
119
120 lcd_write(0x0F, 0x41);
121 lcd_write(0xEA, 0x0A);
122 lcd_write(0xEB, 0x42);
123 lcd_write(0x18, 0x08);
124 lcd_write(0x1A, 0x0B);
125 lcd_write(0x48, 0x03);
126
127 /* lcd width/height */
128 lcd_write(0x30, 0x00);
129 lcd_write(0x31, 0x5F);
130 lcd_write(0x32, 0x00);
131 lcd_write(0x33, 0x5F);
132
133 lcd_write(0xE0, 0x10);
134 lcd_write(0xE1, 0x00);
135 lcd_write(0xE5, 0x00);
136 lcd_write(0x0D, 0x00);
137 lcd_write(0x1D, 0x01);
138 lcd_write(0x09, 0x00);
139 lcd_write(0x13, 0x00);
140 lcd_write(0x16, 0x05);
141 lcd_write(0x3A, 0x03);
142 lcd_write(0x3B, 0x03);
143 lcd_write(0x3C, 0x03);
144 lcd_write(0x3D, 0x45);
145 lcd_write(0x3E, 0x45);
146 lcd_write(0x3F, 0x45);
147 lcd_write(0x40, 0x62);
148 lcd_write(0x41, 0x3D);
149 lcd_write(0x42, 0x46);
150}
151
152/* writes a table entry (for type 1 LCDs) */
153static void lcd_write_table(uint8_t val)
154{
155 lcd_write_dat((val >> 4) & 0x07);
156 lcd_write_dat((val >> 0) & 0x0F);
157}
158
159/* initialises lcd type 1 */
160static void lcd_init_type1(void)
161{
162 static const uint8_t curve[256] = {
163 /* 5-bit curve */
164 0, 5, 10, 15, 20, 25, 30, 35, 39, 43, 47, 51, 55, 59, 63, 67,
165 71, 75, 79, 83, 87, 91, 95, 99, 103, 105, 109, 113, 117, 121, 123, 127,
166 /* 6-bit curve */
167 0, 2, 4, 6, 8, 10, 12, 16, 18, 24, 26, 28, 30, 32, 34, 36,
168 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68,
169 70, 72, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102,
170 104, 106, 108, 110, 112, 114, 116, 118, 120, 121, 122, 123, 124, 125, 126, 127,
171 /* 5-bit curve */
172 0, 5, 10, 15, 20, 25, 30, 35, 39, 43, 47, 51, 55, 59, 63, 67,
173 71, 75, 79, 83, 87, 91, 93, 97, 101, 105, 109, 113, 117, 121, 124, 127
174 };
175 int i;
176
177 lcd_write_cmd(0x02);
178 lcd_write_dat(0x00);
179
180 lcd_write_cmd(0x01);
181
182 lcd_write_cmd(0x03);
183 lcd_write_dat(0x00);
184
185 lcd_write_cmd(0x04);
186 lcd_write_dat(0x03);
187
188 lcd_write_cmd(0x05);
189 lcd_write_dat(0x08);
190
191 lcd_write_cmd(0x06);
192 lcd_write_dat(0x00);
193
194 lcd_write_cmd(0x07);
195 lcd_write_dat(0x00);
196 lcd_write_dat(0x00);
197 lcd_write_dat(0x04);
198 lcd_write_dat(0x1F);
199 lcd_write_dat(0x00);
200 lcd_write_dat(0x00);
201 lcd_write_dat(0x05);
202 lcd_write_dat(0x0F);
203
204 lcd_write_cmd(0x08);
205 lcd_write_dat(0x01);
206
207 lcd_write_cmd(0x09);
208 lcd_write_dat(0x07);
209
210 /* lcd width/height */
211 lcd_write_cmd(0x0A);
212 lcd_write_dat(0x00);
213 lcd_write_dat(0x00);
214 lcd_write_dat(0x05);
215 lcd_write_dat(0x0F);
216 lcd_write_dat(0x00);
217 lcd_write_dat(0x00);
218 lcd_write_dat(0x05);
219 lcd_write_dat(0x0F);
220
221 lcd_write_cmd(0x0B);
222 lcd_write_dat(0x00);
223 lcd_write_dat(0x00);
224 lcd_write_dat(0x00);
225 lcd_write_dat(0x00);
226
227 lcd_write_cmd(0x0E);
228 lcd_write_dat(0x04);
229 lcd_write_dat(0x02);
230 lcd_write_dat(0x02);
231 lcd_write_dat(0x05);
232 lcd_write_dat(0x03);
233 lcd_write_dat(0x0F);
234
235 lcd_write_cmd(0x0F);
236 lcd_write_dat(0x0A);
237 lcd_write_dat(0x0A);
238 lcd_write_dat(0x0A);
239
240 lcd_write_cmd(0x1C);
241 lcd_write_dat(0x08);
242
243 lcd_write_cmd(0x1D);
244 lcd_write_dat(0x00);
245 lcd_write_dat(0x00);
246 lcd_write_dat(0x00);
247
248 lcd_write_cmd(0x1E);
249 lcd_write_dat(0x05);
250
251 lcd_write_cmd(0x1F);
252 lcd_write_dat(0x00);
253
254 lcd_write_cmd(0x30);
255 lcd_write_dat(0x10);
256
257 lcd_write_cmd(0x3A);
258 for (i = 0; i < 256; i++) {
259 lcd_write_table(curve[i]);
260 }
261
262 lcd_write_cmd(0x3C);
263 lcd_write_dat(0x00);
264
265 lcd_write_cmd(0x3D);
266 lcd_write_dat(0x00);
84} 267}
85 268
269/* initialises the lcd */
86void lcd_init_device(void) 270void lcd_init_device(void)
87{ 271{
88 /* TODO */ 272 lcd_type = lcd_hw_init();
89 display_type = lcd_hw_init(); 273 if (lcd_type == 0) {
274 lcd_init_type0();
275 }
276 else {
277 lcd_init_type1();
278 }
90} 279}
91 280
92/* Update a fraction of the display. */ 281/* sets up the lcd to receive frame buffer data */
282static void lcd_setup_rect(int x, int x_end, int y, int y_end)
283{
284 if (lcd_type == 0) {
285 lcd_write(0x34, x);
286 lcd_write(0x35, x_end);
287 lcd_write(0x36, y);
288 lcd_write(0x37, y_end);
289 }
290 else {
291 lcd_write_cmd(0x0A);
292 lcd_write_dat((x >> 8) & 0xFF);
293 lcd_write_dat((x >> 0) & 0xFF);
294 lcd_write_dat((x_end >> 8) & 0xFF);
295 lcd_write_dat((x_end >> 0) & 0xFF);
296 lcd_write_dat((y >> 8) & 0xFF);
297 lcd_write_dat((y >> 0) & 0xFF);
298 lcd_write_dat((y_end >> 8) & 0xFF);
299 lcd_write_dat((y_end >> 0) & 0xFF);
300 }
301}
302
303/* Updates a fraction of the display. */
93void lcd_update_rect(int x, int y, int width, int height) 304void lcd_update_rect(int x, int y, int width, int height)
94{ 305{
95 (void) x; 306 fb_data *ptr;
96 (void) y; 307 fb_data pixel;
97 (void) width; 308 int row, col;
98 (void) height; 309 int x_end = x + width - 1;
99 310 int y_end = y + height - 1;
100 /* TODO not implemented yet, do a full update instead */ 311
101 lcd_update(); 312 /* check/correct bounds */
313 CLAMP(x, 0, LCD_WIDTH - 1);
314 CLAMP(x_end, 0, LCD_WIDTH - 1);
315 CLAMP(y, 0, LCD_HEIGHT - 1);
316 CLAMP(y_end, 0, LCD_HEIGHT - 1);
317 if ((x > x_end) || (y > y_end)) {
318 return;
319 }
320
321 /* setup GRAM write window */
322 lcd_setup_rect(x, x_end, y, y_end);
323
324 /* write to GRAM */
325 lcd_write_cmd((lcd_type == 0) ? 0x08 : 0x0C);
326 for (row = y; row <= y_end; row++) {
327 ptr = &lcd_framebuffer[row][x];
328 for (col = x; col <= x_end; col++) {
329 pixel = *ptr++;
330 lcd_write_dat((pixel >> 8) & 0xFF);
331 lcd_write_dat((pixel >> 0) & 0xFF);
332 }
333 }
334}
335
336/* updates the entire lcd */
337void lcd_update(void)
338{
339 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
102} 340}
103 341