summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-12-16 23:40:39 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-12-16 23:40:39 +0000
commit95e6043d5e256df72c20db39c3be59a3ba977b19 (patch)
tree20a86cd626c43e92436459b6a408c4a13f4c21ef
parent13b2f5381310bc4e58d34f8dac0c8b9bdbd736d2 (diff)
downloadrockbox-95e6043d5e256df72c20db39c3be59a3ba977b19.tar.gz
rockbox-95e6043d5e256df72c20db39c3be59a3ba977b19.zip
Convert remaining memframe LCDs that can be convert to common code.
Massage the way it interfaces a bit to make things more flexible. The chroma_buf scheme on Sansa Connect and Creative ZVx calling the lcd_write_yuv420_lines implementation in lcd-as-memframe.S with five params with a chroma buffer that the function can't use wouldn't work anyway so just have them use the stock implementation (really, how was that working?). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31335 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/SOURCES5
-rw-r--r--firmware/drivers/lcd-memframe.c73
-rw-r--r--firmware/export/lcd.h9
-rw-r--r--firmware/target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c87
-rw-r--r--firmware/target/arm/imx233/sansa-fuzeplus/lcd-target.h30
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/lcd-gigabeat-s.c17
-rw-r--r--firmware/target/arm/s3c2440/lcd-s3c2440.c30
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/lcd-e200.c19
-rw-r--r--firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c147
-rw-r--r--firmware/target/arm/tcc780x/cowond2/lcd-target.h28
-rw-r--r--firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c68
-rw-r--r--firmware/target/arm/tms320dm320/creative-zvm/lcd-target.h18
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c111
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h8
14 files changed, 197 insertions, 453 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 7f9f3319ad..85e6fe3757 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -856,7 +856,6 @@ target/arm/sandisk/sansa-c200/powermgmt-c200.c
856#endif /* SANSA_C200 */ 856#endif /* SANSA_C200 */
857 857
858#ifdef SANSA_VIEW 858#ifdef SANSA_VIEW
859target/arm/lcd-as-memframe.S
860target/arm/sandisk/sansa-view/backlight-view.c 859target/arm/sandisk/sansa-view/backlight-view.c
861target/arm/sandisk/sansa-view/adc-view.c 860target/arm/sandisk/sansa-view/adc-view.c
862target/arm/sandisk/sansa-view/power-view.c 861target/arm/sandisk/sansa-view/power-view.c
@@ -1113,6 +1112,7 @@ target/arm/tms320dm320/mrobe-500/usb-mr500.c
1113#endif /* MROBE_500 */ 1112#endif /* MROBE_500 */
1114 1113
1115#ifdef CREATIVE_ZVx 1114#ifdef CREATIVE_ZVx
1115drivers/lcd-memframe.c
1116target/arm/lcd-as-memframe.S 1116target/arm/lcd-as-memframe.S
1117target/arm/tms320dm320/creative-zvm/adc-creativezvm.c 1117target/arm/tms320dm320/creative-zvm/adc-creativezvm.c
1118target/arm/tms320dm320/creative-zvm/ata-creativezvm.c 1118target/arm/tms320dm320/creative-zvm/ata-creativezvm.c
@@ -1126,6 +1126,7 @@ target/arm/tms320dm320/creative-zvm/usb-creativezvm.c
1126#endif /* CREATIVE_ZVx */ 1126#endif /* CREATIVE_ZVx */
1127 1127
1128#ifdef SANSA_CONNECT 1128#ifdef SANSA_CONNECT
1129drivers/lcd-memframe.c
1129target/arm/lcd-as-memframe.S 1130target/arm/lcd-as-memframe.S
1130target/arm/tms320dm320/sdmmc-dm320.c 1131target/arm/tms320dm320/sdmmc-dm320.c
1131target/arm/tms320dm320/sansa-connect/crt0-board.S 1132target/arm/tms320dm320/sansa-connect/crt0-board.S
@@ -1332,6 +1333,7 @@ target/arm/as3525/lcd-as-e200v2-fuze-fuzev2.S
1332#endif /* SANSA_FUZEV2 */ 1333#endif /* SANSA_FUZEV2 */
1333 1334
1334#ifdef SANSA_FUZEPLUS 1335#ifdef SANSA_FUZEPLUS
1336drivers/lcd-memframe.c
1335drivers/synaptics-rmi.c 1337drivers/synaptics-rmi.c
1336drivers/generic_i2c.c 1338drivers/generic_i2c.c
1337target/arm/lcd-as-memframe.S 1339target/arm/lcd-as-memframe.S
@@ -1370,6 +1372,7 @@ target/arm/tcc77x/iaudio7/audio-iaudio7.c
1370#endif /* IAUDIO_7 */ 1372#endif /* IAUDIO_7 */
1371 1373
1372#ifdef COWON_D2 1374#ifdef COWON_D2
1375drivers/lcd-memframe.c
1373drivers/nand_id.c 1376drivers/nand_id.c
1374drivers/pcf50606.c 1377drivers/pcf50606.c
1375drivers/pcf50635.c 1378drivers/pcf50635.c
diff --git a/firmware/drivers/lcd-memframe.c b/firmware/drivers/lcd-memframe.c
index 304f0a7e9e..dd878876bf 100644
--- a/firmware/drivers/lcd-memframe.c
+++ b/firmware/drivers/lcd-memframe.c
@@ -20,20 +20,15 @@
20 * KIND, either express or implied. 20 * KIND, either express or implied.
21 * 21 *
22 ****************************************************************************/ 22 ****************************************************************************/
23#include <sys/types.h> /* off_t */
24#include "config.h" 23#include "config.h"
25#include "system.h" 24#include "system.h"
26#include "lcd.h" 25#include "lcd.h"
27#include "lcd-target.h" 26#include "lcd-target.h"
28 27
29/*** Misc. functions ***/ 28/*** Misc. functions ***/
29bool lcd_on SHAREDBSS_ATTR = false;
30 30
31#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 31#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
32static bool lcd_on SHAREDBSS_ATTR = false; /* Is the display turned on? */
33#else
34static bool lcd_on SHAREDBSS_ATTR = true; /* Is the display turned on? */
35#endif
36
37bool lcd_active(void) 32bool lcd_active(void)
38{ 33{
39 return lcd_on; 34 return lcd_on;
@@ -45,6 +40,15 @@ void lcd_set_active(bool active)
45 lcd_on = active; 40 lcd_on = active;
46} 41}
47 42
43#else
44#define lcd_on true
45#endif
46
47#ifndef lcd_write_enabled
48#define lcd_write_enabled() lcd_on
49#endif
50
51
48/*** Blitting functions ***/ 52/*** Blitting functions ***/
49 53
50/* Copies a rectangle from one framebuffer to another. Can be used in 54/* Copies a rectangle from one framebuffer to another. Can be used in
@@ -53,23 +57,27 @@ void lcd_set_active(bool active)
53extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src, 57extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
54 int width, int height); 58 int width, int height);
55 59
60#ifndef LCD_OPTIMIZED_UPDATE
56/* Update the display. 61/* Update the display.
57 This must be called after all other LCD functions that change the display. */ 62 This must be called after all other LCD functions that change the display. */
58void lcd_update(void) 63void lcd_update(void)
59{ 64{
60 if (!lcd_on) 65 if (!lcd_write_enabled())
61 return; 66 return;
62 67
63 /* Copy the Rockbox framebuffer to the second framebuffer */ 68 /* Copy the Rockbox framebuffer to the second framebuffer */
64 lcd_copy_buffer_rect(LCD_FRAMEBUF_ADDR(0, 0), &lcd_framebuffer[0][0], 69 lcd_copy_buffer_rect(LCD_FRAMEBUF_ADDR(0, 0), &lcd_framebuffer[0][0],
65 LCD_WIDTH*LCD_HEIGHT, 1); 70 LCD_WIDTH*LCD_HEIGHT, 1);
66} 71}
72#endif /* LCD_OPTIMIZED_UPDATE */
67 73
74#ifndef LCD_OPTIMIZED_UPDATE_RECT
75/* Update a fraction of the display. */
68void lcd_update_rect(int x, int y, int width, int height) 76void lcd_update_rect(int x, int y, int width, int height)
69{ 77{
70 fb_data *dst, *src; 78 fb_data *dst, *src;
71 79
72 if (!lcd_on) 80 if (!lcd_write_enabled())
73 return; 81 return;
74 82
75 if (x + width > LCD_WIDTH) 83 if (x + width > LCD_WIDTH)
@@ -101,6 +109,7 @@ void lcd_update_rect(int x, int y, int width, int height)
101 lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); 109 lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1);
102 } 110 }
103} 111}
112#endif /* LCD_OPTIMIZED_UPDATE_RECT */
104 113
105 114
106/*** YUV functions ***/ 115/*** YUV functions ***/
@@ -124,27 +133,50 @@ void lcd_yuv_set_options(unsigned options)
124 lcd_yuv_options = options; 133 lcd_yuv_options = options;
125} 134}
126 135
127/* Performance function to blit a YUV bitmap directly to the LCD */ 136#ifndef LCD_OPTIMIZED_BLIT_YUV
128/* For the e200 - show it rotated */ 137/* Performance function to blit a YUV bitmap directly to the LCD
129/* So the LCD_WIDTH is now the height */ 138 * src_x, src_y, width and height should be even and within the LCD's
139 * boundaries.
140 *
141 * For portrait LCDs, show it rotated counterclockwise by 90 degrees
142 */
130void lcd_blit_yuv(unsigned char * const src[3], 143void lcd_blit_yuv(unsigned char * const src[3],
131 int src_x, int src_y, int stride, 144 int src_x, int src_y, int stride,
132 int x, int y, int width, int height) 145 int x, int y, int width, int height)
133{ 146{
134 unsigned char const * yuv_src[3]; 147 /* Macrofy the bits that change between orientations */
135 off_t z; 148#if CONFIG_ORIENTATION == SCREEN_PORTRAIT
149 #define LCD_FRAMEBUF_ADDR_ORIENTED(col, row) \
150 LCD_FRAMEBUF_ADDR(row, col)
151 #define lcd_write_yuv420_lines_odither_oriented(dst, src, w, s, col, row) \
152 lcd_write_yuv420_lines_odither(dst, src, w, s, row, col)
153 #define YUV_NEXTLINE() dst -= 2
154 #define YUV_DITHER_NEXTLINE() dst -= 2, y -= 2
155#else
156 #define LCD_FRAMEBUF_ADDR_ORIENTED(col, row) \
157 LCD_FRAMEBUF_ADDR(col, row)
158 #define lcd_write_yuv420_lines_odither_oriented(dst, src, w, s, col, row) \
159 lcd_write_yuv420_lines_odither(dst, src, w, s, col, row)
160 #define YUV_NEXTLINE() dst += 2*LCD_FBWIDTH
161 #define YUV_DITHER_NEXTLINE() dst += 2*LCD_FBWIDTH, y += 2
162#endif
136 163
137 if (!lcd_on) 164 if (!lcd_write_enabled())
138 return; 165 return;
139 166
140 /* Sorry, but width and height must be >= 2 or else */ 167 /* Sorry, but width and height must be >= 2 or else */
141 width &= ~1; 168 width &= ~1;
142 height >>= 1; 169 height >>= 1;
143 170
171#if CONFIG_ORIENTATION == SCREEN_PORTRAIT
172 /* Adjust portrait coordinates to make (0, 0) the upper right corner */
144 y = LCD_WIDTH - 1 - y; 173 y = LCD_WIDTH - 1 - y;
145 fb_data *dst = LCD_FRAMEBUF_ADDR(y, x); 174#endif
146 175
147 z = stride*src_y; 176 fb_data *dst = LCD_FRAMEBUF_ADDR_ORIENTED(x, y);
177 int z = stride*src_y;
178
179 unsigned char const * yuv_src[3];
148 yuv_src[0] = src[0] + z + src_x; 180 yuv_src[0] = src[0] + z + src_x;
149 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); 181 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
150 yuv_src[2] = src[2] + (yuv_src[1] - src[1]); 182 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
@@ -153,12 +185,12 @@ void lcd_blit_yuv(unsigned char * const src[3],
153 { 185 {
154 do 186 do
155 { 187 {
156 lcd_write_yuv420_lines_odither(dst, yuv_src, width, stride, y, x); 188 lcd_write_yuv420_lines_odither_oriented(dst, yuv_src, width,
189 stride, x, y);
157 yuv_src[0] += stride << 1; /* Skip down two luma lines */ 190 yuv_src[0] += stride << 1; /* Skip down two luma lines */
158 yuv_src[1] += stride >> 1; /* Skip down one chroma line */ 191 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
159 yuv_src[2] += stride >> 1; 192 yuv_src[2] += stride >> 1;
160 dst -= 2; 193 YUV_DITHER_NEXTLINE();
161 y -= 2;
162 } 194 }
163 while (--height > 0); 195 while (--height > 0);
164 } 196 }
@@ -170,8 +202,9 @@ void lcd_blit_yuv(unsigned char * const src[3],
170 yuv_src[0] += stride << 1; /* Skip down two luma lines */ 202 yuv_src[0] += stride << 1; /* Skip down two luma lines */
171 yuv_src[1] += stride >> 1; /* Skip down one chroma line */ 203 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
172 yuv_src[2] += stride >> 1; 204 yuv_src[2] += stride >> 1;
173 dst -= 2; 205 YUV_NEXTLINE();
174 } 206 }
175 while (--height > 0); 207 while (--height > 0);
176 } 208 }
177} 209}
210#endif /* LCD_OPTIMIZED_BLIT_YUV */
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 2d0123cfe3..abe5f74ee1 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -442,6 +442,15 @@ enum {
442}; 442};
443 443
444extern bool lcd_active(void); 444extern bool lcd_active(void);
445
446/* Set the active flag - to be called by target drivers only! */
447extern void lcd_set_active(bool active);
448#else
449/* NULL versions for no sleeping */
450static inline bool lcd_active(void)
451 { return true; }
452static inline void lcd_set_active(bool active)
453 { (void)active; }
445#endif 454#endif
446 455
447#ifdef HAVE_LCD_SHUTDOWN 456#ifdef HAVE_LCD_SHUTDOWN
diff --git a/firmware/target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c b/firmware/target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c
index 140e448630..8edc4b7758 100644
--- a/firmware/target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c
+++ b/firmware/target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c
@@ -29,18 +29,14 @@
29#include "pinctrl-imx233.h" 29#include "pinctrl-imx233.h"
30#include "logf.h" 30#include "logf.h"
31 31
32extern bool lcd_on; /* lcd-memframe.c */
33
32/* Copies a rectangle from one framebuffer to another. Can be used in 34/* Copies a rectangle from one framebuffer to another. Can be used in
33 single transfer mode with width = num pixels, and height = 1 which 35 single transfer mode with width = num pixels, and height = 1 which
34 allows a full-width rectangle to be copied more efficiently. */ 36 allows a full-width rectangle to be copied more efficiently. */
35extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src, 37extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
36 int width, int height); 38 int width, int height);
37 39
38static unsigned lcd_yuv_options = 0;
39
40#ifdef HAVE_LCD_ENABLE
41static bool lcd_on = true;
42#endif
43
44static enum lcd_kind_t 40static enum lcd_kind_t
45{ 41{
46 LCD_KIND_7783 = 0x7783, 42 LCD_KIND_7783 = 0x7783,
@@ -386,6 +382,8 @@ void lcd_init_device(void)
386 lcd_kind = LCD_KIND_7783; 382 lcd_kind = LCD_KIND_7783;
387 lcd_init_seq_7783(); break; 383 lcd_init_seq_7783(); break;
388 } 384 }
385
386 lcd_on = true;
389} 387}
390 388
391#ifdef HAVE_LCD_ENABLE 389#ifdef HAVE_LCD_ENABLE
@@ -469,6 +467,7 @@ void lcd_enable(bool enable)
469{ 467{
470 if(lcd_on == enable) 468 if(lcd_on == enable)
471 return; 469 return;
470
472 lcd_on = enable; 471 lcd_on = enable;
473 472
474 if(enable) 473 if(enable)
@@ -482,11 +481,6 @@ void lcd_enable(bool enable)
482 if(!enable) 481 if(!enable)
483 common_lcd_enable(false); 482 common_lcd_enable(false);
484} 483}
485
486bool lcd_active(void)
487{
488 return lcd_on;
489}
490#endif 484#endif
491 485
492void lcd_update(void) 486void lcd_update(void)
@@ -520,74 +514,3 @@ void lcd_update_rect(int x, int y, int width, int height)
520 (void) height; 514 (void) height;
521 lcd_update(); 515 lcd_update();
522} 516}
523
524void lcd_yuv_set_options(unsigned options)
525{
526 lcd_yuv_options = options;
527}
528
529/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
530extern void lcd_write_yuv420_lines(fb_data *dst,
531 unsigned char const * const src[3],
532 int width,
533 int stride);
534extern void lcd_write_yuv420_lines_odither(fb_data *dst,
535 unsigned char const * const src[3],
536 int width,
537 int stride,
538 int x_screen, /* To align dither pattern */
539 int y_screen);
540/* Performance function to blit a YUV bitmap directly to the LCD */
541/* So the LCD_WIDTH is now the height */
542void lcd_blit_yuv(unsigned char * const src[3],
543 int src_x, int src_y, int stride,
544 int x, int y, int width, int height)
545{
546 /* Caches for chroma data so it only need be recaculated every other
547 line */
548 unsigned char const * yuv_src[3];
549 off_t z;
550
551#ifdef HAVE_LCD_ENABLE
552 if (!lcd_on)
553 return;
554#endif
555
556 /* Sorry, but width and height must be >= 2 or else */
557 width &= ~1;
558 height >>= 1;
559
560 y = LCD_WIDTH - 1 - y;
561 fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + y;
562
563 z = stride*src_y;
564 yuv_src[0] = src[0] + z + src_x;
565 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
566 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
567
568 if (lcd_yuv_options & LCD_YUV_DITHER)
569 {
570 do
571 {
572 lcd_write_yuv420_lines_odither(dst, yuv_src, width, stride, y, x);
573 yuv_src[0] += stride << 1; /* Skip down two luma lines */
574 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
575 yuv_src[2] += stride >> 1;
576 dst -= 2;
577 y -= 2;
578 }
579 while (--height > 0);
580 }
581 else
582 {
583 do
584 {
585 lcd_write_yuv420_lines(dst, yuv_src, width, stride);
586 yuv_src[0] += stride << 1; /* Skip down two luma lines */
587 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
588 yuv_src[2] += stride >> 1;
589 dst -= 2;
590 }
591 while (--height > 0);
592 }
593}
diff --git a/firmware/target/arm/imx233/sansa-fuzeplus/lcd-target.h b/firmware/target/arm/imx233/sansa-fuzeplus/lcd-target.h
new file mode 100644
index 0000000000..fe65b916a3
--- /dev/null
+++ b/firmware/target/arm/imx233/sansa-fuzeplus/lcd-target.h
@@ -0,0 +1,30 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2011 by Amaury Pouly
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#define LCD_FRAMEBUF_ADDR(col, row) ((fb_data *)FRAME + (row)*LCD_WIDTH + (col))
25
26/* Not really optimized, but are unusual */
27#define LCD_OPTIMIZED_UPDATE
28#define LCD_OPTIMIZED_UPDATE_RECT
29
30#endif /* LCD_TARGET_H */
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 1d27716d2a..f0a2764851 100644
--- a/firmware/target/arm/imx31/gigabeat-s/lcd-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/lcd-gigabeat-s.c
@@ -29,10 +29,9 @@
29#include "spi-imx31.h" 29#include "spi-imx31.h"
30#include "mc13783.h" 30#include "mc13783.h"
31 31
32extern void lcd_set_active(bool active);
33
34#define MAIN_LCD_IDMAC_CHANNEL 14 32#define MAIN_LCD_IDMAC_CHANNEL 14
35 33
34extern bool lcd_on; /* lcd-memframe.c */
36static bool lcd_powered = true; 35static bool lcd_powered = true;
37 36
38/* Settings shadow regs */ 37/* Settings shadow regs */
@@ -171,6 +170,8 @@ void INIT_ATTR lcd_init_device(void)
171 IPU_IPU_IMA_ADDR = ((0x1 << 16) | (MAIN_LCD_IDMAC_CHANNEL << 4)) + (1 << 3); 170 IPU_IPU_IMA_ADDR = ((0x1 << 16) | (MAIN_LCD_IDMAC_CHANNEL << 4)) + (1 << 3);
172 IPU_IPU_IMA_DATA = FRAME_PHYS_ADDR; 171 IPU_IPU_IMA_DATA = FRAME_PHYS_ADDR;
173 172
173 lcd_on = true;
174
174 lcd_enable_interface(true); 175 lcd_enable_interface(true);
175 lcd_sync_settings(); 176 lcd_sync_settings();
176} 177}
@@ -188,7 +189,7 @@ void lcd_sleep(void)
188 189
189void lcd_enable(bool state) 190void lcd_enable(bool state)
190{ 191{
191 if (state == lcd_active()) 192 if (state == lcd_on)
192 return; 193 return;
193 194
194 if (state) 195 if (state)
@@ -198,13 +199,13 @@ void lcd_enable(bool state)
198 IPU_IDMAC_CHA_EN |= 1ul << MAIN_LCD_IDMAC_CHANNEL; 199 IPU_IDMAC_CHA_EN |= 1ul << MAIN_LCD_IDMAC_CHANNEL;
199 lcd_sync_settings(); 200 lcd_sync_settings();
200 sleep(HZ/50); 201 sleep(HZ/50);
201 lcd_set_active(true); 202 lcd_on = true;
202 lcd_update(); 203 lcd_update();
203 send_event(LCD_EVENT_ACTIVATION, NULL); 204 send_event(LCD_EVENT_ACTIVATION, NULL);
204 } 205 }
205 else 206 else
206 { 207 {
207 lcd_set_active(false); 208 lcd_on = false;
208 } 209 }
209} 210}
210 211
@@ -213,7 +214,7 @@ void lcd_set_contrast(int val)
213{ 214{
214 reg0x0b = val & 0x3f; 215 reg0x0b = val & 0x3f;
215 216
216 if (!lcd_active()) 217 if (!lcd_on)
217 return; 218 return;
218 219
219 lcd_write_reg(0x0b, reg0x0b); 220 lcd_write_reg(0x0b, reg0x0b);
@@ -230,7 +231,7 @@ void lcd_set_invert_display(bool yesno)
230{ 231{
231 reg0x27 = yesno ? 0x10 : 0x00; 232 reg0x27 = yesno ? 0x10 : 0x00;
232 233
233 if (!lcd_active()) 234 if (!lcd_on)
234 return; 235 return;
235 236
236 lcd_write_reg(0x27, reg0x27); 237 lcd_write_reg(0x27, reg0x27);
@@ -242,7 +243,7 @@ void lcd_set_flip(bool yesno)
242{ 243{
243 reg0x06 = yesno ? 0x02 : 0x04; 244 reg0x06 = yesno ? 0x02 : 0x04;
244 245
245 if (!lcd_active()) 246 if (!lcd_on)
246 return; 247 return;
247 248
248 lcd_write_reg(0x06, reg0x06); 249 lcd_write_reg(0x06, reg0x06);
diff --git a/firmware/target/arm/s3c2440/lcd-s3c2440.c b/firmware/target/arm/s3c2440/lcd-s3c2440.c
index 06b67c7535..1631e350f3 100644
--- a/firmware/target/arm/s3c2440/lcd-s3c2440.c
+++ b/firmware/target/arm/s3c2440/lcd-s3c2440.c
@@ -24,8 +24,7 @@
24#include "lcd.h" 24#include "lcd.h"
25#include "lcd-target.h" 25#include "lcd-target.h"
26 26
27extern bool lcd_active(void); 27extern bool lcd_on; /* lcd-memframe.c */
28extern void lcd_set_active(bool active);
29 28
30#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 29#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
31static bool lcd_powered = true; 30static bool lcd_powered = true;
@@ -242,6 +241,8 @@ void lcd_init_device(void)
242#else 241#else
243 LCD_CTRL_clock(true); 242 LCD_CTRL_clock(true);
244#endif 243#endif
244
245 lcd_on = true;
245} 246}
246 247
247#if defined(HAVE_LCD_SLEEP) 248#if defined(HAVE_LCD_SLEEP)
@@ -262,9 +263,7 @@ void lcd_sleep(void)
262 if (lcd_powered) 263 if (lcd_powered)
263 { 264 {
264 /* "not powered" implies "disabled" */ 265 /* "not powered" implies "disabled" */
265 if (!lcd_active()) 266 lcd_enable(false);
266 lcd_enable(false);
267
268 LCD_SPI_powerdown(); 267 LCD_SPI_powerdown();
269 } 268 }
270} 269}
@@ -284,7 +283,7 @@ static void LCD_SPI_powerup(void)
284 283
285void lcd_enable(bool state) 284void lcd_enable(bool state)
286{ 285{
287 if (state == lcd_active()) 286 if (state == lcd_on)
288 return; 287 return;
289 288
290 if(state) 289 if(state)
@@ -298,20 +297,21 @@ void lcd_enable(bool state)
298 sleep(HZ/5); 297 sleep(HZ/5);
299 } 298 }
300 299
301 lcd_set_active(true); 300 lcd_on = true;
302 lcd_update(); 301 lcd_update();
303 send_event(LCD_EVENT_ACTIVATION, NULL); 302 send_event(LCD_EVENT_ACTIVATION, NULL);
304 } 303 }
305 else 304 else
306 { 305 {
307 lcd_set_active(false); 306 lcd_on = false;
308 } 307 }
309} 308}
310#endif 309#endif
311 310
312#ifdef GIGABEAT_F 311#ifdef GIGABEAT_F
313void lcd_set_flip(bool yesno) { 312void lcd_set_flip(bool yesno)
314 if (!lcd_active()) 313{
314 if (!lcd_on)
315 return; 315 return;
316 316
317 LCD_SPI_start(); 317 LCD_SPI_start();
@@ -331,8 +331,9 @@ int lcd_default_contrast(void)
331 return DEFAULT_CONTRAST_SETTING; 331 return DEFAULT_CONTRAST_SETTING;
332} 332}
333 333
334void lcd_set_contrast(int val) { 334void lcd_set_contrast(int val)
335 if (!lcd_active()) 335{
336 if (!lcd_on)
336 return; 337 return;
337 338
338 LCD_SPI_start(); 339 LCD_SPI_start();
@@ -340,8 +341,9 @@ void lcd_set_contrast(int val) {
340 LCD_SPI_stop(); 341 LCD_SPI_stop();
341} 342}
342 343
343void lcd_set_invert_display(bool yesno) { 344void lcd_set_invert_display(bool yesno)
344 if (!lcd_active()) 345{
346 if (!lcd_on)
345 return; 347 return;
346 348
347 LCD_SPI_start(); 349 LCD_SPI_start();
diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
index b3c05fb48c..39ceb9b8e0 100644
--- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
@@ -27,11 +27,9 @@
27#include "lcd.h" 27#include "lcd.h"
28#include "lcd-target.h" 28#include "lcd-target.h"
29 29
30extern bool lcd_active(void);
31extern void lcd_set_active(bool active);
32
33/* Power and display status */ 30/* Power and display status */
34static bool power_on = false; /* Is the power turned on? */ 31extern bool lcd_on; /* lcd-memframe.c */
32static bool power_on = false; /* Is the power turned on? */
35 33
36/* Reverse Flag */ 34/* Reverse Flag */
37#define R_DISP_CONTROL_NORMAL 0x0004 35#define R_DISP_CONTROL_NORMAL 0x0004
@@ -309,7 +307,7 @@ static void lcd_display_on(void)
309 lcd_send_msg(0x70, R_RAM_WRITE_DATA); 307 lcd_send_msg(0x70, R_RAM_WRITE_DATA);
310 308
311 /* tell that we're on now */ 309 /* tell that we're on now */
312 lcd_set_active(true); 310 lcd_on = true;
313} 311}
314 312
315 313
@@ -318,7 +316,7 @@ static void lcd_display_on(void)
318static void lcd_display_off(void) 316static void lcd_display_off(void)
319{ 317{
320 /* block drawing operations and changing of first */ 318 /* block drawing operations and changing of first */
321 lcd_set_active(false); 319 lcd_on = false;
322 320
323 /* NO2-0=01, SDT1-0=00, EQ1-0=00, DIV1-0=00, RTN3-0=0000 */ 321 /* NO2-0=01, SDT1-0=00, EQ1-0=00, DIV1-0=00, RTN3-0=0000 */
324 lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x4000); 322 lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x4000);
@@ -422,7 +420,7 @@ void lcd_init_device(void)
422 LCD_FB_BASE_REG = (long)lcd_driver_framebuffer; 420 LCD_FB_BASE_REG = (long)lcd_driver_framebuffer;
423 421
424 power_on = true; 422 power_on = true;
425 lcd_set_active(true); 423 lcd_on = true;
426 424
427 lcd_set_invert_display(false); 425 lcd_set_invert_display(false);
428 lcd_set_flip(false); 426 lcd_set_flip(false);
@@ -434,7 +432,7 @@ void lcd_init_device(void)
434#if defined(HAVE_LCD_ENABLE) 432#if defined(HAVE_LCD_ENABLE)
435void lcd_enable(bool on) 433void lcd_enable(bool on)
436{ 434{
437 if (on == lcd_active()) 435 if (on == lcd_on)
438 return; 436 return;
439 437
440 if (on) 438 if (on)
@@ -465,9 +463,8 @@ void lcd_sleep(void)
465 if (power_on) 463 if (power_on)
466 { 464 {
467 /* Turn off display */ 465 /* Turn off display */
468 if (lcd_active()) 466 if (lcd_on)
469 lcd_display_off(); 467 lcd_display_off();
470
471 power_on = false; 468 power_on = false;
472 } 469 }
473 470
@@ -499,7 +496,7 @@ void lcd_set_invert_display(bool yesno)
499 r_disp_control_rev = yesno ? R_DISP_CONTROL_REV : 496 r_disp_control_rev = yesno ? R_DISP_CONTROL_REV :
500 R_DISP_CONTROL_NORMAL; 497 R_DISP_CONTROL_NORMAL;
501 498
502 if (lcd_active()) 499 if (lcd_on)
503 { 500 {
504 /* PT1-0=00, VLE2-1=00, SPT=0, IB6(??)=1, GON=1, CL=0, 501 /* PT1-0=00, VLE2-1=00, SPT=0, IB6(??)=1, GON=1, CL=0,
505 DTE=1, REV=x, D1-0=11 */ 502 DTE=1, REV=x, D1-0=11 */
diff --git a/firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c b/firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c
index ab50769983..b4c37b716c 100644
--- a/firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c
+++ b/firmware/target/arm/tcc780x/cowond2/lcd-cowond2.c
@@ -24,9 +24,12 @@
24#include "hwcompat.h" 24#include "hwcompat.h"
25#include "kernel.h" 25#include "kernel.h"
26#include "lcd.h" 26#include "lcd.h"
27#include "lcd-target.h"
27#include "system.h" 28#include "system.h"
28#include "cpu.h" 29#include "cpu.h"
29 30
31extern bool lcd_on; /* lcd-memframe.c */
32
30/* GPIO A pins for LCD panel SDI interface */ 33/* GPIO A pins for LCD panel SDI interface */
31 34
32#define LTV250QV_CS (1<<24) 35#define LTV250QV_CS (1<<24)
@@ -51,11 +54,6 @@
51#define LCDC_I1OFF (*(volatile unsigned long *)0xF00000A8) 54#define LCDC_I1OFF (*(volatile unsigned long *)0xF00000A8)
52#define LCDC_I1SCALE (*(volatile unsigned long *)0xF00000AC) 55#define LCDC_I1SCALE (*(volatile unsigned long *)0xF00000AC)
53 56
54/* Power and display status */
55static bool display_on = false; /* Is the display turned on? */
56
57static unsigned lcd_yuv_options = 0;
58
59/* Framebuffer copy as seen by the hardware */ 57/* Framebuffer copy as seen by the hardware */
60fb_data lcd_driver_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]; 58fb_data lcd_driver_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH];
61 59
@@ -180,13 +178,13 @@ static void lcd_display_on(void)
180 udelay(10000); 178 udelay(10000);
181 179
182 /* tell that we're on now */ 180 /* tell that we're on now */
183 display_on = true; 181 lcd_on = true;
184} 182}
185 183
186static void lcd_display_off(void) 184static void lcd_display_off(void)
187{ 185{
188 /* block drawing operations and changing of first */ 186 /* block drawing operations and changing of first */
189 display_on = false; 187 lcd_on = false;
190 188
191 /* LQV shutdown sequence */ 189 /* LQV shutdown sequence */
192 lcd_write_reg(9, 0x55); 190 lcd_write_reg(9, 0x55);
@@ -204,7 +202,7 @@ static void lcd_display_off(void)
204 202
205void lcd_enable(bool on) 203void lcd_enable(bool on)
206{ 204{
207 if (on == display_on) 205 if (on == lcd_on)
208 return; 206 return;
209 207
210 if (on) 208 if (on)
@@ -221,11 +219,6 @@ void lcd_enable(bool on)
221 } 219 }
222} 220}
223 221
224bool lcd_active(void)
225{
226 return display_on;
227}
228
229/* TODO: implement lcd_sleep() and separate out the power on/off functions */ 222/* TODO: implement lcd_sleep() and separate out the power on/off functions */
230 223
231void lcd_init_device(void) 224void lcd_init_device(void)
@@ -278,67 +271,6 @@ void lcd_init_device(void)
278 271
279 272
280/*** Update functions ***/ 273/*** Update functions ***/
281
282
283/* Copies a rectangle from one framebuffer to another. Can be used in
284 single transfer mode with width = num pixels, and height = 1 which
285 allows a full-width rectangle to be copied more efficiently. */
286extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
287 int width, int height);
288
289/* Update the display.
290 This must be called after all other LCD functions that change the display. */
291void lcd_update(void) ICODE_ATTR;
292void lcd_update(void)
293{
294 if (!display_on)
295 return;
296
297 lcd_copy_buffer_rect(&lcd_driver_framebuffer[0][0],
298 &lcd_framebuffer[0][0], LCD_WIDTH*LCD_HEIGHT, 1);
299}
300
301/* Update a fraction of the display. */
302void lcd_update_rect(int, int, int, int) ICODE_ATTR;
303void lcd_update_rect(int x, int y, int width, int height)
304{
305 fb_data *dst, *src;
306
307 if (!display_on)
308 return;
309
310 if (x + width > LCD_WIDTH)
311 width = LCD_WIDTH - x; /* Clip right */
312 if (x < 0)
313 width += x, x = 0; /* Clip left */
314 if (width <= 0)
315 return; /* nothing left to do */
316
317 if (y + height > LCD_HEIGHT)
318 height = LCD_HEIGHT - y; /* Clip bottom */
319 if (y < 0)
320 height += y, y = 0; /* Clip top */
321 if (height <= 0)
322 return; /* nothing left to do */
323
324 /* TODO: It may be faster to swap the addresses of lcd_driver_framebuffer
325 * and lcd_framebuffer */
326 dst = &lcd_driver_framebuffer[y][x];
327 src = &lcd_framebuffer[y][x];
328
329 /* Copy part of the Rockbox framebuffer to the second framebuffer */
330 if (width < LCD_WIDTH)
331 {
332 /* Not full width - do line-by-line */
333 lcd_copy_buffer_rect(dst, src, width, height);
334 }
335 else
336 {
337 /* Full width - copy as one line */
338 lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1);
339 }
340}
341
342void lcd_set_flip(bool yesno) 274void lcd_set_flip(bool yesno)
343{ 275{
344 // TODO 276 // TODO
@@ -350,70 +282,3 @@ void lcd_set_invert_display(bool yesno)
350 // TODO 282 // TODO
351 (void)yesno; 283 (void)yesno;
352} 284}
353
354void lcd_yuv_set_options(unsigned options)
355{
356 lcd_yuv_options = options;
357}
358
359/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
360extern void lcd_write_yuv420_lines(fb_data *dst,
361 unsigned char const * const src[3],
362 int width,
363 int stride);
364
365extern void lcd_write_yuv420_lines_odither(fb_data *dst,
366 unsigned char const * const src[3],
367 int width,
368 int stride,
369 int x_screen, /* To align dither pattern */
370 int y_screen);
371
372/* Performance function to blit a YUV bitmap directly to the LCD */
373void lcd_blit_yuv(unsigned char * const src[3],
374 int src_x, int src_y, int stride,
375 int x, int y, int width, int height)
376{
377 unsigned char const * yuv_src[3];
378 off_t z;
379
380 if (!display_on)
381 return;
382
383 /* Sorry, but width and height must be >= 2 or else */
384 width &= ~1;
385 height >>= 1;
386
387 fb_data *dst = &lcd_driver_framebuffer[y][x];
388
389 z = stride*src_y;
390 yuv_src[0] = src[0] + z + src_x;
391 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
392 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
393
394 if (lcd_yuv_options & LCD_YUV_DITHER)
395 {
396 do
397 {
398 lcd_write_yuv420_lines_odither(dst, yuv_src, width, stride, y, x);
399 yuv_src[0] += stride << 1; /* Skip down two luma lines */
400 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
401 yuv_src[2] += stride >> 1;
402 dst += 2*LCD_FBWIDTH;
403 y -= 2;
404 }
405 while (--height > 0);
406 }
407 else
408 {
409 do
410 {
411 lcd_write_yuv420_lines(dst, yuv_src, width, stride);
412 yuv_src[0] += stride << 1; /* Skip down two luma lines */
413 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
414 yuv_src[2] += stride >> 1;
415 dst += 2*LCD_FBWIDTH;
416 }
417 while (--height > 0);
418 }
419}
diff --git a/firmware/target/arm/tcc780x/cowond2/lcd-target.h b/firmware/target/arm/tcc780x/cowond2/lcd-target.h
new file mode 100644
index 0000000000..52caf34a45
--- /dev/null
+++ b/firmware/target/arm/tcc780x/cowond2/lcd-target.h
@@ -0,0 +1,28 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Rob Purchase
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
24extern 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 */
diff --git a/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c
index c92920337b..e6d9e034ed 100644
--- a/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c
+++ b/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c
@@ -33,7 +33,7 @@
33#include "ltv350qv.h" 33#include "ltv350qv.h"
34 34
35/* Power and display status */ 35/* Power and display status */
36static bool display_on = false; /* Is the display turned on? */ 36extern bool lcd_on; /* lcd-memframe.c */
37static bool direct_fb_access = false; /* Does the DM320 has direct access to the FB? */ 37static bool direct_fb_access = false; /* Does the DM320 has direct access to the FB? */
38 38
39/* Copies a rectangle from one framebuffer to another. Can be used in 39/* Copies a rectangle from one framebuffer to another. Can be used in
@@ -189,7 +189,7 @@ static void lcd_display_on(bool reset)
189 IO_VID_ENC_VMOD |= VENC_VMOD_VENC; 189 IO_VID_ENC_VMOD |= VENC_VMOD_VENC;
190 } 190 }
191 /* tell that we're on now */ 191 /* tell that we're on now */
192 display_on = true; 192 lcd_on = true;
193} 193}
194 194
195#ifdef HAVE_LCD_ENABLE 195#ifdef HAVE_LCD_ENABLE
@@ -224,14 +224,14 @@ static void lcd_display_off(void)
224 224
225 enable_venc(false); 225 enable_venc(false);
226 226
227 display_on = false; 227 lcd_on = false;
228} 228}
229 229
230void lcd_enable(bool on) 230void lcd_enable(bool on)
231{ 231{
232/* Disabled until properly working */ 232/* Disabled until properly working */
233return; 233return;
234 if (on == display_on) 234 if (on == lcd_on)
235 return; 235 return;
236 236
237 if (on) 237 if (on)
@@ -247,13 +247,6 @@ return;
247} 247}
248#endif 248#endif
249 249
250#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
251bool lcd_active(void)
252{
253 return display_on;
254}
255#endif
256
257void lcd_set_direct_fb(bool yes) 250void lcd_set_direct_fb(bool yes)
258{ 251{
259 unsigned int addr; 252 unsigned int addr;
@@ -323,7 +316,7 @@ void lcd_init_device(void)
323 DM320_REG(0x0864) = 0; /* ???? */ 316 DM320_REG(0x0864) = 0; /* ???? */
324 } 317 }
325 else 318 else
326 display_on = true; 319 lcd_on = true;
327 320
328 /* Based on lcd-mr500.c from Catalin Patulea */ 321 /* Based on lcd-mr500.c from Catalin Patulea */
329 /* Clear the Frame */ 322 /* Clear the Frame */
@@ -369,7 +362,7 @@ void lcd_update_rect(int x, int y, int width, int height)
369{ 362{
370 register fb_data *dst, *src; 363 register fb_data *dst, *src;
371 364
372 if (!display_on || direct_fb_access) 365 if (!lcd_on || direct_fb_access)
373 return; 366 return;
374 367
375 if (x + width > LCD_WIDTH) 368 if (x + width > LCD_WIDTH)
@@ -424,7 +417,7 @@ void lcd_update_rect(int x, int y, int width, int height)
424This must be called after all other LCD functions that change the display. */ 417This must be called after all other LCD functions that change the display. */
425void lcd_update(void) 418void lcd_update(void)
426{ 419{
427 if (!display_on || direct_fb_access) 420 if (!lcd_on || direct_fb_access)
428 return; 421 return;
429#if CONFIG_ORIENTATION == SCREEN_PORTRAIT 422#if CONFIG_ORIENTATION == SCREEN_PORTRAIT
430 lcd_copy_buffer_rect((fb_data *)FRAME, &lcd_framebuffer[0][0], 423 lcd_copy_buffer_rect((fb_data *)FRAME, &lcd_framebuffer[0][0],
@@ -433,50 +426,3 @@ void lcd_update(void)
433 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); 426 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
434#endif 427#endif
435} 428}
436
437/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
438extern void lcd_write_yuv420_lines(fb_data *dst,
439unsigned char chroma_buf[LCD_HEIGHT/2*3],
440unsigned char const * const src[3],
441int width,
442int stride);
443/* Performance function to blit a YUV bitmap directly to the LCD */
444/* For the Gigabeat - show it rotated */
445/* So the LCD_WIDTH is now the height */
446void lcd_blit_yuv(unsigned char * const src[3],
447 int src_x, int src_y, int stride,
448 int x, int y, int width, int height)
449{
450 /* Caches for chroma data so it only need be recalculated every other
451 line */
452 unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */
453 unsigned char const * yuv_src[3];
454 off_t z;
455
456 if (!display_on || direct_fb_access)
457 return;
458
459 /* Sorry, but width and height must be >= 2 or else */
460 width &= ~1;
461 height >>= 1;
462
463 fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
464
465 z = stride*src_y;
466 yuv_src[0] = src[0] + z + src_x;
467 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
468 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
469
470 do
471 {
472 lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width,
473 stride);
474
475 yuv_src[0] += stride << 1; /* Skip down two luma lines */
476 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
477 yuv_src[2] += stride >> 1;
478 dst -= 2;
479 }
480 while (--height > 0);
481}
482
diff --git a/firmware/target/arm/tms320dm320/creative-zvm/lcd-target.h b/firmware/target/arm/tms320dm320/creative-zvm/lcd-target.h
index 720aa0cf19..456f0e3cfe 100644
--- a/firmware/target/arm/tms320dm320/creative-zvm/lcd-target.h
+++ b/firmware/target/arm/tms320dm320/creative-zvm/lcd-target.h
@@ -19,12 +19,20 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#ifndef _LCD_TARGET_H_ 22#ifndef LCD_TARGET_H
23#define _LCD_TARGET_H_ 23#define LCD_TARGET_H
24
25extern void lcd_enable(bool state);
26 24
27void lcd_set_direct_fb(bool yes); 25void lcd_set_direct_fb(bool yes);
28bool lcd_get_direct_fb(void); 26bool lcd_get_direct_fb(void);
29 27
30#endif 28/* Direct FB access disables regular updates */
29#define lcd_write_enabled() \
30 ({ lcd_on && !lcd_get_direct_fb(); })
31
32/* Very strange functions */
33#define LCD_OPTIMIZED_UPDATE
34#define LCD_OPTIMIZED_UPDATE_RECT
35
36#define LCD_FRAMEBUF_ADDR(col, row) ((fb_data *)FRAME + (row)*LCD_WIDTH + (col))
37
38#endif /* LCD_TARGET_H */
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c
index 308b4297c2..ad417663fe 100644
--- a/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c
+++ b/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c
@@ -30,18 +30,7 @@
30#include "lcd-target.h" 30#include "lcd-target.h"
31#include "avr-sansaconnect.h" 31#include "avr-sansaconnect.h"
32 32
33/* Copies a rectangle from one framebuffer to another. Can be used in 33extern bool lcd_on; /* lcd-memframe.c */
34 single transfer mode with width = num pixels, and height = 1 which
35 allows a full-width rectangle to be copied more efficiently. */
36extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
37 int width, int height);
38
39static bool lcd_on = true;
40
41bool lcd_active(void)
42{
43 return lcd_on;
44}
45 34
46#if defined(HAVE_LCD_SLEEP) 35#if defined(HAVE_LCD_SLEEP)
47void lcd_sleep(void) 36void lcd_sleep(void)
@@ -49,6 +38,7 @@ void lcd_sleep(void)
49 if (lcd_on) 38 if (lcd_on)
50 { 39 {
51 lcd_on = false; 40 lcd_on = false;
41
52 avr_hid_lcm_sleep(); 42 avr_hid_lcm_sleep();
53 sleep(HZ/20); 43 sleep(HZ/20);
54 44
@@ -67,6 +57,7 @@ void lcd_awake(void)
67 if (!lcd_on) 57 if (!lcd_on)
68 { 58 {
69 lcd_on = true; 59 lcd_on = true;
60
70 /* enable video encoder clock */ 61 /* enable video encoder clock */
71 bitset16(&IO_CLK_MOD1, CLK_MOD1_VENC); 62 bitset16(&IO_CLK_MOD1, CLK_MOD1_VENC);
72 63
@@ -159,56 +150,7 @@ void lcd_init_device(void)
159 /* Enable Video Encoder - RGB666, custom timing */ 150 /* Enable Video Encoder - RGB666, custom timing */
160 IO_VID_ENC_VMOD = 0x2011; 151 IO_VID_ENC_VMOD = 0x2011;
161 avr_hid_lcm_wake(); 152 avr_hid_lcm_wake();
162} 153 lcd_on = true;
163
164/* Update a fraction of the display. */
165void lcd_update_rect(int x, int y, int width, int height)
166 __attribute__ ((section(".icode")));
167void lcd_update_rect(int x, int y, int width, int height)
168{
169 register fb_data *dst, *src;
170
171 if (!lcd_on)
172 return;
173
174 if ((width | height) < 0)
175 return; /* Nothing left to do */
176
177 if (x + width > LCD_WIDTH)
178 width = LCD_WIDTH - x; /* Clip right */
179 if (x < 0)
180 width += x, x = 0; /* Clip left */
181
182 if (y + height > LCD_HEIGHT)
183 height = LCD_HEIGHT - y; /* Clip bottom */
184 if (y < 0)
185 height += y, y = 0; /* Clip top */
186
187 dst = FRAME + LCD_WIDTH*y + x;
188 src = &lcd_framebuffer[y][x];
189
190 /* Copy part of the Rockbox framebuffer to the second framebuffer */
191 if (width < LCD_WIDTH)
192 {
193 /* Not full width - do line-by-line */
194 lcd_copy_buffer_rect(dst, src, width, height);
195 }
196 else
197 {
198 /* Full width - copy as one line */
199 lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1);
200 }
201}
202
203/* Update the display.
204 This must be called after all other LCD functions that change the display. */
205void lcd_update(void) __attribute__ ((section(".icode")));
206void lcd_update(void)
207{
208 if (!lcd_on)
209 return;
210
211 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
212} 154}
213 155
214void lcd_set_contrast(int val) { 156void lcd_set_contrast(int val) {
@@ -225,48 +167,3 @@ void lcd_set_flip(bool yesno) {
225 (void) yesno; 167 (void) yesno;
226 // TODO: 168 // TODO:
227} 169}
228
229/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
230extern void lcd_write_yuv420_lines(fb_data *dst,
231 unsigned char chroma_buf[LCD_HEIGHT/2*3],
232 unsigned char const * const src[3],
233 int width, int stride);
234
235/* Performance function to blit a YUV bitmap directly to the LCD */
236void lcd_blit_yuv(unsigned char * const src[3],
237 int src_x, int src_y, int stride,
238 int x, int y, int width, int height)
239{
240 /* Caches for chroma data so it only need be recalculated every other
241 line */
242 unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */
243 unsigned char const * yuv_src[3];
244 off_t z;
245
246 if (!lcd_on)
247 return;
248
249 /* Sorry, but width and height must be >= 2 or else */
250 width &= ~1;
251 height >>= 1;
252
253 fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
254
255 z = stride*src_y;
256 yuv_src[0] = src[0] + z + src_x;
257 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
258 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
259
260 do
261 {
262 lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width,
263 stride);
264
265 yuv_src[0] += stride << 1; /* Skip down two luma lines */
266 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
267 yuv_src[2] += stride >> 1;
268 dst -= 2;
269 }
270 while (--height > 0);
271}
272
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h b/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h
index da82c8fe7d..60d5df69c8 100644
--- a/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h
+++ b/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h
@@ -19,9 +19,11 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#ifndef _LCD_TARGET_H_ 22#ifndef LCD_TARGET_H
23#define _LCD_TARGET_H_ 23#define LCD_TARGET_H
24
25#define LCD_FRAMEBUF_ADDR(col, row) ((fb_data *)FRAME + (row)*LCD_WIDTH + (col))
24 26
25void lcd_awake(void); 27void lcd_awake(void);
26 28
27#endif 29#endif /* LCD_TARGET_H */