diff options
Diffstat (limited to 'firmware/target/arm/as3525/sansa-e200v2')
-rw-r--r-- | firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c | 152 |
1 files changed, 99 insertions, 53 deletions
diff --git a/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c b/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c index e14ad21681..1ffd9fddd5 100644 --- a/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c +++ b/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c | |||
@@ -34,7 +34,7 @@ | |||
34 | 34 | ||
35 | static bool display_on = false; /* is the display turned on? */ | 35 | static bool display_on = false; /* is the display turned on? */ |
36 | static bool display_flipped = false; | 36 | static bool display_flipped = false; |
37 | static int xoffset = 0; /* needed for flip */ | 37 | static int y_offset = 0; /* needed for flip */ |
38 | 38 | ||
39 | /* register defines */ | 39 | /* register defines */ |
40 | #define R_START_OSC 0x00 | 40 | #define R_START_OSC 0x00 |
@@ -79,23 +79,22 @@ static int xoffset = 0; /* needed for flip */ | |||
79 | #define R_HORIZ_RAM_ADDR_POS 0x44 | 79 | #define R_HORIZ_RAM_ADDR_POS 0x44 |
80 | #define R_VERT_RAM_ADDR_POS 0x45 | 80 | #define R_VERT_RAM_ADDR_POS 0x45 |
81 | 81 | ||
82 | #define LCD_CMD (*(volatile unsigned short *)0xf0000000) | ||
83 | #define LCD_DATA (*(volatile unsigned short *)0xf0000002) | ||
84 | |||
85 | #define R_ENTRY_MODE_HORZ 0x7030 | 82 | #define R_ENTRY_MODE_HORZ 0x7030 |
86 | #define R_ENTRY_MODE_VERT 0x7038 | 83 | #define R_ENTRY_MODE_VERT 0x7038 |
84 | #define R_ENTRY_MODE_SOLID_VERT 0x1038 | ||
87 | 85 | ||
88 | /* TODO: Implement this function */ | 86 | /* TODO: Implement this function */ |
89 | static void lcd_delay(int x) | 87 | static void lcd_delay(int x) |
90 | { | 88 | { |
91 | (void)x; | 89 | /* This is just arbitrary - the OF does something more complex */ |
90 | x *= 1024; | ||
91 | while (x--); | ||
92 | } | 92 | } |
93 | 93 | ||
94 | /* DBOP initialisation, do what OF does */ | 94 | /* DBOP initialisation, do what OF does */ |
95 | static void ams3525_dbop_init(void) | 95 | static void ams3525_dbop_init(void) |
96 | { | 96 | { |
97 | 97 | /* TODO: The OF calls some other functions here, but maybe not important */ | |
98 | /* TODO: More... */ | ||
99 | 98 | ||
100 | DBOP_TIMPOL_01 = 0xe167e167; | 99 | DBOP_TIMPOL_01 = 0xe167e167; |
101 | DBOP_TIMPOL_23 = 0xe167006e; | 100 | DBOP_TIMPOL_23 = 0xe167006e; |
@@ -109,35 +108,43 @@ static void ams3525_dbop_init(void) | |||
109 | DBOP_TIMPOL_01 = 0x6e167; | 108 | DBOP_TIMPOL_01 = 0x6e167; |
110 | DBOP_TIMPOL_23 = 0xa167e06f; | 109 | DBOP_TIMPOL_23 = 0xa167e06f; |
111 | 110 | ||
112 | /* TODO: More... */ | 111 | /* TODO: The OF calls some other functions here, but maybe not important */ |
113 | } | 112 | } |
114 | 113 | ||
115 | static void lcd_write_reg(int reg, int value) | 114 | |
115 | static void lcd_write_cmd(int cmd) | ||
116 | { | 116 | { |
117 | /* Write register */ | ||
117 | DBOP_CTRL &= ~(1<<14); | 118 | DBOP_CTRL &= ~(1<<14); |
118 | 119 | ||
119 | DBOP_TIMPOL_23 = 0xa167006e; | 120 | DBOP_TIMPOL_23 = 0xa167006e; |
120 | 121 | ||
121 | DBOP_DOUT = reg; | 122 | DBOP_DOUT = cmd; |
122 | 123 | ||
123 | /* Wait for fifo to empty */ | 124 | /* Wait for fifo to empty */ |
124 | while ((DBOP_STAT & (1<<10)) == 0); | 125 | while ((DBOP_STAT & (1<<10)) == 0); |
125 | 126 | ||
126 | DBOP_TIMPOL_23 = 0xa167e06f; | 127 | DBOP_TIMPOL_23 = 0xa167e06f; |
127 | |||
128 | |||
129 | DBOP_DOUT = value; | ||
130 | |||
131 | /* Wait for fifo to empty */ | ||
132 | while ((DBOP_STAT & (1<<10)) == 0); | ||
133 | } | 128 | } |
134 | 129 | ||
135 | void lcd_write_data(const fb_data* p_bytes, int count) | 130 | void lcd_write_data(const fb_data* p_bytes, int count) |
136 | { | 131 | { |
137 | (void)p_bytes; | 132 | while (count--) |
138 | (void)count; | 133 | { |
134 | DBOP_DOUT = *p_bytes++; | ||
135 | |||
136 | /* Wait for fifo to empty */ | ||
137 | while ((DBOP_STAT & (1<<10)) == 0); | ||
138 | } | ||
139 | } | 139 | } |
140 | 140 | ||
141 | static void lcd_write_reg(int reg, int value) | ||
142 | { | ||
143 | unsigned short data = value; | ||
144 | |||
145 | lcd_write_cmd(reg); | ||
146 | lcd_write_data(&data, 1); | ||
147 | } | ||
141 | 148 | ||
142 | /*** hardware configuration ***/ | 149 | /*** hardware configuration ***/ |
143 | 150 | ||
@@ -161,7 +168,7 @@ static void flip_lcd(bool yesno) | |||
161 | void lcd_set_flip(bool yesno) | 168 | void lcd_set_flip(bool yesno) |
162 | { | 169 | { |
163 | display_flipped = yesno; | 170 | display_flipped = yesno; |
164 | xoffset = yesno ? 4 : 0; | 171 | y_offset = yesno ? 4 : 0; /* FIXME: Is a y_offset needed? */ |
165 | 172 | ||
166 | if (display_on) | 173 | if (display_on) |
167 | flip_lcd(yesno); | 174 | flip_lcd(yesno); |
@@ -277,42 +284,42 @@ static void _display_on(void) | |||
277 | /* LCD init */ | 284 | /* LCD init */ |
278 | void lcd_init_device(void) | 285 | void lcd_init_device(void) |
279 | { | 286 | { |
280 | ams3525_dbop_init(); | 287 | ams3525_dbop_init(); |
281 | 288 | ||
282 | /* Init GPIOs the same as the OF */ | 289 | /* Init GPIOs the same as the OF */ |
283 | 290 | ||
284 | GPIOA_DIR |= (1<<5); | 291 | GPIOA_DIR |= (1<<5); |
285 | GPIOA_PIN(5) = 0; | 292 | GPIOA_PIN(5) = 0; |
286 | 293 | ||
287 | GPIOA_PIN(3) = (1<<3); | 294 | GPIOA_PIN(3) = (1<<3); |
288 | 295 | ||
289 | GPIOA_DIR |= (3<<3); | 296 | GPIOA_DIR |= (3<<3); |
290 | 297 | ||
291 | GPIOA_PIN(3) = (1<<3); | 298 | GPIOA_PIN(3) = (1<<3); |
292 | 299 | ||
293 | GPIOA_PIN(4) = 0; //c80b0040 := 0; | 300 | GPIOA_PIN(4) = 0; //c80b0040 := 0; |
294 | 301 | ||
295 | GPIOA_DIR |= (1<<7); | 302 | GPIOA_DIR |= (1<<7); |
296 | GPIOA_PIN(7) = 0; | 303 | GPIOA_PIN(7) = 0; |
297 | 304 | ||
298 | CCU_IO &= ~(1<<2); | 305 | CCU_IO &= ~(1<<2); |
299 | CCU_IO &= ~(1<<3); | 306 | CCU_IO &= ~(1<<3); |
300 | 307 | ||
301 | GPIOD_DIR |= (1<<7); | 308 | GPIOD_DIR |= (1<<7); |
302 | 309 | ||
303 | #if 0 | 310 | #if 0 |
304 | /* TODO: This code is conditional on a variable in the OF init, we need to | 311 | /* TODO: This code is conditional on a variable in the OF init, we need to |
305 | work out what it means */ | 312 | work out what it means */ |
306 | 313 | ||
307 | GPIOD_PIN(7) = (1<<7); | 314 | GPIOD_PIN(7) = (1<<7); |
308 | GPIOD_DIR |= (1<<7); | 315 | GPIOD_DIR |= (1<<7); |
309 | #endif | 316 | #endif |
310 | 317 | ||
311 | lcd_delay(1); | 318 | lcd_delay(1); |
312 | 319 | ||
313 | GPIOA_PIN(5) = (1<<5); | 320 | GPIOA_PIN(5) = (1<<5); |
314 | 321 | ||
315 | lcd_delay(1); | 322 | lcd_delay(1); |
316 | 323 | ||
317 | _display_on(); | 324 | _display_on(); |
318 | } | 325 | } |
@@ -361,25 +368,64 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
361 | 368 | ||
362 | /* Update the display. | 369 | /* Update the display. |
363 | This must be called after all other LCD functions that change the display. */ | 370 | This must be called after all other LCD functions that change the display. */ |
364 | void lcd_update(void) ICODE_ATTR; | ||
365 | void lcd_update(void) | 371 | void lcd_update(void) |
366 | { | 372 | { |
367 | if(display_on){ | 373 | if (!display_on) |
368 | /* TODO */ | 374 | return; |
369 | } | 375 | |
370 | } | 376 | lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_SOLID_VERT); |
377 | |||
378 | /* Set start position and window */ | ||
379 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, | ||
380 | ((y_offset + LCD_HEIGHT-1) << 8) | y_offset); | ||
381 | lcd_write_reg(R_VERT_RAM_ADDR_POS, (LCD_WIDTH-1) << 8); | ||
382 | lcd_write_reg(R_RAM_ADDR_SET, y_offset); | ||
383 | |||
384 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | ||
385 | |||
386 | lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT); | ||
387 | } /* lcd_update */ | ||
371 | 388 | ||
372 | 389 | ||
373 | /* Update a fraction of the display. */ | 390 | /* Update a fraction of the display. */ |
374 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; | ||
375 | void lcd_update_rect(int x, int y, int width, int height) | 391 | void lcd_update_rect(int x, int y, int width, int height) |
376 | { | 392 | { |
377 | (void)x; | 393 | int ymax; |
378 | (void)y; | 394 | const unsigned short *ptr; |
379 | (void)width; | 395 | |
380 | (void)height; | 396 | if (!display_on) |
381 | 397 | return; | |
382 | if(display_on) { | 398 | |
383 | /* TODO */ | 399 | if (x + width > LCD_WIDTH) |
400 | width = LCD_WIDTH - x; /* Clip right */ | ||
401 | if (x < 0) | ||
402 | width += x, x = 0; /* Clip left */ | ||
403 | if (width <= 0) | ||
404 | return; /* nothing left to do */ | ||
405 | |||
406 | ymax = y + height; | ||
407 | if (ymax > LCD_HEIGHT) | ||
408 | ymax = LCD_HEIGHT; /* Clip bottom */ | ||
409 | if (y < 0) | ||
410 | y = 0; /* Clip top */ | ||
411 | if (y >= ymax) | ||
412 | return; /* nothing left to do */ | ||
413 | |||
414 | lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_SOLID_VERT); | ||
415 | /* Set start position and window */ | ||
416 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, | ||
417 | ((y_offset + LCD_HEIGHT-1) << 8) | y_offset); | ||
418 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((x + width - 1) << 8) | x); | ||
419 | lcd_write_reg(R_RAM_ADDR_SET, (x << 8) | (y + y_offset)); | ||
420 | |||
421 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | ||
422 | |||
423 | ptr = (unsigned short *)&lcd_framebuffer[y][x]; | ||
424 | |||
425 | do | ||
426 | { | ||
427 | lcd_write_data(ptr, width); | ||
428 | ptr += LCD_WIDTH; | ||
384 | } | 429 | } |
385 | } | 430 | while (++y < ymax); |
431 | } /* lcd_update_rect */ | ||