diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/lcd-gigabeat-s.c | 158 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/lcd-target.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/lcd-target.h | 6 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/lcd-s3c2440.c | 158 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/mini2440/lcd-target.h | 6 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | 152 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/lcd-target.h | 28 |
7 files changed, 69 insertions, 443 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/lcd-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/lcd-gigabeat-s.c index 6a0c889851..8185479390 100644 --- a/firmware/target/arm/imx31/gigabeat-s/lcd-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/lcd-gigabeat-s.c | |||
@@ -18,32 +18,20 @@ | |||
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include <sys/types.h> | ||
22 | #include "inttypes.h" | ||
23 | |||
24 | #include "config.h" | 21 | #include "config.h" |
25 | #include "system.h" | 22 | #include "system.h" |
26 | #include "cpu.h" | ||
27 | #include "spi-imx31.h" | ||
28 | #include "mc13783.h" | ||
29 | #include "string.h" | ||
30 | #include "lcd.h" | 23 | #include "lcd.h" |
31 | #include "kernel.h" | ||
32 | #include "lcd-target.h" | 24 | #include "lcd-target.h" |
33 | #include "backlight-target.h" | 25 | #include "backlight-target.h" |
26 | #include "spi-imx31.h" | ||
27 | #include "mc13783.h" | ||
34 | 28 | ||
35 | #define MAIN_LCD_IDMAC_CHANNEL 14 | 29 | extern void lcd_set_active(bool active); |
36 | #define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)]) | ||
37 | 30 | ||
38 | /* Copies a rectangle from one framebuffer to another. Can be used in | 31 | #define MAIN_LCD_IDMAC_CHANNEL 14 |
39 | single transfer mode with width = num pixels, and height = 1 which | ||
40 | allows a full-width rectangle to be copied more efficiently. */ | ||
41 | extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src, | ||
42 | int width, int height); | ||
43 | 32 | ||
44 | static bool lcd_on = true; | ||
45 | static bool lcd_powered = true; | 33 | static bool lcd_powered = true; |
46 | static unsigned lcd_yuv_options = 0; | 34 | |
47 | /* Settings shadow regs */ | 35 | /* Settings shadow regs */ |
48 | #ifdef HAVE_LCD_CONTRAST | 36 | #ifdef HAVE_LCD_CONTRAST |
49 | static uint8_t reg0x0b = 0x2f; | 37 | static uint8_t reg0x0b = 0x2f; |
@@ -184,44 +172,6 @@ void INIT_ATTR lcd_init_device(void) | |||
184 | lcd_sync_settings(); | 172 | lcd_sync_settings(); |
185 | } | 173 | } |
186 | 174 | ||
187 | /* Update a fraction of the display. */ | ||
188 | void lcd_update_rect(int x, int y, int width, int height) | ||
189 | { | ||
190 | fb_data *dst, *src; | ||
191 | |||
192 | if (!lcd_on) | ||
193 | return; | ||
194 | |||
195 | if (x + width > LCD_WIDTH) | ||
196 | width = LCD_WIDTH - x; /* Clip right */ | ||
197 | if (x < 0) | ||
198 | width += x, x = 0; /* Clip left */ | ||
199 | if (width <= 0) | ||
200 | return; /* nothing left to do */ | ||
201 | |||
202 | if (y + height > LCD_HEIGHT) | ||
203 | height = LCD_HEIGHT - y; /* Clip bottom */ | ||
204 | if (y < 0) | ||
205 | height += y, y = 0; /* Clip top */ | ||
206 | if (height <= 0) | ||
207 | return; /* nothing left to do */ | ||
208 | |||
209 | dst = (fb_data *)FRAME + LCD_WIDTH*y + x; | ||
210 | src = &lcd_framebuffer[y][x]; | ||
211 | |||
212 | /* Copy part of the Rockbox framebuffer to the second framebuffer */ | ||
213 | if (width < LCD_WIDTH) | ||
214 | { | ||
215 | /* Not full width - do line-by-line */ | ||
216 | lcd_copy_buffer_rect(dst, src, width, height); | ||
217 | } | ||
218 | else | ||
219 | { | ||
220 | /* Full width - copy as one line */ | ||
221 | lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | void lcd_sleep(void) | 175 | void lcd_sleep(void) |
226 | { | 176 | { |
227 | if (!lcd_powered) | 177 | if (!lcd_powered) |
@@ -235,7 +185,7 @@ void lcd_sleep(void) | |||
235 | 185 | ||
236 | void lcd_enable(bool state) | 186 | void lcd_enable(bool state) |
237 | { | 187 | { |
238 | if (state == lcd_on) | 188 | if (state == lcd_active()) |
239 | return; | 189 | return; |
240 | 190 | ||
241 | if (state) | 191 | if (state) |
@@ -245,99 +195,13 @@ void lcd_enable(bool state) | |||
245 | IPU_IDMAC_CHA_EN |= 1ul << MAIN_LCD_IDMAC_CHANNEL; | 195 | IPU_IDMAC_CHA_EN |= 1ul << MAIN_LCD_IDMAC_CHANNEL; |
246 | lcd_sync_settings(); | 196 | lcd_sync_settings(); |
247 | sleep(HZ/50); | 197 | sleep(HZ/50); |
248 | lcd_on = true; | 198 | lcd_set_active(true); |
249 | lcd_update(); | 199 | lcd_update(); |
250 | send_event(LCD_EVENT_ACTIVATION, NULL); | 200 | send_event(LCD_EVENT_ACTIVATION, NULL); |
251 | } | 201 | } |
252 | else | 202 | else |
253 | { | 203 | { |
254 | lcd_on = false; | 204 | lcd_set_active(false); |
255 | } | ||
256 | } | ||
257 | |||
258 | bool lcd_active(void) | ||
259 | { | ||
260 | return lcd_on; | ||
261 | } | ||
262 | |||
263 | /* Update the display. | ||
264 | This must be called after all other LCD functions that change the display. */ | ||
265 | void lcd_update(void) | ||
266 | { | ||
267 | if (!lcd_on) | ||
268 | return; | ||
269 | |||
270 | lcd_copy_buffer_rect((fb_data *)FRAME, &lcd_framebuffer[0][0], | ||
271 | LCD_WIDTH*LCD_HEIGHT, 1); | ||
272 | } | ||
273 | |||
274 | void lcd_yuv_set_options(unsigned options) | ||
275 | { | ||
276 | lcd_yuv_options = options; | ||
277 | } | ||
278 | |||
279 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
280 | extern void lcd_write_yuv420_lines(fb_data *dst, | ||
281 | unsigned char const * const src[3], | ||
282 | int width, | ||
283 | int stride); | ||
284 | extern void lcd_write_yuv420_lines_odither(fb_data *dst, | ||
285 | unsigned char const * const src[3], | ||
286 | int width, | ||
287 | int stride, | ||
288 | int x_screen, /* To align dither pattern */ | ||
289 | int y_screen); | ||
290 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
291 | /* For the Gigabeat - show it rotated */ | ||
292 | /* So the LCD_WIDTH is now the height */ | ||
293 | void lcd_blit_yuv(unsigned char * const src[3], | ||
294 | int src_x, int src_y, int stride, | ||
295 | int x, int y, int width, int height) | ||
296 | { | ||
297 | /* Caches for chroma data so it only need be recaculated every other | ||
298 | line */ | ||
299 | unsigned char const * yuv_src[3]; | ||
300 | off_t z; | ||
301 | |||
302 | if (!lcd_on) | ||
303 | return; | ||
304 | |||
305 | /* Sorry, but width and height must be >= 2 or else */ | ||
306 | width &= ~1; | ||
307 | height >>= 1; | ||
308 | |||
309 | y = LCD_WIDTH - 1 - y; | ||
310 | fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + y; | ||
311 | |||
312 | z = stride*src_y; | ||
313 | yuv_src[0] = src[0] + z + src_x; | ||
314 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
315 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
316 | |||
317 | if (lcd_yuv_options & LCD_YUV_DITHER) | ||
318 | { | ||
319 | do | ||
320 | { | ||
321 | lcd_write_yuv420_lines_odither(dst, yuv_src, width, stride, y, x); | ||
322 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
323 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
324 | yuv_src[2] += stride >> 1; | ||
325 | dst -= 2; | ||
326 | y -= 2; | ||
327 | } | ||
328 | while (--height > 0); | ||
329 | } | ||
330 | else | ||
331 | { | ||
332 | do | ||
333 | { | ||
334 | lcd_write_yuv420_lines(dst, yuv_src, width, stride); | ||
335 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
336 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
337 | yuv_src[2] += stride >> 1; | ||
338 | dst -= 2; | ||
339 | } | ||
340 | while (--height > 0); | ||
341 | } | 205 | } |
342 | } | 206 | } |
343 | 207 | ||
@@ -346,7 +210,7 @@ void lcd_set_contrast(int val) | |||
346 | { | 210 | { |
347 | reg0x0b = val & 0x3f; | 211 | reg0x0b = val & 0x3f; |
348 | 212 | ||
349 | if (!lcd_on) | 213 | if (!lcd_active()) |
350 | return; | 214 | return; |
351 | 215 | ||
352 | lcd_write_reg(0x0b, reg0x0b); | 216 | lcd_write_reg(0x0b, reg0x0b); |
@@ -363,7 +227,7 @@ void lcd_set_invert_display(bool yesno) | |||
363 | { | 227 | { |
364 | reg0x27 = yesno ? 0x10 : 0x00; | 228 | reg0x27 = yesno ? 0x10 : 0x00; |
365 | 229 | ||
366 | if (!lcd_on) | 230 | if (!lcd_active()) |
367 | return; | 231 | return; |
368 | 232 | ||
369 | lcd_write_reg(0x27, reg0x27); | 233 | lcd_write_reg(0x27, reg0x27); |
@@ -375,7 +239,7 @@ void lcd_set_flip(bool yesno) | |||
375 | { | 239 | { |
376 | reg0x06 = yesno ? 0x02 : 0x04; | 240 | reg0x06 = yesno ? 0x02 : 0x04; |
377 | 241 | ||
378 | if (!lcd_on) | 242 | if (!lcd_active()) |
379 | return; | 243 | return; |
380 | 244 | ||
381 | lcd_write_reg(0x06, reg0x06); | 245 | lcd_write_reg(0x06, reg0x06); |
diff --git a/firmware/target/arm/imx31/gigabeat-s/lcd-target.h b/firmware/target/arm/imx31/gigabeat-s/lcd-target.h index 8e44585682..9cf7fa38e2 100644 --- a/firmware/target/arm/imx31/gigabeat-s/lcd-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/lcd-target.h | |||
@@ -21,8 +21,6 @@ | |||
21 | #ifndef LCD_TARGET_H | 21 | #ifndef LCD_TARGET_H |
22 | #define LCD_TARGET_H | 22 | #define LCD_TARGET_H |
23 | 23 | ||
24 | #if 0 | 24 | #define LCD_FRAMEBUF_ADDR(col, row) ((fb_data *)FRAME + (row)*LCD_WIDTH + (col)) |
25 | void lcd_enable(bool state); | ||
26 | #endif | ||
27 | 25 | ||
28 | #endif /* LCD_TARGET_H */ | 26 | #endif /* LCD_TARGET_H */ |
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-target.h b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-target.h index c136a2052d..d5656f6d45 100644 --- a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-target.h +++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-target.h | |||
@@ -18,8 +18,10 @@ | |||
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #ifndef LCD_TARGET_H | ||
22 | #define LCD_TARGET_H | ||
21 | 23 | ||
22 | extern void lcd_enable(bool state); | 24 | #define LCD_FRAMEBUF_ADDR(col, row) ((fb_data *)FRAME + (row)*LCD_WIDTH + (col)) |
23 | 25 | ||
24 | /* Config values for LCDCON1 */ | 26 | /* Config values for LCDCON1 */ |
25 | /* ENVID = 0, BPPMODE = 16 bpp, PNRMODE = TFT, MMODE = Each Frame, CLKVAL = 8 */ | 27 | /* ENVID = 0, BPPMODE = 16 bpp, PNRMODE = TFT, MMODE = Each Frame, CLKVAL = 8 */ |
@@ -43,3 +45,5 @@ extern void lcd_enable(bool state); | |||
43 | /* Config values for LCDCON4 */ | 45 | /* Config values for LCDCON4 */ |
44 | /* HSPW = 7 */ | 46 | /* HSPW = 7 */ |
45 | #define LCD_HSYNC_LEN 7 | 47 | #define LCD_HSYNC_LEN 7 |
48 | |||
49 | #endif /* LCD_TARGET_H */ | ||
diff --git a/firmware/target/arm/s3c2440/lcd-s3c2440.c b/firmware/target/arm/s3c2440/lcd-s3c2440.c index 77be29f556..cbf4784064 100644 --- a/firmware/target/arm/s3c2440/lcd-s3c2440.c +++ b/firmware/target/arm/s3c2440/lcd-s3c2440.c | |||
@@ -19,36 +19,16 @@ | |||
19 | * KIND, either express or implied. | 19 | * KIND, either express or implied. |
20 | * | 20 | * |
21 | ****************************************************************************/ | 21 | ****************************************************************************/ |
22 | #include <sys/types.h> /* off_t */ | ||
23 | |||
24 | #include "config.h" | 22 | #include "config.h" |
25 | #include "system.h" | 23 | #include "system.h" |
26 | #include "cpu.h" | ||
27 | #include "string.h" | ||
28 | #include "lcd.h" | 24 | #include "lcd.h" |
29 | #include "kernel.h" | ||
30 | #include "lcd-target.h" | 25 | #include "lcd-target.h" |
31 | 26 | ||
32 | #define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)]) | 27 | extern void lcd_set_active(bool active); |
33 | 28 | ||
34 | static bool lcd_on = true; | ||
35 | #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) | 29 | #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) |
36 | static bool lcd_powered = true; | 30 | static bool lcd_powered = true; |
37 | #endif | 31 | #endif |
38 | static unsigned lcd_yuv_options = 0; | ||
39 | |||
40 | /* Copies a rectangle from one framebuffer to another. Can be used in | ||
41 | single transfer mode with width = num pixels, and height = 1 which | ||
42 | allows a full-width rectangle to be copied more efficiently. */ | ||
43 | extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src, | ||
44 | int width, int height); | ||
45 | |||
46 | #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) | ||
47 | bool lcd_active(void) | ||
48 | { | ||
49 | return lcd_on; | ||
50 | } | ||
51 | #endif | ||
52 | 32 | ||
53 | static unsigned int LCDBANK(unsigned int address) | 33 | static unsigned int LCDBANK(unsigned int address) |
54 | { | 34 | { |
@@ -281,7 +261,7 @@ void lcd_sleep(void) | |||
281 | if (lcd_powered) | 261 | if (lcd_powered) |
282 | { | 262 | { |
283 | /* "not powered" implies "disabled" */ | 263 | /* "not powered" implies "disabled" */ |
284 | if (lcd_on) | 264 | if (!lcd_active()) |
285 | lcd_enable(false); | 265 | lcd_enable(false); |
286 | 266 | ||
287 | LCD_SPI_powerdown(); | 267 | LCD_SPI_powerdown(); |
@@ -303,7 +283,7 @@ static void LCD_SPI_powerup(void) | |||
303 | 283 | ||
304 | void lcd_enable(bool state) | 284 | void lcd_enable(bool state) |
305 | { | 285 | { |
306 | if (state == lcd_on) | 286 | if (state == lcd_active()) |
307 | return; | 287 | return; |
308 | 288 | ||
309 | if(state) | 289 | if(state) |
@@ -317,20 +297,20 @@ void lcd_enable(bool state) | |||
317 | sleep(HZ/5); | 297 | sleep(HZ/5); |
318 | } | 298 | } |
319 | 299 | ||
320 | lcd_on = true; | 300 | lcd_set_active(true); |
321 | lcd_update(); | 301 | lcd_update(); |
322 | send_event(LCD_EVENT_ACTIVATION, NULL); | 302 | send_event(LCD_EVENT_ACTIVATION, NULL); |
323 | } | 303 | } |
324 | else | 304 | else |
325 | { | 305 | { |
326 | lcd_on = false; | 306 | lcd_set_active(false); |
327 | } | 307 | } |
328 | } | 308 | } |
329 | #endif | 309 | #endif |
330 | 310 | ||
331 | #ifdef GIGABEAT_F | 311 | #ifdef GIGABEAT_F |
332 | void lcd_set_flip(bool yesno) { | 312 | void lcd_set_flip(bool yesno) { |
333 | if (!lcd_on) | 313 | if (!lcd_active()) |
334 | return; | 314 | return; |
335 | 315 | ||
336 | LCD_SPI_start(); | 316 | LCD_SPI_start(); |
@@ -351,7 +331,7 @@ int lcd_default_contrast(void) | |||
351 | } | 331 | } |
352 | 332 | ||
353 | void lcd_set_contrast(int val) { | 333 | void lcd_set_contrast(int val) { |
354 | if (!lcd_on) | 334 | if (!lcd_active()) |
355 | return; | 335 | return; |
356 | 336 | ||
357 | LCD_SPI_start(); | 337 | LCD_SPI_start(); |
@@ -360,7 +340,7 @@ void lcd_set_contrast(int val) { | |||
360 | } | 340 | } |
361 | 341 | ||
362 | void lcd_set_invert_display(bool yesno) { | 342 | void lcd_set_invert_display(bool yesno) { |
363 | if (!lcd_on) | 343 | if (!lcd_active()) |
364 | return; | 344 | return; |
365 | 345 | ||
366 | LCD_SPI_start(); | 346 | LCD_SPI_start(); |
@@ -399,125 +379,3 @@ void lcd_set_invert_display(bool yesno) | |||
399 | } | 379 | } |
400 | 380 | ||
401 | #endif | 381 | #endif |
402 | |||
403 | /* Update a fraction of the display. */ | ||
404 | void lcd_update_rect(int x, int y, int width, int height) | ||
405 | { | ||
406 | fb_data *dst, *src; | ||
407 | |||
408 | if (!lcd_on) | ||
409 | return; | ||
410 | |||
411 | if (x + width > LCD_WIDTH) | ||
412 | width = LCD_WIDTH - x; /* Clip right */ | ||
413 | if (x < 0) | ||
414 | width += x, x = 0; /* Clip left */ | ||
415 | if (width <= 0) | ||
416 | return; /* nothing left to do */ | ||
417 | |||
418 | if (y + height > LCD_HEIGHT) | ||
419 | height = LCD_HEIGHT - y; /* Clip bottom */ | ||
420 | if (y < 0) | ||
421 | height += y, y = 0; /* Clip top */ | ||
422 | if (height <= 0) | ||
423 | return; /* nothing left to do */ | ||
424 | |||
425 | /* TODO: It may be faster to swap the addresses of lcd_driver_framebuffer | ||
426 | * and lcd_framebuffer */ | ||
427 | dst = (fb_data *)FRAME + LCD_WIDTH*y + x; | ||
428 | src = &lcd_framebuffer[y][x]; | ||
429 | |||
430 | /* Copy part of the Rockbox framebuffer to the second framebuffer */ | ||
431 | if (width < LCD_WIDTH) | ||
432 | { | ||
433 | /* Not full width - do line-by-line */ | ||
434 | lcd_copy_buffer_rect(dst, src, width, height); | ||
435 | } | ||
436 | else | ||
437 | { | ||
438 | /* Full width - copy as one line */ | ||
439 | lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); | ||
440 | } | ||
441 | } | ||
442 | |||
443 | /* Update the display. | ||
444 | This must be called after all other LCD functions that change the display. */ | ||
445 | void lcd_update(void) | ||
446 | { | ||
447 | if (!lcd_on) | ||
448 | return; | ||
449 | |||
450 | lcd_copy_buffer_rect((fb_data *)FRAME, &lcd_framebuffer[0][0], | ||
451 | LCD_WIDTH*LCD_HEIGHT, 1); | ||
452 | } | ||
453 | |||
454 | void lcd_yuv_set_options(unsigned options) | ||
455 | { | ||
456 | lcd_yuv_options = options; | ||
457 | } | ||
458 | |||
459 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
460 | extern void lcd_write_yuv420_lines(fb_data *dst, | ||
461 | unsigned char const * const src[3], | ||
462 | int width, | ||
463 | int stride); | ||
464 | extern void lcd_write_yuv420_lines_odither(fb_data *dst, | ||
465 | unsigned char const * const src[3], | ||
466 | int width, | ||
467 | int stride, | ||
468 | int x_screen, /* To align dither pattern */ | ||
469 | int y_screen); | ||
470 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
471 | /* For the Gigabeat - show it rotated */ | ||
472 | /* So the LCD_WIDTH is now the height */ | ||
473 | void lcd_blit_yuv(unsigned char * const src[3], | ||
474 | int src_x, int src_y, int stride, | ||
475 | int x, int y, int width, int height) | ||
476 | { | ||
477 | /* Caches for chroma data so it only need be recaculated every other | ||
478 | line */ | ||
479 | unsigned char const * yuv_src[3]; | ||
480 | off_t z; | ||
481 | |||
482 | if (!lcd_on) | ||
483 | return; | ||
484 | |||
485 | /* Sorry, but width and height must be >= 2 or else */ | ||
486 | width &= ~1; | ||
487 | height >>= 1; | ||
488 | |||
489 | y = LCD_WIDTH - 1 - y; | ||
490 | fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + y; | ||
491 | |||
492 | z = stride*src_y; | ||
493 | yuv_src[0] = src[0] + z + src_x; | ||
494 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
495 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
496 | |||
497 | if (lcd_yuv_options & LCD_YUV_DITHER) | ||
498 | { | ||
499 | do | ||
500 | { | ||
501 | lcd_write_yuv420_lines_odither(dst, yuv_src, width, stride, y, x); | ||
502 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
503 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
504 | yuv_src[2] += stride >> 1; | ||
505 | dst -= 2; | ||
506 | y -= 2; | ||
507 | } | ||
508 | while (--height > 0); | ||
509 | } | ||
510 | else | ||
511 | { | ||
512 | do | ||
513 | { | ||
514 | lcd_write_yuv420_lines(dst, yuv_src, width, stride); | ||
515 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
516 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
517 | yuv_src[2] += stride >> 1; | ||
518 | dst -= 2; | ||
519 | } | ||
520 | while (--height > 0); | ||
521 | } | ||
522 | } | ||
523 | |||
diff --git a/firmware/target/arm/s3c2440/mini2440/lcd-target.h b/firmware/target/arm/s3c2440/mini2440/lcd-target.h index b2882e2390..97643f8163 100644 --- a/firmware/target/arm/s3c2440/mini2440/lcd-target.h +++ b/firmware/target/arm/s3c2440/mini2440/lcd-target.h | |||
@@ -18,8 +18,10 @@ | |||
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #ifndef LCD_TARGET_H | ||
22 | #define LCD_TARGET_H | ||
21 | 23 | ||
22 | extern void lcd_enable(bool state); | 24 | #define LCD_FRAMEBUF_ADDR(col, row) ((fb_data *)FRAME + (row)*LCD_WIDTH + (col)) |
23 | 25 | ||
24 | /* Setup for Mini2440, 3.5" TFT LCD Touchscreen */ | 26 | /* Setup for Mini2440, 3.5" TFT LCD Touchscreen */ |
25 | 27 | ||
@@ -41,3 +43,5 @@ extern void lcd_enable(bool state); | |||
41 | 43 | ||
42 | /* Config values for LCDCON4 */ | 44 | /* Config values for LCDCON4 */ |
43 | #define LCD_HSYNC_LEN 4 | 45 | #define LCD_HSYNC_LEN 4 |
46 | |||
47 | #endif /* LCD_TARGET_H */ | ||
diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c index 0f9ca9b046..87765802c3 100644 --- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | |||
@@ -22,17 +22,15 @@ | |||
22 | * KIND, either express or implied. | 22 | * KIND, either express or implied. |
23 | * | 23 | * |
24 | ****************************************************************************/ | 24 | ****************************************************************************/ |
25 | #include <sys/types.h> /* off_t */ | 25 | #include "config.h" |
26 | #include <string.h> | ||
27 | #include "cpu.h" | ||
28 | #include "system.h" | 26 | #include "system.h" |
29 | #include "backlight-target.h" | ||
30 | #include "lcd.h" | 27 | #include "lcd.h" |
28 | #include "lcd-target.h" | ||
29 | |||
30 | extern void lcd_set_active(bool active); | ||
31 | 31 | ||
32 | /* Power and display status */ | 32 | /* Power and display status */ |
33 | static bool power_on = false; /* Is the power turned on? */ | 33 | static bool power_on = false; /* Is the power turned on? */ |
34 | static bool display_on SHAREDBSS_ATTR = false; /* Is the display turned on? */ | ||
35 | static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0; | ||
36 | 34 | ||
37 | /* Reverse Flag */ | 35 | /* Reverse Flag */ |
38 | #define R_DISP_CONTROL_NORMAL 0x0004 | 36 | #define R_DISP_CONTROL_NORMAL 0x0004 |
@@ -112,7 +110,7 @@ static unsigned short r_drv_output_control = R_DRV_OUTPUT_CONTROL_NORMAL; | |||
112 | /* We don't know how to receive a DMA finished signal from the LCD controller. | 110 | /* We don't know how to receive a DMA finished signal from the LCD controller. |
113 | * To avoid problems with flickering, we double-buffer the framebuffer. | 111 | * To avoid problems with flickering, we double-buffer the framebuffer. |
114 | * Align as in lcd-16bit.c and not cached. */ | 112 | * Align as in lcd-16bit.c and not cached. */ |
115 | static fb_data lcd_driver_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] | 113 | fb_data lcd_driver_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] |
116 | __attribute__((aligned(16))) NOCACHEBSS_ATTR; | 114 | __attribute__((aligned(16))) NOCACHEBSS_ATTR; |
117 | 115 | ||
118 | #ifdef BOOTLOADER | 116 | #ifdef BOOTLOADER |
@@ -310,21 +308,16 @@ static void lcd_display_on(void) | |||
310 | lcd_send_msg(0x70, R_RAM_WRITE_DATA); | 308 | lcd_send_msg(0x70, R_RAM_WRITE_DATA); |
311 | 309 | ||
312 | /* tell that we're on now */ | 310 | /* tell that we're on now */ |
313 | display_on = true; | 311 | lcd_set_active(true); |
314 | } | 312 | } |
315 | 313 | ||
316 | 314 | ||
317 | #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) | 315 | #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) |
318 | bool lcd_active(void) | ||
319 | { | ||
320 | return display_on; | ||
321 | } | ||
322 | |||
323 | /* Turn off visible display operations */ | 316 | /* Turn off visible display operations */ |
324 | static void lcd_display_off(void) | 317 | static void lcd_display_off(void) |
325 | { | 318 | { |
326 | /* block drawing operations and changing of first */ | 319 | /* block drawing operations and changing of first */ |
327 | display_on = false; | 320 | lcd_set_active(false); |
328 | 321 | ||
329 | /* NO2-0=01, SDT1-0=00, EQ1-0=00, DIV1-0=00, RTN3-0=0000 */ | 322 | /* NO2-0=01, SDT1-0=00, EQ1-0=00, DIV1-0=00, RTN3-0=0000 */ |
330 | lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x4000); | 323 | lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x4000); |
@@ -428,7 +421,7 @@ void lcd_init_device(void) | |||
428 | LCD_FB_BASE_REG = (long)lcd_driver_framebuffer; | 421 | LCD_FB_BASE_REG = (long)lcd_driver_framebuffer; |
429 | 422 | ||
430 | power_on = true; | 423 | power_on = true; |
431 | display_on = true; | 424 | lcd_set_active(true); |
432 | 425 | ||
433 | lcd_set_invert_display(false); | 426 | lcd_set_invert_display(false); |
434 | lcd_set_flip(false); | 427 | lcd_set_flip(false); |
@@ -440,7 +433,7 @@ void lcd_init_device(void) | |||
440 | #if defined(HAVE_LCD_ENABLE) | 433 | #if defined(HAVE_LCD_ENABLE) |
441 | void lcd_enable(bool on) | 434 | void lcd_enable(bool on) |
442 | { | 435 | { |
443 | if (on == display_on) | 436 | if (on == lcd_active()) |
444 | return; | 437 | return; |
445 | 438 | ||
446 | if (on) | 439 | if (on) |
@@ -471,7 +464,7 @@ void lcd_sleep(void) | |||
471 | if (power_on) | 464 | if (power_on) |
472 | { | 465 | { |
473 | /* Turn off display */ | 466 | /* Turn off display */ |
474 | if (display_on) | 467 | if (lcd_active()) |
475 | lcd_display_off(); | 468 | lcd_display_off(); |
476 | 469 | ||
477 | power_on = false; | 470 | power_on = false; |
@@ -483,59 +476,6 @@ void lcd_sleep(void) | |||
483 | } | 476 | } |
484 | #endif | 477 | #endif |
485 | 478 | ||
486 | /* Copies a rectangle from one framebuffer to another. Can be used in | ||
487 | single transfer mode with width = num pixels, and height = 1 which | ||
488 | allows a full-width rectangle to be copied more efficiently. */ | ||
489 | extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src, | ||
490 | int width, int height); | ||
491 | void lcd_update_rect(int x, int y, int width, int height) | ||
492 | { | ||
493 | fb_data *dst, *src; | ||
494 | |||
495 | if (!display_on) | ||
496 | return; | ||
497 | |||
498 | if (x + width > LCD_WIDTH) | ||
499 | width = LCD_WIDTH - x; /* Clip right */ | ||
500 | if (x < 0) | ||
501 | width += x, x = 0; /* Clip left */ | ||
502 | if (width <= 0) | ||
503 | return; /* nothing left to do */ | ||
504 | |||
505 | if (y + height > LCD_HEIGHT) | ||
506 | height = LCD_HEIGHT - y; /* Clip bottom */ | ||
507 | if (y < 0) | ||
508 | height += y, y = 0; /* Clip top */ | ||
509 | if (height <= 0) | ||
510 | return; /* nothing left to do */ | ||
511 | |||
512 | dst = &lcd_driver_framebuffer[y][x]; | ||
513 | src = &lcd_framebuffer[y][x]; | ||
514 | |||
515 | /* Copy part of the Rockbox framebuffer to the second framebuffer */ | ||
516 | if (width < LCD_WIDTH) | ||
517 | { | ||
518 | /* Not full width - do line-by-line */ | ||
519 | lcd_copy_buffer_rect(dst, src, width, height); | ||
520 | } | ||
521 | else | ||
522 | { | ||
523 | /* Full width - copy as one line */ | ||
524 | lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); | ||
525 | } | ||
526 | } | ||
527 | |||
528 | void lcd_update(void) | ||
529 | { | ||
530 | if (!display_on) | ||
531 | return; | ||
532 | |||
533 | /* Copy the Rockbox framebuffer to the second framebuffer */ | ||
534 | lcd_copy_buffer_rect(&lcd_driver_framebuffer[0][0], | ||
535 | &lcd_framebuffer[0][0], LCD_WIDTH*LCD_HEIGHT, 1); | ||
536 | } | ||
537 | |||
538 | |||
539 | /*** hardware configuration ***/ | 479 | /*** hardware configuration ***/ |
540 | 480 | ||
541 | void lcd_set_contrast(int val) | 481 | void lcd_set_contrast(int val) |
@@ -558,7 +498,7 @@ void lcd_set_invert_display(bool yesno) | |||
558 | r_disp_control_rev = yesno ? R_DISP_CONTROL_REV : | 498 | r_disp_control_rev = yesno ? R_DISP_CONTROL_REV : |
559 | R_DISP_CONTROL_NORMAL; | 499 | R_DISP_CONTROL_NORMAL; |
560 | 500 | ||
561 | if (display_on) | 501 | if (lcd_active()) |
562 | { | 502 | { |
563 | /* PT1-0=00, VLE2-1=00, SPT=0, IB6(??)=1, GON=1, CL=0, | 503 | /* PT1-0=00, VLE2-1=00, SPT=0, IB6(??)=1, GON=1, CL=0, |
564 | DTE=1, REV=x, D1-0=11 */ | 504 | DTE=1, REV=x, D1-0=11 */ |
@@ -602,73 +542,3 @@ void lcd_set_flip(bool yesno) | |||
602 | LCD_REG_6 |= 1; /* Restart DMA */ | 542 | LCD_REG_6 |= 1; /* Restart DMA */ |
603 | } | 543 | } |
604 | } | 544 | } |
605 | |||
606 | /* Blitting functions */ | ||
607 | |||
608 | void lcd_yuv_set_options(unsigned options) | ||
609 | { | ||
610 | lcd_yuv_options = options; | ||
611 | } | ||
612 | |||
613 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
614 | extern void lcd_write_yuv420_lines(fb_data *dst, | ||
615 | unsigned char const * const src[3], | ||
616 | int width, | ||
617 | int stride); | ||
618 | extern void lcd_write_yuv420_lines_odither(fb_data *dst, | ||
619 | unsigned char const * const src[3], | ||
620 | int width, | ||
621 | int stride, | ||
622 | int x_screen, /* To align dither pattern */ | ||
623 | int y_screen); | ||
624 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
625 | /* For the e200 - show it rotated */ | ||
626 | /* So the LCD_WIDTH is now the height */ | ||
627 | void lcd_blit_yuv(unsigned char * const src[3], | ||
628 | int src_x, int src_y, int stride, | ||
629 | int x, int y, int width, int height) | ||
630 | { | ||
631 | unsigned char const * yuv_src[3]; | ||
632 | off_t z; | ||
633 | |||
634 | if (!display_on) | ||
635 | return; | ||
636 | |||
637 | /* Sorry, but width and height must be >= 2 or else */ | ||
638 | width &= ~1; | ||
639 | height >>= 1; | ||
640 | |||
641 | y = LCD_WIDTH - 1 - y; | ||
642 | fb_data *dst = &lcd_driver_framebuffer[x][y]; | ||
643 | |||
644 | z = stride*src_y; | ||
645 | yuv_src[0] = src[0] + z + src_x; | ||
646 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
647 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
648 | |||
649 | if (lcd_yuv_options & LCD_YUV_DITHER) | ||
650 | { | ||
651 | do | ||
652 | { | ||
653 | lcd_write_yuv420_lines_odither(dst, yuv_src, width, stride, y, x); | ||
654 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
655 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
656 | yuv_src[2] += stride >> 1; | ||
657 | dst -= 2; | ||
658 | y -= 2; | ||
659 | } | ||
660 | while (--height > 0); | ||
661 | } | ||
662 | else | ||
663 | { | ||
664 | do | ||
665 | { | ||
666 | lcd_write_yuv420_lines(dst, yuv_src, width, stride); | ||
667 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
668 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
669 | yuv_src[2] += stride >> 1; | ||
670 | dst -= 2; | ||
671 | } | ||
672 | while (--height > 0); | ||
673 | } | ||
674 | } | ||
diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-target.h b/firmware/target/arm/sandisk/sansa-e200/lcd-target.h new file mode 100644 index 0000000000..e589dce78c --- /dev/null +++ b/firmware/target/arm/sandisk/sansa-e200/lcd-target.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2011 Michael Sevakis | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef LCD_TARGET_H | ||
22 | #define LCD_TARGET_H | ||
23 | |||
24 | extern fb_data lcd_driver_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]; | ||
25 | |||
26 | #define LCD_FRAMEBUF_ADDR(col, row) (&lcd_driver_framebuffer[row][col]) | ||
27 | |||
28 | #endif /* LCD_TARGET_H */ | ||