diff options
author | Mark Arigo <markarigo@gmail.com> | 2009-05-25 21:10:45 +0000 |
---|---|---|
committer | Mark Arigo <markarigo@gmail.com> | 2009-05-25 21:10:45 +0000 |
commit | 758bb3bc628705ff8e5c677b3b2d87720c726c13 (patch) | |
tree | d78cbf984e4bc613b0b76fcf4a5f090ab1d774b8 /firmware/target/arm/samsung/yh925/lcd-yh925.c | |
parent | d2ea7db6f55cbb121870ecd41d4d80581354b799 (diff) | |
download | rockbox-758bb3bc628705ff8e5c677b3b2d87720c726c13.tar.gz rockbox-758bb3bc628705ff8e5c677b3b2d87720c726c13.zip |
3 new ports: Samsung YH-820, YH-920, and YH-925. Mostly functional. Audio working on 820 & 925 (untested on the 920). No battery readings. No recording. No plugins. Keymap needs work.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21083 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/samsung/yh925/lcd-yh925.c')
-rw-r--r-- | firmware/target/arm/samsung/yh925/lcd-yh925.c | 638 |
1 files changed, 638 insertions, 0 deletions
diff --git a/firmware/target/arm/samsung/yh925/lcd-yh925.c b/firmware/target/arm/samsung/yh925/lcd-yh925.c new file mode 100644 index 0000000000..8afcf58bea --- /dev/null +++ b/firmware/target/arm/samsung/yh925/lcd-yh925.c | |||
@@ -0,0 +1,638 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 by Barry Wardell | ||
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 | #include "config.h" | ||
22 | #include "cpu.h" | ||
23 | #include "lcd.h" | ||
24 | #include "kernel.h" | ||
25 | #include "system.h" | ||
26 | |||
27 | /** Initialized in lcd_init_device() **/ | ||
28 | /* Is the power turned on? */ | ||
29 | static bool power_on; | ||
30 | /* Is the display turned on? */ | ||
31 | static bool display_on; | ||
32 | /* Amount of vertical offset. Used for flip offset correction/detection. */ | ||
33 | static int y_offset; | ||
34 | /* Reverse flag. Must be remembered when display is turned off. */ | ||
35 | static unsigned short disp_control_rev; | ||
36 | /* Contrast setting << 8 */ | ||
37 | static int lcd_contrast; | ||
38 | |||
39 | static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0; | ||
40 | |||
41 | /* Forward declarations */ | ||
42 | #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) | ||
43 | static void lcd_display_off(void); | ||
44 | #endif | ||
45 | |||
46 | /* register defines for the Renesas HD66773R */ | ||
47 | #define R_START_OSC 0x00 | ||
48 | #define R_DEVICE_CODE_READ 0x00 | ||
49 | #define R_DRV_OUTPUT_CONTROL 0x01 | ||
50 | #define R_DRV_AC_CONTROL 0x02 | ||
51 | #define R_POWER_CONTROL1 0x03 | ||
52 | #define R_POWER_CONTROL2 0x04 | ||
53 | #define R_ENTRY_MODE 0x05 | ||
54 | #define R_COMPARE_REG 0x06 | ||
55 | #define R_DISP_CONTROL 0x07 | ||
56 | #define R_FRAME_CYCLE_CONTROL 0x0b | ||
57 | #define R_POWER_CONTROL3 0x0c | ||
58 | #define R_POWER_CONTROL4 0x0d | ||
59 | #define R_POWER_CONTROL5 0x0e | ||
60 | #define R_GATE_SCAN_START_POS 0x0f | ||
61 | #define R_VERT_SCROLL_CONTROL 0x11 | ||
62 | #define R_1ST_SCR_DRV_POS 0x14 | ||
63 | #define R_2ND_SCR_DRV_POS 0x15 | ||
64 | #define R_HORIZ_RAM_ADDR_POS 0x16 | ||
65 | #define R_VERT_RAM_ADDR_POS 0x17 | ||
66 | #define R_RAM_WRITE_DATA_MASK 0x20 | ||
67 | #define R_RAM_ADDR_SET 0x21 | ||
68 | #define R_WRITE_DATA_2_GRAM 0x22 | ||
69 | #define R_RAM_READ_DATA 0x22 | ||
70 | #define R_GAMMA_FINE_ADJ_POS1 0x30 | ||
71 | #define R_GAMMA_FINE_ADJ_POS2 0x31 | ||
72 | #define R_GAMMA_FINE_ADJ_POS3 0x32 | ||
73 | #define R_GAMMA_GRAD_ADJ_POS 0x33 | ||
74 | #define R_GAMMA_FINE_ADJ_NEG1 0x34 | ||
75 | #define R_GAMMA_FINE_ADJ_NEG2 0x35 | ||
76 | #define R_GAMMA_FINE_ADJ_NEG3 0x36 | ||
77 | #define R_GAMMA_GRAD_ADJ_NEG 0x37 | ||
78 | #define R_GAMMA_AMP_ADJ_POS 0x3a | ||
79 | #define R_GAMMA_AMP_ADJ_NEG 0x3b | ||
80 | |||
81 | static inline void lcd_wait_write(void) | ||
82 | { | ||
83 | while (LCD2_PORT & LCD2_BUSY_MASK); | ||
84 | } | ||
85 | |||
86 | /* Send command */ | ||
87 | static inline void lcd_send_cmd(unsigned cmd) | ||
88 | { | ||
89 | lcd_wait_write(); | ||
90 | LCD2_PORT = LCD2_CMD_MASK; /* Send MSB first (should always be 0) */ | ||
91 | lcd_wait_write(); | ||
92 | LCD2_PORT = LCD2_CMD_MASK | cmd; | ||
93 | } | ||
94 | |||
95 | /* Send 16-bit data */ | ||
96 | static inline void lcd_send_data(unsigned data) | ||
97 | { | ||
98 | lcd_wait_write(); | ||
99 | LCD2_PORT = (data >> 8) | LCD2_DATA_MASK; /* Send MSB first */ | ||
100 | lcd_wait_write(); | ||
101 | LCD2_PORT = (data & 0xff) | LCD2_DATA_MASK; | ||
102 | } | ||
103 | |||
104 | /* Send 16-bit data byte-swapped. Only needed until we can use block transfer. */ | ||
105 | static inline void lcd_send_data_swapped(unsigned v) | ||
106 | { | ||
107 | lcd_wait_write(); | ||
108 | LCD2_PORT = LCD2_DATA_MASK | (v & 0xff); /* Send LSB first */ | ||
109 | LCD2_PORT = LCD2_DATA_MASK | (v >> 8); | ||
110 | } | ||
111 | |||
112 | /* Write value to register */ | ||
113 | static void lcd_write_reg(int reg, int val) | ||
114 | { | ||
115 | lcd_send_cmd(reg); | ||
116 | lcd_send_data(val); | ||
117 | } | ||
118 | |||
119 | /*** hardware configuration ***/ | ||
120 | |||
121 | int lcd_default_contrast(void) | ||
122 | { | ||
123 | return DEFAULT_CONTRAST_SETTING; | ||
124 | } | ||
125 | |||
126 | void lcd_set_contrast(int val) | ||
127 | { | ||
128 | /* Clamp val in range 0-14, 16-30 */ | ||
129 | if (val < 1) | ||
130 | val = 0; | ||
131 | else if (val <= 15) | ||
132 | --val; | ||
133 | else if (val > 30) | ||
134 | val = 30; | ||
135 | |||
136 | lcd_contrast = val << 8; | ||
137 | |||
138 | if (!power_on) | ||
139 | return; | ||
140 | |||
141 | /* VCOMG=1, VDV4-0=xxxxx, VCM4-0=11000 */ | ||
142 | lcd_write_reg(R_POWER_CONTROL5, 0x2018 | lcd_contrast); | ||
143 | } | ||
144 | |||
145 | void lcd_set_invert_display(bool yesno) | ||
146 | { | ||
147 | if (yesno == (disp_control_rev == 0x0000)) | ||
148 | return; | ||
149 | |||
150 | disp_control_rev = yesno ? 0x0000 : 0x0004; | ||
151 | |||
152 | if (!display_on) | ||
153 | return; | ||
154 | |||
155 | /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=1, REV=x, D1-0=11 */ | ||
156 | lcd_write_reg(R_DISP_CONTROL, 0x0033 | disp_control_rev); | ||
157 | } | ||
158 | |||
159 | |||
160 | /* turn the display upside down (call lcd_update() afterwards) */ | ||
161 | void lcd_set_flip(bool yesno) | ||
162 | { | ||
163 | /* NOT MODIFIED FOR THE YH-925 */ | ||
164 | |||
165 | if (yesno == (y_offset != 0)) | ||
166 | return; | ||
167 | |||
168 | /* The LCD controller is 132x160 while the LCD itself is 128x160, so we need | ||
169 | * to shift the origin by 4 when we flip the LCD */ | ||
170 | y_offset = yesno ? 4 : 0; | ||
171 | |||
172 | if (!power_on) | ||
173 | return; | ||
174 | |||
175 | /* SCN4-0=000x0 (G1/G160) */ | ||
176 | lcd_write_reg(R_GATE_SCAN_START_POS, yesno ? 0x0002 : 0x0000); | ||
177 | /* SM=0, GS=x, SS=x, NL4-0=10011 (G1-G160) */ | ||
178 | lcd_write_reg(R_DRV_OUTPUT_CONTROL, yesno ? 0x0213 : 0x0113); | ||
179 | } | ||
180 | |||
181 | /* LCD init */ | ||
182 | void lcd_init_device(void) | ||
183 | { | ||
184 | #if 0 | ||
185 | /* This is the OF LCD init */ | ||
186 | int i; | ||
187 | |||
188 | DEV_EN2 |= 0x2000; | ||
189 | DEV_INIT1 |= 0xfc000000; | ||
190 | CLCD_CLOCK_SRC &= ~0xf; | ||
191 | DEV_INIT2 &= ~0x400; | ||
192 | |||
193 | GPIOF_ENABLE |= 0x4; | ||
194 | GPIOF_OUTPUT_EN |= 0x4; | ||
195 | GPIOF_OUTPUT_VAL &= ~0x4; | ||
196 | udelay(300000); | ||
197 | GPIOF_OUTPUT_VAL |= 0x4; | ||
198 | |||
199 | outl(0x220, 0x70008a00); | ||
200 | outl(0x1f00, 0x70008a04); | ||
201 | LCD2_BLOCK_CTRL = 0x10008080; | ||
202 | LCD2_BLOCK_CONFIG = 0xf00000; | ||
203 | udelay(100000); | ||
204 | |||
205 | for (i = 0; i < 8; i++) | ||
206 | { | ||
207 | lcd_send_data(0); | ||
208 | udelay(1); | ||
209 | } | ||
210 | |||
211 | lcd_write_reg(R_START_OSC, 0x0001); | ||
212 | udelay(20000); | ||
213 | lcd_write_reg(R_DRV_OUTPUT_CONTROL, 0x0315); | ||
214 | lcd_write_reg(R_DRV_AC_CONTROL, 0x0700); | ||
215 | lcd_write_reg(R_ENTRY_MODE, 0x1028); | ||
216 | lcd_write_reg(R_COMPARE_REG, 0x0000); | ||
217 | lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x4008); | ||
218 | lcd_write_reg(R_RAM_ADDR_SET, 0x0000); | ||
219 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS1, 0x0700); | ||
220 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS2, 0x0000); | ||
221 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS3, 0x0000); | ||
222 | lcd_write_reg(R_GAMMA_GRAD_ADJ_POS, 0x0100); | ||
223 | lcd_write_reg(R_GAMMA_FINE_ADJ_NEG1, 0x0707); | ||
224 | lcd_write_reg(R_GAMMA_FINE_ADJ_NEG2, 0x0007); | ||
225 | lcd_write_reg(R_GAMMA_FINE_ADJ_NEG3, 0x0700); | ||
226 | lcd_write_reg(R_GAMMA_GRAD_ADJ_NEG, 0x0001); | ||
227 | lcd_write_reg(R_GATE_SCAN_START_POS, 0x0000); | ||
228 | lcd_write_reg(R_VERT_SCROLL_CONTROL, 0x0000); | ||
229 | lcd_write_reg(R_1ST_SCR_DRV_POS, 0xaf10); | ||
230 | lcd_write_reg(R_2ND_SCR_DRV_POS, 0x0000); | ||
231 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0x7f00); /* ((LCD_HEIGHT - 1) << 8 | 0 */ | ||
232 | lcd_write_reg(R_VERT_RAM_ADDR_POS, 0xaf10); /* ((LCD_WIDTH + 16 - 1) << 8) | 16 */ | ||
233 | lcd_write_reg(R_GAMMA_AMP_ADJ_POS, 0x1600); | ||
234 | lcd_write_reg(R_GAMMA_AMP_ADJ_NEG, 0x0006); | ||
235 | lcd_write_reg(R_DISP_CONTROL, 0x0104); | ||
236 | lcd_write_reg(R_POWER_CONTROL4, 0x0100); | ||
237 | lcd_write_reg(R_POWER_CONTROL5, 0x0d18); | ||
238 | lcd_write_reg(R_POWER_CONTROL3, 0x0000); | ||
239 | udelay(50000); | ||
240 | lcd_write_reg(R_POWER_CONTROL1, 0x0008); | ||
241 | lcd_write_reg(R_POWER_CONTROL3, 0x0000); | ||
242 | lcd_write_reg(R_POWER_CONTROL2, 0x0000); | ||
243 | udelay(50000); | ||
244 | lcd_write_reg(R_POWER_CONTROL5, 0x2d18); | ||
245 | lcd_write_reg(R_POWER_CONTROL3, 0x0000); | ||
246 | udelay(50000); | ||
247 | lcd_write_reg(R_POWER_CONTROL4, 0x0110); | ||
248 | //~ lcd_clear_display(); | ||
249 | lcd_write_reg(R_DISP_CONTROL, 0x0105); | ||
250 | udelay(20000); | ||
251 | lcd_write_reg(R_DISP_CONTROL, 0x0125); | ||
252 | lcd_write_reg(R_DISP_CONTROL, 0x0127); | ||
253 | udelay(20000); | ||
254 | lcd_write_reg(R_DISP_CONTROL, 0x0137); | ||
255 | lcd_send_cmd(R_WRITE_DATA_2_GRAM); | ||
256 | |||
257 | GPIOF_ENABLE |= 0x02; | ||
258 | GPIOF_OUTPUT_EN |= 0x02; | ||
259 | GPIOF_OUTPUT_VAL |= 0x02; | ||
260 | #endif | ||
261 | |||
262 | #ifndef BOOTLOADER | ||
263 | /* The OF won't boot if this is done in the bootloader - ideally we should | ||
264 | tweak the lcd controller speed settings but this will do for now */ | ||
265 | CLCD_CLOCK_SRC |= 0xc0000000; /* Set LCD interface clock to PLL */ | ||
266 | #endif | ||
267 | |||
268 | /* only these bits are needed from the OF init */ | ||
269 | lcd_write_reg(R_DRV_OUTPUT_CONTROL, 0x0215); | ||
270 | lcd_write_reg(R_ENTRY_MODE, 0x1028); | ||
271 | |||
272 | power_on = true; | ||
273 | display_on = true; | ||
274 | y_offset = 0; | ||
275 | disp_control_rev = 0x0004; | ||
276 | lcd_contrast = DEFAULT_CONTRAST_SETTING << 8; | ||
277 | } | ||
278 | |||
279 | /* THE SLEEP AND POWER FUNCTIONS HAVE NOT BEEN MODIFIED FOR THE YH-925 */ | ||
280 | |||
281 | #ifdef HAVE_LCD_SLEEP | ||
282 | static void lcd_power_on(void) | ||
283 | { | ||
284 | /* Be sure standby bit is clear. */ | ||
285 | /* BT2-0=000, DC2-0=000, AP2-0=000, SLP=0, STB=0 */ | ||
286 | lcd_write_reg(R_POWER_CONTROL1, 0x0000); | ||
287 | |||
288 | /** Power ON Sequence **/ | ||
289 | /* Per datasheet Rev.1.10, Jun.21.2003, p. 99 */ | ||
290 | |||
291 | lcd_write_reg(R_START_OSC, 0x0001); /* Start Oscillation */ | ||
292 | /* 10ms or more for oscillation circuit to stabilize */ | ||
293 | sleep(HZ/50); | ||
294 | /* Instruction (1) for power setting; VC2-0, VRH3-0, CAD, | ||
295 | VRL3-0, VCM4-0, VDV4-0 */ | ||
296 | /* VC2-0=001 */ | ||
297 | lcd_write_reg(R_POWER_CONTROL3, 0x0001); | ||
298 | /* VRL3-0=0100, PON=0, VRH3-0=0001 */ | ||
299 | lcd_write_reg(R_POWER_CONTROL4, 0x0401); | ||
300 | /* CAD=1 */ | ||
301 | lcd_write_reg(R_POWER_CONTROL2, 0x8000); | ||
302 | /* VCOMG=0, VDV4-0=xxxxx (19), VCM4-0=11000 */ | ||
303 | lcd_write_reg(R_POWER_CONTROL5, 0x0018 | lcd_contrast); | ||
304 | /* Instruction (2) for power setting; BT2-0, DC2-0, AP2-0 */ | ||
305 | /* BT2-0=000, DC2-0=001, AP2-0=011, SLP=0, STB=0 */ | ||
306 | lcd_write_reg(R_POWER_CONTROL1, 0x002c); | ||
307 | /* Instruction (3) for power setting; VCOMG = "1" */ | ||
308 | /* VCOMG=1, VDV4-0=xxxxx (19), VCM4-0=11000 */ | ||
309 | lcd_write_reg(R_POWER_CONTROL5, 0x2018 | lcd_contrast); | ||
310 | |||
311 | /* 40ms or more; time for step-up circuits 1,2 to stabilize */ | ||
312 | sleep(HZ/25); | ||
313 | |||
314 | /* Instruction (4) for power setting; PON = "1" */ | ||
315 | /* VRL3-0=0100, PON=1, VRH3-0=0001 */ | ||
316 | lcd_write_reg(R_POWER_CONTROL4, 0x0411); | ||
317 | |||
318 | /* 40ms or more; time for step-up circuit 4 to stabilize */ | ||
319 | sleep(HZ/25); | ||
320 | |||
321 | /* Instructions for other mode settings (in register order). */ | ||
322 | /* SM=0, GS=x, SS=0, NL4-0=10011 (G1-G160)*/ | ||
323 | lcd_write_reg(R_DRV_OUTPUT_CONTROL, y_offset ? 0x0013 : 0x0113); /* different to X5 */ | ||
324 | /* FLD1-0=01 (1 field), B/C=1, EOR=1 (C-pat), NW5-0=000000 (1 row) */ | ||
325 | lcd_write_reg(R_DRV_AC_CONTROL, 0x0700); | ||
326 | /* DIT=0, BGR=1, HWM=0, I/D1-0=10, AM=1, LG2-0=000 */ | ||
327 | lcd_write_reg(R_ENTRY_MODE, 0x1028); /* different to X5 */ | ||
328 | /* CP15-0=0000000000000000 */ | ||
329 | lcd_write_reg(R_COMPARE_REG, 0x0000); | ||
330 | /* NO1-0=01, SDT1-0=00, EQ1-0=00, DIV1-0=00, RTN3-00000 */ | ||
331 | lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x4000); | ||
332 | /* SCN4-0=000x0 (G1/G160) */ | ||
333 | /* lcd_write_reg(R_GATE_SCAN_START_POS, y_offset ? 0x0000 : 0x0002); */ | ||
334 | /* VL7-0=0x00 */ | ||
335 | lcd_write_reg(R_VERT_SCROLL_CONTROL, 0x0000); | ||
336 | /* SE17-10(End)=0x9f (159), SS17-10(Start)=0x00 */ | ||
337 | lcd_write_reg(R_1ST_SCR_DRV_POS, 0x9f00); | ||
338 | /* SE27-20(End)=0x5c (92), SS27-20(Start)=0x00 */ | ||
339 | lcd_write_reg(R_2ND_SCR_DRV_POS, 0x5c00); | ||
340 | /* HEA7-0=7f, HSA7-0=00 */ | ||
341 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0x7f00); | ||
342 | /* PKP12-10=0x0, PKP02-00=0x0 */ | ||
343 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS1, 0x0003); | ||
344 | /* PKP32-30=0x4, PKP22-20=0x0 */ | ||
345 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS2, 0x0400); | ||
346 | /* PKP52-50=0x4, PKP42-40=0x7 */ | ||
347 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS3, 0x0407); | ||
348 | /* PRP12-10=0x3, PRP02-00=0x5 */ | ||
349 | lcd_write_reg(R_GAMMA_GRAD_ADJ_POS, 0x0305); | ||
350 | /* PKN12-10=0x0, PKN02-00=0x3 */ | ||
351 | lcd_write_reg(R_GAMMA_FINE_ADJ_NEG1, 0x0003); | ||
352 | /* PKN32-30=0x7, PKN22-20=0x4 */ | ||
353 | lcd_write_reg(R_GAMMA_FINE_ADJ_NEG2, 0x0704); | ||
354 | /* PKN52-50=0x4, PRN42-40=0x7 */ | ||
355 | lcd_write_reg(R_GAMMA_FINE_ADJ_NEG3, 0x0407); | ||
356 | /* PRN12-10=0x5, PRN02-00=0x3 */ | ||
357 | lcd_write_reg(R_GAMMA_GRAD_ADJ_NEG, 0x0503); | ||
358 | /* VRP14-10=0x14, VRP03-00=0x09 */ | ||
359 | lcd_write_reg(R_GAMMA_AMP_ADJ_POS, 0x1409); | ||
360 | /* VRN14-00=0x06, VRN03-00=0x02 */ | ||
361 | lcd_write_reg(R_GAMMA_AMP_ADJ_NEG, 0x0602); | ||
362 | |||
363 | /* 100ms or more; time for step-up circuits to stabilize */ | ||
364 | sleep(HZ/10); | ||
365 | |||
366 | power_on = true; | ||
367 | } | ||
368 | |||
369 | static void lcd_power_off(void) | ||
370 | { | ||
371 | /* Display must be off first */ | ||
372 | if (display_on) | ||
373 | lcd_display_off(); | ||
374 | |||
375 | power_on = false; | ||
376 | |||
377 | /** Power OFF sequence **/ | ||
378 | /* Per datasheet Rev.1.10, Jun.21.2003, p. 99 */ | ||
379 | |||
380 | /* Step-up1 halt setting bit */ | ||
381 | /* BT2-0=110, DC2-0=001, AP2-0=011, SLP=0, STB=0 */ | ||
382 | lcd_write_reg(R_POWER_CONTROL1, 0x062c); | ||
383 | /* Step-up3,4 halt setting bit */ | ||
384 | /* VRL3-0=0100, PON=0, VRH3-0=0001 */ | ||
385 | lcd_write_reg(R_POWER_CONTROL4, 0x0401); | ||
386 | /* VCOMG=0, VDV4-0=10011, VCM4-0=11000 */ | ||
387 | lcd_write_reg(R_POWER_CONTROL5, 0x0018 | lcd_contrast); | ||
388 | |||
389 | /* Wait 100ms or more */ | ||
390 | sleep(HZ/10); | ||
391 | |||
392 | /* Step-up2,amp halt setting bit */ | ||
393 | /* BT2-0=000, DC2-0=000, AP2-0=000, SLP=0, STB=0 */ | ||
394 | lcd_write_reg(R_POWER_CONTROL1, 0x0000); | ||
395 | } | ||
396 | |||
397 | void lcd_sleep(void) | ||
398 | { | ||
399 | if (power_on) | ||
400 | lcd_power_off(); | ||
401 | |||
402 | /* Set standby mode */ | ||
403 | /* BT2-0=000, DC2-0=000, AP2-0=000, SLP=0, STB=1 */ | ||
404 | lcd_write_reg(R_POWER_CONTROL1, 0x0001); | ||
405 | } | ||
406 | #endif | ||
407 | |||
408 | #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) | ||
409 | static void lcd_display_off(void) | ||
410 | { | ||
411 | display_on = false; | ||
412 | |||
413 | /** Display OFF sequence **/ | ||
414 | /* Per datasheet Rev.1.10, Jun.21.2003, p. 97 */ | ||
415 | |||
416 | /* EQ1-0=00 already */ | ||
417 | |||
418 | /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=1, REV=x, D1-0=10 */ | ||
419 | lcd_write_reg(R_DISP_CONTROL, 0x0032 | disp_control_rev); | ||
420 | |||
421 | sleep(HZ/25); /* Wait 2 frames or more */ | ||
422 | |||
423 | /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=0, REV=x, D1-0=10 */ | ||
424 | lcd_write_reg(R_DISP_CONTROL, 0x0022 | disp_control_rev); | ||
425 | |||
426 | sleep(HZ/25); /* Wait 2 frames or more */ | ||
427 | |||
428 | /* PT1-0=00, VLE2-1=00, SPT=0, GON=0, DTE=0, REV=0, D1-0=00 */ | ||
429 | lcd_write_reg(R_DISP_CONTROL, 0x0000); | ||
430 | } | ||
431 | #endif | ||
432 | |||
433 | #if defined(HAVE_LCD_ENABLE) | ||
434 | static void lcd_display_on(void) | ||
435 | { | ||
436 | /* Be sure power is on first */ | ||
437 | if (!power_on) | ||
438 | lcd_power_on(); | ||
439 | |||
440 | /** Display ON Sequence **/ | ||
441 | /* Per datasheet Rev.1.10, Jun.21.2003, p. 97 */ | ||
442 | |||
443 | /* PT1-0=00, VLE2-1=00, SPT=0, GON=0, DTE=0, REV=0, D1-0=01 */ | ||
444 | lcd_write_reg(R_DISP_CONTROL, 0x0001); | ||
445 | |||
446 | sleep(HZ/25); /* Wait 2 frames or more */ | ||
447 | |||
448 | /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=0, REV=x, D1-0=01 */ | ||
449 | lcd_write_reg(R_DISP_CONTROL, 0x0021 | disp_control_rev); | ||
450 | /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=0, REV=x, D1-0=11 */ | ||
451 | lcd_write_reg(R_DISP_CONTROL, 0x0023 | disp_control_rev); | ||
452 | |||
453 | sleep(HZ/25); /* Wait 2 frames or more */ | ||
454 | |||
455 | /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=1, REV=x, D1-0=11 */ | ||
456 | lcd_write_reg(R_DISP_CONTROL, 0x0033 | disp_control_rev); | ||
457 | |||
458 | display_on = true; | ||
459 | } | ||
460 | |||
461 | void lcd_enable(bool on) | ||
462 | { | ||
463 | if (on == display_on) | ||
464 | return; | ||
465 | |||
466 | if (on) | ||
467 | { | ||
468 | lcd_display_on(); | ||
469 | /* Probably out of sync and we don't wanna pepper the code with | ||
470 | lcd_update() calls for this. */ | ||
471 | lcd_update(); | ||
472 | lcd_activation_call_hook(); | ||
473 | } | ||
474 | else | ||
475 | { | ||
476 | lcd_display_off(); | ||
477 | } | ||
478 | } | ||
479 | #endif | ||
480 | |||
481 | #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) | ||
482 | bool lcd_active(void) | ||
483 | { | ||
484 | return display_on; | ||
485 | } | ||
486 | #endif | ||
487 | |||
488 | /*** update functions ***/ | ||
489 | |||
490 | void lcd_yuv_set_options(unsigned options) | ||
491 | { | ||
492 | lcd_yuv_options = options; | ||
493 | } | ||
494 | |||
495 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
496 | extern void lcd_write_yuv420_lines(unsigned char const * const src[3], | ||
497 | int width, | ||
498 | int stride); | ||
499 | extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3], | ||
500 | int width, | ||
501 | int stride, | ||
502 | int x_screen, /* To align dither pattern */ | ||
503 | int y_screen); | ||
504 | |||
505 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
506 | void lcd_blit_yuv(unsigned char * const src[3], | ||
507 | int src_x, int src_y, int stride, | ||
508 | int x, int y, int width, int height) | ||
509 | { | ||
510 | const unsigned char *yuv_src[3]; | ||
511 | const unsigned char *ysrc_max; | ||
512 | int y0; | ||
513 | int options; | ||
514 | |||
515 | /* NOT MODIFIED FOR THE YH-925 */ | ||
516 | |||
517 | if (!display_on) | ||
518 | return; | ||
519 | |||
520 | width &= ~1; | ||
521 | height &= ~1; | ||
522 | |||
523 | /* calculate the drawing region */ | ||
524 | |||
525 | /* The 20GB LCD is actually 128x160 but rotated 90 degrees so the origin | ||
526 | * is actually the bottom left and horizontal and vertical are swapped. | ||
527 | * Rockbox expects the origin to be the top left so we need to use | ||
528 | * 127 - y instead of just y */ | ||
529 | |||
530 | /* max vert << 8 | start vert */ | ||
531 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((x + width - 1) << 8) | x); | ||
532 | |||
533 | y0 = LCD_HEIGHT - 1 - y + y_offset; | ||
534 | |||
535 | /* DIT=0, BGR=1, HWM=0, I/D1-0=10, AM=0, LG2-0=000 */ | ||
536 | lcd_write_reg(R_ENTRY_MODE, 0x1020); | ||
537 | |||
538 | yuv_src[0] = src[0] + src_y * stride + src_x; | ||
539 | yuv_src[1] = src[1] + (src_y * stride >> 2) + (src_x >> 1); | ||
540 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
541 | ysrc_max = yuv_src[0] + height * stride; | ||
542 | |||
543 | options = lcd_yuv_options; | ||
544 | |||
545 | do | ||
546 | { | ||
547 | /* max horiz << 8 | start horiz */ | ||
548 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (y0 << 8) | (y0 - 1)); | ||
549 | |||
550 | /* position cursor (set AD0-AD15) */ | ||
551 | /* start vert << 8 | start horiz */ | ||
552 | lcd_write_reg(R_RAM_ADDR_SET, (x << 8) | y0); | ||
553 | |||
554 | /* start drawing */ | ||
555 | lcd_send_cmd(R_WRITE_DATA_2_GRAM); | ||
556 | |||
557 | if (options & LCD_YUV_DITHER) | ||
558 | { | ||
559 | lcd_write_yuv420_lines_odither(yuv_src, width, stride, | ||
560 | x, y); | ||
561 | y -= 2; | ||
562 | } | ||
563 | else | ||
564 | { | ||
565 | lcd_write_yuv420_lines(yuv_src, width, stride); | ||
566 | } | ||
567 | |||
568 | y0 -= 2; | ||
569 | yuv_src[0] += stride << 1; | ||
570 | yuv_src[1] += stride >> 1; | ||
571 | yuv_src[2] += stride >> 1; | ||
572 | } | ||
573 | while (yuv_src[0] < ysrc_max); | ||
574 | |||
575 | /* DIT=0, BGR=1, HWM=0, I/D1-0=10, AM=1, LG2-0=000 */ | ||
576 | lcd_write_reg(R_ENTRY_MODE, 0x1028); | ||
577 | } | ||
578 | |||
579 | |||
580 | /* Update a fraction of the display. */ | ||
581 | void lcd_update_rect(int x0, int y0, int width, int height) | ||
582 | { | ||
583 | int x1, y1; | ||
584 | int lcd_x0, lcd_x1, lcd_y0, lcd_y1; | ||
585 | unsigned short *addr; | ||
586 | |||
587 | if (!display_on) | ||
588 | return; | ||
589 | |||
590 | /* calculate the drawing region */ | ||
591 | y1 = (y0 + height) - 1; /* max vert */ | ||
592 | x1 = (x0 + width) - 1; /* max horiz */ | ||
593 | |||
594 | if(x1 >= LCD_WIDTH) | ||
595 | x1 = LCD_WIDTH - 1; | ||
596 | if (x1 <= 0) | ||
597 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ | ||
598 | if(y1 >= LCD_HEIGHT) | ||
599 | y1 = LCD_HEIGHT-1; | ||
600 | |||
601 | /* The LCD is actually 128x160 rotated 90 degrees */ | ||
602 | lcd_x0 = (LCD_HEIGHT - 1) - y1 + 4; | ||
603 | lcd_x1 = (LCD_HEIGHT - 1) - y0 + 4; | ||
604 | lcd_y0 = x0 + 16; | ||
605 | lcd_y1 = x1 + 16; | ||
606 | |||
607 | /* set the drawing window */ | ||
608 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (lcd_x1 << 8) | lcd_x0); | ||
609 | lcd_write_reg(R_VERT_RAM_ADDR_POS, (lcd_y1 << 8) | lcd_y0); | ||
610 | |||
611 | /* set the starting position */ | ||
612 | lcd_write_reg(R_RAM_ADDR_SET, (lcd_y0 << 8) | lcd_x1); | ||
613 | |||
614 | /* start drawing */ | ||
615 | lcd_send_cmd(R_WRITE_DATA_2_GRAM); | ||
616 | |||
617 | addr = (unsigned short*)&lcd_framebuffer[y0][x0]; | ||
618 | |||
619 | int c, r; | ||
620 | |||
621 | /* for each row */ | ||
622 | for (r = 0; r < height; r++) { | ||
623 | /* for each column */ | ||
624 | for (c = 0; c < width; c++) { | ||
625 | /* output 1 pixel */ | ||
626 | lcd_send_data(*addr++); | ||
627 | } | ||
628 | |||
629 | addr += (LCD_WIDTH - width); | ||
630 | } | ||
631 | } | ||
632 | |||
633 | /* Update the display. | ||
634 | This must be called after all other LCD functions that change the display. */ | ||
635 | void lcd_update(void) | ||
636 | { | ||
637 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | ||
638 | } | ||