diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/iriver/h10/backlight-h10.c | 7 | ||||
-rw-r--r-- | firmware/target/arm/iriver/h10/lcd-h10_20gb.c | 633 | ||||
-rw-r--r-- | firmware/target/arm/iriver/h10/lcd-h10_5gb.c (renamed from firmware/target/arm/iriver/h10/lcd-h10.c) | 83 |
3 files changed, 640 insertions, 83 deletions
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 | ||
24 | void __backlight_on(void) | 25 | void __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 | ||
29 | void __backlight_off(void) | 33 | void __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 */ | ||
26 | static 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? */ | ||
33 | static bool power_on; | ||
34 | /* Is the display turned on? */ | ||
35 | static bool display_on; | ||
36 | /* Amount of vertical offset. Used for flip offset correction/detection. */ | ||
37 | static int y_offset; | ||
38 | /* Reverse flag. Must be remembered when display is turned off. */ | ||
39 | static unsigned short disp_control_rev; | ||
40 | |||
41 | /* Forward declarations */ | ||
42 | static 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 | |||
90 | static 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 */ | ||
102 | static 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 */ | ||
110 | static 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 */ | ||
118 | static 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 | |||
126 | int lcd_default_contrast(void) | ||
127 | { | ||
128 | return DEFAULT_CONTRAST_SETTING; | ||
129 | } | ||
130 | |||
131 | void 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 | |||
144 | void 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) */ | ||
160 | void 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 */ | ||
179 | void lcd_init_device(void) | ||
180 | { | ||
181 | power_on = true; | ||
182 | display_on = true; | ||
183 | y_offset = 0; | ||
184 | disp_control_rev = 0x0004; | ||
185 | } | ||
186 | |||
187 | static 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 | |||
274 | static 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 | |||
302 | static 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 | |||
329 | static 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 | |||
352 | void 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 | |||
370 | void 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! */ | ||
384 | void 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 */ | ||
411 | void 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. */ | ||
571 | void 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. */ | ||
630 | void 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 | |||
112 | static inline void lcd_wait_write(void) | 73 | static 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); |