summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Wardell <rockbox@barrywardell.net>2006-09-09 19:02:18 +0000
committerBarry Wardell <rockbox@barrywardell.net>2006-09-09 19:02:18 +0000
commit24ca76ffec3e0d782f75ac1cca2c0b2c8b71f5db (patch)
treef8c8476949fed16e768fb193e9e0987c4dc2d580
parenta374ca96fbb7e0ea00dcc85382ee806a523373ac (diff)
downloadrockbox-24ca76ffec3e0d782f75ac1cca2c0b2c8b71f5db.tar.gz
rockbox-24ca76ffec3e0d782f75ac1cca2c0b2c8b71f5db.zip
H10 fixes: Split LCD driver up into two drivers, one for each LCD type. Improvements to 20GB LCD driver - support for enable/disable, contrast adjustment, make the update code clearer and ~4% faster, support for flipping, support for invert. Fix CPU frequency for both models. Fix default battery capacity for 5/6GB.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10910 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/settings.h8
-rw-r--r--firmware/SOURCES4
-rw-r--r--firmware/export/config-h10.h23
-rw-r--r--firmware/export/config-h10_5gb.h6
-rw-r--r--firmware/target/arm/iriver/h10/backlight-h10.c7
-rw-r--r--firmware/target/arm/iriver/h10/lcd-h10_20gb.c633
-rw-r--r--firmware/target/arm/iriver/h10/lcd-h10_5gb.c (renamed from firmware/target/arm/iriver/h10/lcd-h10.c)83
-rwxr-xr-xtools/configure2
8 files changed, 667 insertions, 99 deletions
diff --git a/apps/settings.h b/apps/settings.h
index 05f5dee382..b66e96b765 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -532,17 +532,15 @@ extern long lasttime;
532extern const char rec_base_directory[]; 532extern const char rec_base_directory[];
533 533
534/* system defines */ 534/* system defines */
535#ifdef IAUDIO_X5 535#ifndef TARGET_TREE
536#define MIN_CONTRAST_SETTING 1 536#if defined HAVE_LCD_CHARCELLS
537#define MAX_CONTRAST_SETTING 30
538#define DEFAULT_CONTRAST_SETTING 19
539#elif defined HAVE_LCD_CHARCELLS
540#define MIN_CONTRAST_SETTING 5 537#define MIN_CONTRAST_SETTING 5
541#define MAX_CONTRAST_SETTING 31 538#define MAX_CONTRAST_SETTING 31
542#else 539#else
543#define MIN_CONTRAST_SETTING 5 540#define MIN_CONTRAST_SETTING 5
544#define MAX_CONTRAST_SETTING 63 541#define MAX_CONTRAST_SETTING 63
545#endif 542#endif
543#endif /* !TARGET_TREE */
546 544
547/* argument bits for settings_load() */ 545/* argument bits for settings_load() */
548#define SETTINGS_RTC 1 /* only the settings from the RTC nonvolatile RAM */ 546#define SETTINGS_RTC 1 /* only the settings from the RTC nonvolatile RAM */
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 545227fbdf..bc5eeedeef 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -275,7 +275,7 @@ target/arm/iriver/h10/button-h10.c
275target/arm/ata-pp5020.c 275target/arm/ata-pp5020.c
276target/arm/iriver/h10/power-h10.c 276target/arm/iriver/h10/power-h10.c
277target/arm/iriver/h10/usb-h10.c 277target/arm/iriver/h10/usb-h10.c
278target/arm/iriver/h10/lcd-h10.c 278target/arm/iriver/h10/lcd-h10_20gb.c
279target/arm/iriver/h10/adc-h10.c 279target/arm/iriver/h10/adc-h10.c
280#endif 280#endif
281#endif 281#endif
@@ -287,7 +287,7 @@ target/arm/iriver/h10/button-h10.c
287target/arm/ata-pp5020.c 287target/arm/ata-pp5020.c
288target/arm/iriver/h10/power-h10.c 288target/arm/iriver/h10/power-h10.c
289target/arm/iriver/h10/usb-h10.c 289target/arm/iriver/h10/usb-h10.c
290target/arm/iriver/h10/lcd-h10.c 290target/arm/iriver/h10/lcd-h10_5gb.c
291target/arm/iriver/h10/adc-h10.c 291target/arm/iriver/h10/adc-h10.c
292#endif 292#endif
293#endif 293#endif
diff --git a/firmware/export/config-h10.h b/firmware/export/config-h10.h
index a316cbec3f..c024fd464c 100644
--- a/firmware/export/config-h10.h
+++ b/firmware/export/config-h10.h
@@ -26,7 +26,10 @@
26#define LCD_WIDTH 160 26#define LCD_WIDTH 160
27#define LCD_HEIGHT 128 27#define LCD_HEIGHT 128
28#define LCD_DEPTH 16 /* 65536 colours */ 28#define LCD_DEPTH 16 /* 65536 colours */
29#define LCD_PIXELFORMAT RGB565SWAPPED /* rgb565 byte-swapped */ 29#define LCD_PIXELFORMAT RGB565 /* rgb565 */
30
31/* define this if you can flip your LCD */
32#define HAVE_LCD_FLIP
30 33
31/* #define IRAM_LCDFRAMEBUFFER IDATA_ATTR *//* put the lcd frame buffer in IRAM */ 34/* #define IRAM_LCDFRAMEBUFFER IDATA_ATTR *//* put the lcd frame buffer in IRAM */
32 35
@@ -93,13 +96,25 @@
93#define ROM_START 0x00000000 96#define ROM_START 0x00000000
94 97
95/* Define this to the CPU frequency */ 98/* Define this to the CPU frequency */
96/* TODO: this is probably wrong */ 99#define CPU_FREQ 75000000
97#define CPU_FREQ 11289600
98 100
99/* Type of LCD */ 101/* Type of LCD */
100#define CONFIG_LCD LCD_H10_20GB 102#define CONFIG_LCD LCD_H10_20GB
101 103
102#define DEFAULT_CONTRAST_SETTING 19 104/* Define this if your LCD can set contrast */
105#define HAVE_LCD_CONTRAST
106
107#define MIN_CONTRAST_SETTING 0
108#define MAX_CONTRAST_SETTING 30
109#define DEFAULT_CONTRAST_SETTING 14 /* Match boot contrast */
110
111/* Define this if your LCD can be enabled/disabled */
112#define HAVE_LCD_ENABLE
113
114/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE
115 * should be defined as well.
116 * We can currently put the lcd to sleep but it won't wake up properly */
117/*#define HAVE_LCD_SLEEP*/
103 118
104/* Offset ( in the firmware file's header ) to the file length */ 119/* Offset ( in the firmware file's header ) to the file length */
105#define FIRMWARE_OFFSET_FILE_LENGTH 0 120#define FIRMWARE_OFFSET_FILE_LENGTH 0
diff --git a/firmware/export/config-h10_5gb.h b/firmware/export/config-h10_5gb.h
index d3750c1a08..9ad7eede2e 100644
--- a/firmware/export/config-h10_5gb.h
+++ b/firmware/export/config-h10_5gb.h
@@ -63,7 +63,7 @@
63#define CONFIG_BACKLIGHT BL_H10 /* TODO: figure this out, probably not necessary 63#define CONFIG_BACKLIGHT BL_H10 /* TODO: figure this out, probably not necessary
64 because of target tree stuff */ 64 because of target tree stuff */
65 65
66#define BATTERY_CAPACITY_DEFAULT 700 /* default battery capacity */ 66#define BATTERY_CAPACITY_DEFAULT 820 /* default battery capacity */
67 67
68#ifndef SIMULATOR 68#ifndef SIMULATOR
69 69
@@ -93,13 +93,11 @@
93 93
94/* Define this to the CPU frequency */ 94/* Define this to the CPU frequency */
95/* TODO: this is probably wrong */ 95/* TODO: this is probably wrong */
96#define CPU_FREQ 11289600 96#define CPU_FREQ 75000000
97 97
98/* Type of LCD */ 98/* Type of LCD */
99#define CONFIG_LCD LCD_H10_5GB 99#define CONFIG_LCD LCD_H10_5GB
100 100
101#define DEFAULT_CONTRAST_SETTING 19
102
103/* Offset ( in the firmware file's header ) to the file length */ 101/* Offset ( in the firmware file's header ) to the file length */
104#define FIRMWARE_OFFSET_FILE_LENGTH 0 102#define FIRMWARE_OFFSET_FILE_LENGTH 0
105 103
diff --git a/firmware/target/arm/iriver/h10/backlight-h10.c b/firmware/target/arm/iriver/h10/backlight-h10.c
index 21595d1c0f..db3e0b8877 100644
--- a/firmware/target/arm/iriver/h10/backlight-h10.c
+++ b/firmware/target/arm/iriver/h10/backlight-h10.c
@@ -20,13 +20,20 @@
20#include "cpu.h" 20#include "cpu.h"
21#include "system.h" 21#include "system.h"
22#include "backlight.h" 22#include "backlight.h"
23#include "lcd.h"
23 24
24void __backlight_on(void) 25void __backlight_on(void)
25{ 26{
27#if (CONFIG_LCD == LCD_H10_20GB)
28 lcd_enable(true);
29#endif
26 GPIOL_OUTPUT_VAL |= 0x20; 30 GPIOL_OUTPUT_VAL |= 0x20;
27} 31}
28 32
29void __backlight_off(void) 33void __backlight_off(void)
30{ 34{
31 GPIOL_OUTPUT_VAL &=~ 0x20; 35 GPIOL_OUTPUT_VAL &=~ 0x20;
36#if (CONFIG_LCD == LCD_H10_20GB)
37 lcd_enable(false);
38#endif
32} 39}
diff --git a/firmware/target/arm/iriver/h10/lcd-h10_20gb.c b/firmware/target/arm/iriver/h10/lcd-h10_20gb.c
new file mode 100644
index 0000000000..cbada34b2c
--- /dev/null
+++ b/firmware/target/arm/iriver/h10/lcd-h10_20gb.c
@@ -0,0 +1,633 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Barry Wardell
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20#include "cpu.h"
21#include "lcd.h"
22#include "kernel.h"
23#include "system.h"
24
25/* check if number of useconds has past */
26static inline bool timer_check(int clock_start, int usecs)
27{
28 return ((int)(USEC_TIMER - clock_start)) >= usecs;
29}
30
31/** Initialized in lcd_init_device() **/
32/* Is the power turned on? */
33static bool power_on;
34/* Is the display turned on? */
35static bool display_on;
36/* Amount of vertical offset. Used for flip offset correction/detection. */
37static int y_offset;
38/* Reverse flag. Must be remembered when display is turned off. */
39static unsigned short disp_control_rev;
40
41/* Forward declarations */
42static void lcd_display_off(void);
43
44/* Hardware address of LCD. Bits are:
45 * 31 - set to write, poll for completion.
46 * 24 - 0 for command, 1 for data
47 * 7..0 - command/data to send
48 * Commands/Data are always sent in 16-bits, msb first.
49 */
50#define LCD_BASE *(volatile unsigned int *)0x70008a0c
51#define LCD_BUSY_MASK 0x80000000
52#define LCD_CMD 0x80000000
53#define LCD_DATA 0x81000000
54
55/* register defines for the Renesas HD66773R */
56#define R_START_OSC 0x00
57#define R_DEVICE_CODE_READ 0x00
58#define R_DRV_OUTPUT_CONTROL 0x01
59#define R_DRV_AC_CONTROL 0x02
60#define R_POWER_CONTROL1 0x03
61#define R_POWER_CONTROL2 0x04
62#define R_ENTRY_MODE 0x05
63#define R_COMPARE_REG 0x06
64#define R_DISP_CONTROL 0x07
65#define R_FRAME_CYCLE_CONTROL 0x0b
66#define R_POWER_CONTROL3 0x0c
67#define R_POWER_CONTROL4 0x0d
68#define R_POWER_CONTROL5 0x0e
69#define R_GATE_SCAN_START_POS 0x0f
70#define R_VERT_SCROLL_CONTROL 0x11
71#define R_1ST_SCR_DRV_POS 0x14
72#define R_2ND_SCR_DRV_POS 0x15
73#define R_HORIZ_RAM_ADDR_POS 0x16
74#define R_VERT_RAM_ADDR_POS 0x17
75#define R_RAM_WRITE_DATA_MASK 0x20
76#define R_RAM_ADDR_SET 0x21
77#define R_WRITE_DATA_2_GRAM 0x22
78#define R_RAM_READ_DATA 0x22
79#define R_GAMMA_FINE_ADJ_POS1 0x30
80#define R_GAMMA_FINE_ADJ_POS2 0x31
81#define R_GAMMA_FINE_ADJ_POS3 0x32
82#define R_GAMMA_GRAD_ADJ_POS 0x33
83#define R_GAMMA_FINE_ADJ_NEG1 0x34
84#define R_GAMMA_FINE_ADJ_NEG2 0x35
85#define R_GAMMA_FINE_ADJ_NEG3 0x36
86#define R_GAMMA_GRAD_ADJ_NEG 0x37
87#define R_GAMMA_AMP_ADJ_POS 0x3a
88#define R_GAMMA_AMP_ADJ_NEG 0x3b
89
90static inline void lcd_wait_write(void)
91{
92 if ((LCD_BASE & LCD_BUSY_MASK) != 0) {
93 int start = USEC_TIMER;
94
95 do {
96 if ((LCD_BASE & LCD_BUSY_MASK) == 0) break;
97 } while (timer_check(start, 1000) == 0);
98 }
99}
100
101/* Send command */
102static inline void lcd_send_cmd(int v)
103{
104 lcd_wait_write();
105 LCD_BASE = 0x00000000 | LCD_CMD;
106 LCD_BASE = v | LCD_CMD;
107}
108
109/* Send 16-bit data */
110static inline void lcd_send_data(int v)
111{
112 lcd_wait_write();
113 LCD_BASE = ((v>>8) & 0xff) | LCD_DATA; /* Send MSB first */
114 LCD_BASE = ( v & 0xff) | LCD_DATA;
115}
116
117/* Write value to register */
118static inline void lcd_write_reg(int reg, int val)
119{
120 lcd_send_cmd(reg);
121 lcd_send_data(val);
122}
123
124/*** hardware configuration ***/
125
126int lcd_default_contrast(void)
127{
128 return DEFAULT_CONTRAST_SETTING;
129}
130
131void lcd_set_contrast(int val)
132{
133 /* Clamp val in range 0-14, 16-30 */
134 if (val < 1)
135 val = 0;
136 else if (val <= 15)
137 --val;
138 else if (val > 30)
139 val = 30;
140
141 lcd_write_reg(R_POWER_CONTROL5, 0x2018 + (val<<8));
142}
143
144void lcd_set_invert_display(bool yesno)
145{
146 if (yesno == (disp_control_rev == 0x0000))
147 return;
148
149 disp_control_rev = yesno ? 0x0000 : 0x0004;
150
151 if (!display_on)
152 return;
153
154 /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=1, REV=x, D1-0=11 */
155 lcd_write_reg(R_DISP_CONTROL, 0x0033 | disp_control_rev);
156}
157
158
159/* turn the display upside down (call lcd_update() afterwards) */
160void lcd_set_flip(bool yesno)
161{
162 if (yesno == (y_offset != 0))
163 return;
164
165 /* The LCD controller is 132x160 while the LCD itself is 128x160, so we need
166 * to shift the origin by 4 when we flip the LCD */
167 y_offset = yesno ? 4 : 0;
168
169 if (!power_on)
170 return;
171
172 /* SM=0, GS=x, SS=x, NL4-0=10011 (G1-G160) */
173 lcd_write_reg(R_DRV_OUTPUT_CONTROL, yesno ? 0x0013 : 0x0113);
174 /* HEA7-0=0xxx, HSA7-0=0xxx */
175 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, y_offset ? 0x8304 : 0x7f00);
176}
177
178/* LCD init */
179void lcd_init_device(void)
180{
181 power_on = true;
182 display_on = true;
183 y_offset = 0;
184 disp_control_rev = 0x0004;
185}
186
187static void lcd_power_on(void)
188{
189 /* Be sure standby bit is clear. */
190 /* BT2-0=000, DC2-0=000, AP2-0=000, SLP=0, STB=0 */
191 lcd_write_reg(R_POWER_CONTROL1, 0x0000);
192
193 /** Power ON Sequence **/
194 /* Per datasheet Rev.1.10, Jun.21.2003, p. 99 */
195
196 lcd_write_reg(R_START_OSC, 0x0001); /* Start Oscillation */
197 /* 10ms or more for oscillation circuit to stabilize */
198 sleep(HZ/50);
199 /* Instruction (1) for power setting; VC2-0, VRH3-0, CAD,
200 VRL3-0, VCM4-0, VDV4-0 */
201 /* VC2-0=001 */
202 lcd_write_reg(R_POWER_CONTROL3, 0x0001);
203 /* VRL3-0=0100, PON=0, VRH3-0=0001 */
204 lcd_write_reg(R_POWER_CONTROL4, 0x0401);
205 /* CAD=1 */
206 lcd_write_reg(R_POWER_CONTROL2, 0x8000);
207 /* VCOMG=0, VDV4-0=10011 (19), VCM4-0=11000 */
208 lcd_write_reg(R_POWER_CONTROL5, 0x1318);
209 /* Instruction (2) for power setting; BT2-0, DC2-0, AP2-0 */
210 /* BT2-0=000, DC2-0=001, AP2-0=011, SLP=0, STB=0 */
211 lcd_write_reg(R_POWER_CONTROL1, 0x002c);
212 /* Instruction (3) for power setting; VCOMG = "1" */
213 /* VCOMG=1, VDV4-0=10011 (19), VCM4-0=11000 */
214 lcd_write_reg(R_POWER_CONTROL5, 0x3318);
215
216 /* 40ms or more; time for step-up circuits 1,2 to stabilize */
217 sleep(HZ/25);
218
219 /* Instruction (4) for power setting; PON = "1" */
220 /* VRL3-0=0100, PON=1, VRH3-0=0001 */
221 lcd_write_reg(R_POWER_CONTROL4, 0x0411);
222
223 /* 40ms or more; time for step-up circuit 4 to stabilize */
224 sleep(HZ/25);
225
226 /* Instructions for other mode settings (in register order). */
227 /* SM=0, GS=x, SS=0, NL4-0=10011 (G1-G160)*/
228 lcd_write_reg(R_DRV_OUTPUT_CONTROL, y_offset ? 0x0013 : 0x0113); /* different to X5 */
229 /* FLD1-0=01 (1 field), B/C=1, EOR=1 (C-pat), NW5-0=000000 (1 row) */
230 lcd_write_reg(R_DRV_AC_CONTROL, 0x0700);
231 /* DIT=0, BGR=1, HWM=0, I/D1-0=10, AM=1, LG2-0=000 */
232 lcd_write_reg(R_ENTRY_MODE, 0x1028); /* different to X5 */
233 /* CP15-0=0000000000000000 */
234 lcd_write_reg(R_COMPARE_REG, 0x0000);
235 /* NO1-0=01, SDT1-0=00, EQ1-0=00, DIV1-0=00, RTN3-00000 */
236 lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x4000);
237 /* SCN4-0=000x0 (G1/G160) */
238/* lcd_write_reg(R_GATE_SCAN_START_POS, y_offset ? 0x0000 : 0x0002); */
239 /* VL7-0=0x00 */
240 lcd_write_reg(R_VERT_SCROLL_CONTROL, 0x0000);
241 /* SE17-10(End)=0x9f (159), SS17-10(Start)=0x00 */
242 lcd_write_reg(R_1ST_SCR_DRV_POS, 0x9f00);
243 /* SE27-20(End)=0x5c (92), SS27-20(Start)=0x00 */
244 lcd_write_reg(R_2ND_SCR_DRV_POS, 0x5c00);
245 /* HEA7-0=0xxx, HSA7-0=0xxx */
246 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, y_offset ? 0x8304 : 0x7f00);
247 /* PKP12-10=0x0, PKP02-00=0x0 */
248 lcd_write_reg(R_GAMMA_FINE_ADJ_POS1, 0x0003);
249 /* PKP32-30=0x4, PKP22-20=0x0 */
250 lcd_write_reg(R_GAMMA_FINE_ADJ_POS2, 0x0400);
251 /* PKP52-50=0x4, PKP42-40=0x7 */
252 lcd_write_reg(R_GAMMA_FINE_ADJ_POS3, 0x0407);
253 /* PRP12-10=0x3, PRP02-00=0x5 */
254 lcd_write_reg(R_GAMMA_GRAD_ADJ_POS, 0x0305);
255 /* PKN12-10=0x0, PKN02-00=0x3 */
256 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG1, 0x0003);
257 /* PKN32-30=0x7, PKN22-20=0x4 */
258 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG2, 0x0704);
259 /* PKN52-50=0x4, PRN42-40=0x7 */
260 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG3, 0x0407);
261 /* PRN12-10=0x5, PRN02-00=0x3 */
262 lcd_write_reg(R_GAMMA_GRAD_ADJ_NEG, 0x0503);
263 /* VRP14-10=0x14, VRP03-00=0x09 */
264 lcd_write_reg(R_GAMMA_AMP_ADJ_POS, 0x1409);
265 /* VRN14-00=0x06, VRN03-00=0x02 */
266 lcd_write_reg(R_GAMMA_AMP_ADJ_NEG, 0x0602);
267
268 /* 100ms or more; time for step-up circuits to stabilize */
269 sleep(HZ/10);
270
271 power_on = true;
272}
273
274static void lcd_power_off(void)
275{
276 /* Display must be off first */
277 if (display_on)
278 lcd_display_off();
279
280 power_on = false;
281
282 /** Power OFF sequence **/
283 /* Per datasheet Rev.1.10, Jun.21.2003, p. 99 */
284
285 /* Step-up1 halt setting bit */
286 /* BT2-0=110, DC2-0=001, AP2-0=011, SLP=0, STB=0 */
287 lcd_write_reg(R_POWER_CONTROL1, 0x062c);
288 /* Step-up3,4 halt setting bit */
289 /* VRL3-0=0100, PON=0, VRH3-0=0001 */
290 lcd_write_reg(R_POWER_CONTROL4, 0x0401);
291 /* VCOMG=0, VDV4-0=10011, VCM4-0=11000 */
292 lcd_write_reg(R_POWER_CONTROL5, 0x1318);
293
294 /* Wait 100ms or more */
295 sleep(HZ/10);
296
297 /* Step-up2,amp halt setting bit */
298 /* BT2-0=000, DC2-0=000, AP2-0=000, SLP=0, STB=0 */
299 lcd_write_reg(R_POWER_CONTROL1, 0x0000);
300}
301
302static void lcd_display_on(void)
303{
304 /* Be sure power is on first */
305 if (!power_on)
306 lcd_power_on();
307
308 /** Display ON Sequence **/
309 /* Per datasheet Rev.1.10, Jun.21.2003, p. 97 */
310
311 /* PT1-0=00, VLE2-1=00, SPT=0, GON=0, DTE=0, REV=0, D1-0=01 */
312 lcd_write_reg(R_DISP_CONTROL, 0x0001);
313
314 sleep(HZ/25); /* Wait 2 frames or more */
315
316 /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=0, REV=x, D1-0=01 */
317 lcd_write_reg(R_DISP_CONTROL, 0x0021 | disp_control_rev);
318 /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=0, REV=x, D1-0=11 */
319 lcd_write_reg(R_DISP_CONTROL, 0x0023 | disp_control_rev);
320
321 sleep(HZ/25); /* Wait 2 frames or more */
322
323 /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=1, REV=x, D1-0=11 */
324 lcd_write_reg(R_DISP_CONTROL, 0x0033 | disp_control_rev);
325
326 display_on = true;
327}
328
329static void lcd_display_off(void)
330{
331 display_on = false;
332
333 /** Display OFF sequence **/
334 /* Per datasheet Rev.1.10, Jun.21.2003, p. 97 */
335
336 /* EQ1-0=00 already */
337
338 /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=1, REV=x, D1-0=10 */
339 lcd_write_reg(R_DISP_CONTROL, 0x0032 | disp_control_rev);
340
341 sleep(HZ/25); /* Wait 2 frames or more */
342
343 /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=0, REV=x, D1-0=10 */
344 lcd_write_reg(R_DISP_CONTROL, 0x0022 | disp_control_rev);
345
346 sleep(HZ/25); /* Wait 2 frames or more */
347
348 /* PT1-0=00, VLE2-1=00, SPT=0, GON=0, DTE=0, REV=0, D1-0=00 */
349 lcd_write_reg(R_DISP_CONTROL, 0x0000);
350}
351
352void lcd_enable(bool on)
353{
354 if (on == display_on)
355 return;
356
357 if (on)
358 {
359 lcd_display_on();
360 /* Probably out of sync and we don't wanna pepper the code with
361 lcd_update() calls for this. */
362 lcd_update();
363 }
364 else
365 {
366 lcd_display_off();
367 }
368}
369
370void lcd_sleep(void)
371{
372 if (power_on)
373 lcd_power_off();
374
375 /* Set standby mode */
376 /* BT2-0=000, DC2-0=000, AP2-0=000, SLP=0, STB=1 */
377 lcd_write_reg(R_POWER_CONTROL1, 0x0001);
378}
379
380/*** update functions ***/
381
382/* Performance function that works with an external buffer
383 note that by and bheight are in 4-pixel units! */
384void lcd_blit(const fb_data* data, int x, int by, int width,
385 int bheight, int stride)
386{
387 /* TODO: Implement lcd_blit() */
388 (void)data;
389 (void)x;
390 (void)by;
391 (void)width;
392 (void)bheight;
393 (void)stride;
394}
395
396#define CSUB_X 2
397#define CSUB_Y 2
398
399#define RYFAC (31*257)
400#define GYFAC (31*257)
401#define BYFAC (31*257)
402#define RVFAC 11170 /* 31 * 257 * 1.402 */
403#define GVFAC (-5690) /* 31 * 257 * -0.714136 */
404#define GUFAC (-2742) /* 31 * 257 * -0.344136 */
405#define BUFAC 14118 /* 31 * 257 * 1.772 */
406
407#define ROUNDOFFS (127*257)
408#define ROUNDOFFSG (63*257)
409
410/* Performance function to blit a YUV bitmap directly to the LCD */
411void lcd_yuv_blit(unsigned char * const src[3],
412 int src_x, int src_y, int stride,
413 int x, int y, int width, int height)
414{
415 int y0, x0, y1, x1;
416 int ymax;
417
418 if (!display_on)
419 return;
420
421 width = (width + 1) & ~1;
422
423 /* calculate the drawing region */
424 x0 = x;
425 x1 = x + width - 1;
426 y0 = y;
427 y1 = y + height - 1;
428
429 /* The 20GB LCD is actually 128x160 but rotated 90 degrees so the origin
430 * is actually the bottom left and horizontal and vertical are swapped.
431 * Rockbox expects the origin to be the top left so we need to use
432 * 127 - y instead of just y */
433
434 /* max horiz << 8 | start horiz */
435 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS);
436 lcd_send_data( (((LCD_HEIGHT-1)-y0+y_offset) << 8) | ((LCD_HEIGHT-1)-y1+y_offset) );
437
438 /* max vert << 8 | start vert */
439 lcd_send_cmd(R_VERT_RAM_ADDR_POS);
440 lcd_send_data((x1 << 8) | x0);
441
442 /* position cursor (set AD0-AD15) */
443 /* start vert << 8 | start horiz */
444 lcd_send_cmd(R_RAM_ADDR_SET);
445 lcd_send_data( (x0 << 8) | ((LCD_HEIGHT-1)-y0+y_offset) );
446
447 /* start drawing */
448 lcd_send_cmd(R_WRITE_DATA_2_GRAM);
449
450 ymax = y + height - 1 ;
451
452 const int stride_div_csub_x = stride/CSUB_X;
453
454 for (; y <= ymax ; y++)
455 {
456 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
457 const unsigned char *ysrc = src[0] + stride * src_y + src_x;
458
459 const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) +
460 (src_x/CSUB_X);
461
462 const unsigned char *usrc = src[1] + uvoffset;
463 const unsigned char *vsrc = src[2] + uvoffset;
464 const unsigned char *row_end = ysrc + width;
465
466 int y, u, v;
467 int red1, green1, blue1;
468 int red2, green2, blue2;
469 unsigned rbits, gbits, bbits;
470
471 int rc, gc, bc;
472
473 do
474 {
475 u = *usrc++ - 128;
476 v = *vsrc++ - 128;
477 rc = RVFAC * v + ROUNDOFFS;
478 gc = GVFAC * v + GUFAC * u + ROUNDOFFSG;
479 bc = BUFAC * u + ROUNDOFFS;
480
481 /* Pixel 1 */
482 y = *ysrc++;
483
484 red1 = RYFAC * y + rc;
485 green1 = GYFAC * y + gc;
486 blue1 = BYFAC * y + bc;
487
488 /* Pixel 2 */
489 y = *ysrc++;
490 red2 = RYFAC * y + rc;
491 green2 = GYFAC * y + gc;
492 blue2 = BYFAC * y + bc;
493
494 /* Since out of bounds errors are relatively rare, we check two
495 pixels at once to see if any components are out of bounds, and
496 then fix whichever is broken. This works due to high values and
497 negative values both becoming larger than the cutoff when
498 casted to unsigned. And ORing them together checks all of them
499 simultaneously. */
500 if (((unsigned)(red1 | green1 | blue1 |
501 red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) {
502 if (((unsigned)(red1 | green1 | blue1)) >
503 (RYFAC*255+ROUNDOFFS)) {
504 if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS))
505 {
506 if (red1 < 0)
507 red1 = 0;
508 else
509 red1 = (RYFAC*255+ROUNDOFFS);
510 }
511 if ((unsigned)green1 > (GYFAC*255+ROUNDOFFSG))
512 {
513 if (green1 < 0)
514 green1 = 0;
515 else
516 green1 = (GYFAC*255+ROUNDOFFSG);
517 }
518 if ((unsigned)blue1 > (BYFAC*255+ROUNDOFFS))
519 {
520 if (blue1 < 0)
521 blue1 = 0;
522 else
523 blue1 = (BYFAC*255+ROUNDOFFS);
524 }
525 }
526
527 if (((unsigned)(red2 | green2 | blue2)) >
528 (RYFAC*255+ROUNDOFFS)) {
529 if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS))
530 {
531 if (red2 < 0)
532 red2 = 0;
533 else
534 red2 = (RYFAC*255+ROUNDOFFS);
535 }
536 if ((unsigned)green2 > (GYFAC*255+ROUNDOFFSG))
537 {
538 if (green2 < 0)
539 green2 = 0;
540 else
541 green2 = (GYFAC*255+ROUNDOFFSG);
542 }
543 if ((unsigned)blue2 > (BYFAC*255+ROUNDOFFS))
544 {
545 if (blue2 < 0)
546 blue2 = 0;
547 else
548 blue2 = (BYFAC*255+ROUNDOFFS);
549 }
550 }
551 }
552
553 rbits = red1 >> 16 ;
554 gbits = green1 >> 15 ;
555 bbits = blue1 >> 16 ;
556 lcd_send_data((rbits << 11) | (gbits << 5) | bbits);
557
558 rbits = red2 >> 16 ;
559 gbits = green2 >> 15 ;
560 bbits = blue2 >> 16 ;
561 lcd_send_data((rbits << 11) | (gbits << 5) | bbits);
562 }
563 while (ysrc < row_end);
564
565 src_y++;
566 }
567}
568
569
570/* Update a fraction of the display. */
571void lcd_update_rect(int x0, int y0, int width, int height)
572{
573 int x1, y1;
574
575 unsigned short *addr = (unsigned short *)lcd_framebuffer;
576
577 if (!display_on)
578 return;
579
580 /* calculate the drawing region */
581 y1 = (y0 + height) - 1; /* max vert */
582 x1 = (x0 + width) - 1; /* max horiz */
583
584 if(x1 >= LCD_WIDTH)
585 x1 = LCD_WIDTH - 1;
586 if (x1 <= 0)
587 return; /* nothing left to do, 0 is harmful to lcd_write_data() */
588 if(y1 >= LCD_HEIGHT)
589 y1 = LCD_HEIGHT-1;
590
591 /* The 20GB LCD is actually 128x160 but rotated 90 degrees so the origin
592 * is actually the bottom left and horizontal and vertical are swapped.
593 * Rockbox expects the origin to be the top left so we need to use
594 * 127 - y instead of just y */
595
596 /* max horiz << 8 | start horiz */
597 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS);
598 lcd_send_data( (((LCD_HEIGHT-1)-y0+y_offset) << 8) | ((LCD_HEIGHT-1)-y1+y_offset) );
599
600 /* max vert << 8 | start vert */
601 lcd_send_cmd(R_VERT_RAM_ADDR_POS);
602 lcd_send_data((x1 << 8) | x0);
603
604 /* position cursor (set AD0-AD15) */
605 /* start vert << 8 | start horiz */
606 lcd_send_cmd(R_RAM_ADDR_SET);
607 lcd_send_data( (x0 << 8) | ((LCD_HEIGHT-1)-y0+y_offset) );
608
609 /* start drawing */
610 lcd_send_cmd(R_WRITE_DATA_2_GRAM);
611
612 addr = (unsigned short*)&lcd_framebuffer[y0][x0];
613
614 int c, r;
615
616 /* for each row */
617 for (r = 0; r < height; r++) {
618 /* for each column */
619 for (c = 0; c < width; c++) {
620 /* output 1 pixel */
621 lcd_send_data(*(addr++));
622 }
623
624 addr += LCD_WIDTH - width;
625 }
626}
627
628/* Update the display.
629 This must be called after all other LCD functions that change the display. */
630void lcd_update(void)
631{
632 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
633}
diff --git a/firmware/target/arm/iriver/h10/lcd-h10.c b/firmware/target/arm/iriver/h10/lcd-h10_5gb.c
index 64e8f5d8b9..01f4130efb 100644
--- a/firmware/target/arm/iriver/h10/lcd-h10.c
+++ b/firmware/target/arm/iriver/h10/lcd-h10_5gb.c
@@ -39,43 +39,6 @@ static inline bool timer_check(int clock_start, int usecs)
39#define LCD_CMD 0x80000000 39#define LCD_CMD 0x80000000
40#define LCD_DATA 0x81000000 40#define LCD_DATA 0x81000000
41 41
42#ifdef IRIVER_H10
43/* register defines for the Renesas HD66773R */
44#define R_START_OSC 0x00
45#define R_DEVICE_CODE_READ 0x00
46#define R_DRV_OUTPUT_CONTROL 0x01
47#define R_DRV_AC_CONTROL 0x02
48#define R_POWER_CONTROL1 0x03
49#define R_POWER_CONTROL2 0x04
50#define R_ENTRY_MODE 0x05
51#define R_COMPARE_REG 0x06
52#define R_DISP_CONTROL 0x07
53#define R_FRAME_CYCLE_CONTROL 0x0b
54#define R_POWER_CONTROL3 0x0c
55#define R_POWER_CONTROL4 0x0d
56#define R_POWER_CONTROL5 0x0e
57#define R_GATE_SCAN_START_POS 0x0f
58#define R_VERT_SCROLL_CONTROL 0x11
59#define R_1ST_SCR_DRV_POS 0x14
60#define R_2ND_SCR_DRV_POS 0x15
61#define R_HORIZ_RAM_ADDR_POS 0x16
62#define R_VERT_RAM_ADDR_POS 0x17
63#define R_RAM_WRITE_DATA_MASK 0x20
64#define R_RAM_ADDR_SET 0x21
65#define R_WRITE_DATA_2_GRAM 0x22
66#define R_RAM_READ_DATA 0x22
67#define R_GAMMA_FINE_ADJ_POS1 0x30
68#define R_GAMMA_FINE_ADJ_POS2 0x31
69#define R_GAMMA_FINE_ADJ_POS3 0x32
70#define R_GAMMA_GRAD_ADJ_POS 0x33
71#define R_GAMMA_FINE_ADJ_NEG1 0x34
72#define R_GAMMA_FINE_ADJ_NEG2 0x35
73#define R_GAMMA_FINE_ADJ_NEG3 0x36
74#define R_GAMMA_GRAD_ADJ_NEG 0x37
75#define R_GAMMA_AMP_ADJ_POS 0x3a
76#define R_GAMMA_AMP_ADJ_NEG 0x3b
77
78#elif defined(IRIVER_H10_5GB)
79/* register defines for TL1771 */ 42/* register defines for TL1771 */
80#define R_START_OSC 0x00 43#define R_START_OSC 0x00
81#define R_DEVICE_CODE_READ 0x00 44#define R_DEVICE_CODE_READ 0x00
@@ -107,8 +70,6 @@ static inline bool timer_check(int clock_start, int usecs)
107#define R_HORIZ_RAM_ADDR_POS 0x44 70#define R_HORIZ_RAM_ADDR_POS 0x44
108#define R_VERT_RAM_ADDR_POS 0x45 71#define R_VERT_RAM_ADDR_POS 0x45
109 72
110#endif
111
112static inline void lcd_wait_write(void) 73static inline void lcd_wait_write(void)
113{ 74{
114 if ((LCD_BASE & LCD_BUSY_MASK) != 0) { 75 if ((LCD_BASE & LCD_BUSY_MASK) != 0) {
@@ -219,7 +180,6 @@ void lcd_yuv_blit(unsigned char * const src[3],
219 y0 = y; 180 y0 = y;
220 y1 = y + height - 1; 181 y1 = y + height - 1;
221 182
222#if CONFIG_LCD == LCD_H10_5GB
223 /* start horiz << 8 | max horiz */ 183 /* start horiz << 8 | max horiz */
224 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS); 184 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS);
225 lcd_send_data((x0 << 8) | x1); 185 lcd_send_data((x0 << 8) | x1);
@@ -232,27 +192,6 @@ void lcd_yuv_blit(unsigned char * const src[3],
232 lcd_send_cmd(R_RAM_ADDR_SET); 192 lcd_send_cmd(R_RAM_ADDR_SET);
233 lcd_send_data(((x0 << 8) | y0)); 193 lcd_send_data(((x0 << 8) | y0));
234 194
235#elif CONFIG_LCD == LCD_H10_20GB
236 /* The 20GB LCD is actually 128x160 but rotated 90 degrees so the origin
237 * is actually the bottom left and horizontal and vertical are swapped.
238 * Rockbox expects the origin to be the top left so we need to use
239 * 127 - y instead of just y */
240
241 /* start horiz << 8 | max horiz */
242 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS);
243 lcd_send_data(((127-y1) << 8) | (127-y0));
244
245 /* start vert << 8 | max vert */
246 lcd_send_cmd(R_VERT_RAM_ADDR_POS);
247 lcd_send_data((x0 << 8) | x1);
248
249 /* position cursor (set AD0-AD15) */
250 /* start horiz << 8 | start vert */
251 lcd_send_cmd(R_RAM_ADDR_SET);
252 lcd_send_data((((127-y0) << 8) | x0));
253
254#endif /* CONFIG_LCD */
255
256 /* start drawing */ 195 /* start drawing */
257 lcd_send_cmd(R_WRITE_DATA_2_GRAM); 196 lcd_send_cmd(R_WRITE_DATA_2_GRAM);
258 197
@@ -412,7 +351,6 @@ void lcd_update_rect(int x0, int y0, int width, int height)
412 x1 = t; 351 x1 = t;
413 } 352 }
414 353
415#if CONFIG_LCD == LCD_H10_5GB
416 /* start horiz << 8 | max horiz */ 354 /* start horiz << 8 | max horiz */
417 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS); 355 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS);
418 lcd_send_data((x0 << 8) | x1); 356 lcd_send_data((x0 << 8) | x1);
@@ -424,27 +362,6 @@ void lcd_update_rect(int x0, int y0, int width, int height)
424 /* start horiz << 8 | start vert */ 362 /* start horiz << 8 | start vert */
425 lcd_send_cmd(R_RAM_ADDR_SET); 363 lcd_send_cmd(R_RAM_ADDR_SET);
426 lcd_send_data(((x0 << 8) | y0)); 364 lcd_send_data(((x0 << 8) | y0));
427
428#elif CONFIG_LCD == LCD_H10_20GB
429 /* The 20GB LCD is actually 128x160 but rotated 90 degrees so the origin
430 * is actually the bottom left and horizontal and vertical are swapped.
431 * Rockbox expects the origin to be the top left so we need to use
432 * 127 - y instead of just y */
433
434 /* start horiz << 8 | max horiz */
435 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS);
436 lcd_send_data(((127-y1) << 8) | (127-y0));
437
438 /* start vert << 8 | max vert */
439 lcd_send_cmd(R_VERT_RAM_ADDR_POS);
440 lcd_send_data((x0 << 8) | x1);
441
442 /* position cursor (set AD0-AD15) */
443 /* start horiz << 8 | start vert */
444 lcd_send_cmd(R_RAM_ADDR_SET);
445 lcd_send_data((((127-y0) << 8) | x0));
446
447#endif /* CONFIG_LCD */
448 365
449 /* start drawing */ 366 /* start drawing */
450 lcd_send_cmd(R_WRITE_DATA_2_GRAM); 367 lcd_send_cmd(R_WRITE_DATA_2_GRAM);
diff --git a/tools/configure b/tools/configure
index 0f51e486a2..c1c942a7ea 100755
--- a/tools/configure
+++ b/tools/configure
@@ -951,7 +951,7 @@ EOF
951 arm7tdmicc 951 arm7tdmicc
952 tool="$rootdir/tools/scramble -add=h10" 952 tool="$rootdir/tools/scramble -add=h10"
953 bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" 953 bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
954 bmp2rb_native="$rootdir/tools/bmp2rb -f 5" 954 bmp2rb_native="$rootdir/tools/bmp2rb -f 4"
955 output="rockbox.h10" 955 output="rockbox.h10"
956 appextra="recorder:gui" 956 appextra="recorder:gui"
957 archosrom="" 957 archosrom=""