summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Arigo <markarigo@gmail.com>2009-07-01 02:18:49 +0000
committerMark Arigo <markarigo@gmail.com>2009-07-01 02:18:49 +0000
commit4093874f80571f32e2aedd2b09b2be9eb5efc47c (patch)
treef3e2bff8519f60587f9b5db0809c310396cd2e67
parentd12df3a50ee99766ed7dfba797a19ab08cc9aec7 (diff)
downloadrockbox-4093874f80571f32e2aedd2b09b2be9eb5efc47c.tar.gz
rockbox-4093874f80571f32e2aedd2b09b2be9eb5efc47c.zip
Philips SA9200. Add LCD features: enable, sleep, flip, contrast, and invert.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21583 a1c6a512-1295-4272-9138-f99709370657
-rwxr-xr-xfirmware/export/config-sa9200.h24
-rw-r--r--firmware/target/arm/philips/sa9200/backlight-sa9200.c1
-rwxr-xr-xfirmware/target/arm/philips/sa9200/lcd-sa9200.c258
-rw-r--r--firmware/target/arm/philips/sa9200/power-sa9200.c7
4 files changed, 258 insertions, 32 deletions
diff --git a/firmware/export/config-sa9200.h b/firmware/export/config-sa9200.h
index 37c0b50035..30aad93898 100755
--- a/firmware/export/config-sa9200.h
+++ b/firmware/export/config-sa9200.h
@@ -42,18 +42,21 @@
42#define LCD_DEPTH 16 /* 65536 colours */ 42#define LCD_DEPTH 16 /* 65536 colours */
43#define LCD_PIXELFORMAT RGB565 /* rgb565 */ 43#define LCD_PIXELFORMAT RGB565 /* rgb565 */
44 44
45#ifndef BOOTLOADER
45/* define this if you have LCD enable function */ 46/* define this if you have LCD enable function */
46/* #define HAVE_LCD_ENABLE */ 47#define HAVE_LCD_ENABLE
47 48
48/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE 49/* Define this if your LCD can be put to sleep.
49 should be defined as well. */ 50 HAVE_LCD_ENABLE should be defined as well. */
50/* #define HAVE_LCD_SLEEP */ 51#define HAVE_LCD_SLEEP
52#define HAVE_LCD_SLEEP_SETTING
53#endif
51 54
52/* define this if you can flip your LCD */ 55/* define this if you can flip your LCD */
53/* #define HAVE_LCD_FLIP */ 56#define HAVE_LCD_FLIP
54 57
55/* define this if you can invert the colours on your LCD */ 58/* define this if you can invert the colours on your LCD */
56/* #define HAVE_LCD_INVERT */ 59#define HAVE_LCD_INVERT
57 60
58/* #define IRAM_LCDFRAMEBUFFER IDATA_ATTR *//* put the lcd frame buffer in IRAM */ 61/* #define IRAM_LCDFRAMEBUFFER IDATA_ATTR *//* put the lcd frame buffer in IRAM */
59 62
@@ -150,9 +153,16 @@
150/* Define this to the CPU frequency */ 153/* Define this to the CPU frequency */
151#define CPU_FREQ 75000000 154#define CPU_FREQ 75000000
152 155
153/* Type of LCD TODO: hopefully the same as the x5 but check this*/ 156/* Type of LCD */
154#define CONFIG_LCD LCD_SA9200 157#define CONFIG_LCD LCD_SA9200
155 158
159/* Define this if your LCD can set contrast */
160#define HAVE_LCD_CONTRAST
161
162#define MIN_CONTRAST_SETTING 0
163#define MAX_CONTRAST_SETTING 31
164#define DEFAULT_CONTRAST_SETTING 22 /* Match boot contrast */
165
156/* USB On-the-go */ 166/* USB On-the-go */
157#define CONFIG_USBOTG USBOTG_ARC 167#define CONFIG_USBOTG USBOTG_ARC
158 168
diff --git a/firmware/target/arm/philips/sa9200/backlight-sa9200.c b/firmware/target/arm/philips/sa9200/backlight-sa9200.c
index 22aae1ae6b..0de4c05df5 100644
--- a/firmware/target/arm/philips/sa9200/backlight-sa9200.c
+++ b/firmware/target/arm/philips/sa9200/backlight-sa9200.c
@@ -25,6 +25,7 @@
25#include "ascodec.h" 25#include "ascodec.h"
26#include "as3514.h" 26#include "as3514.h"
27#include "synaptics-mep.h" 27#include "synaptics-mep.h"
28#include "lcd.h"
28 29
29void _backlight_set_brightness(int brightness) 30void _backlight_set_brightness(int brightness)
30{ 31{
diff --git a/firmware/target/arm/philips/sa9200/lcd-sa9200.c b/firmware/target/arm/philips/sa9200/lcd-sa9200.c
index d7fe2e9c12..3937c078c6 100755
--- a/firmware/target/arm/philips/sa9200/lcd-sa9200.c
+++ b/firmware/target/arm/philips/sa9200/lcd-sa9200.c
@@ -24,6 +24,19 @@
24#include "kernel.h" 24#include "kernel.h"
25#include "system.h" 25#include "system.h"
26 26
27/* Settings to remember when display is turned off */
28static bool invert;
29static bool flip;
30static int contrast;
31
32static bool power_on;
33static bool display_on;
34
35/* Forward declarations */
36#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
37static void lcd_display_off(void);
38#endif
39
27/* The SA9200 controller closely matches the register defines for the 40/* The SA9200 controller closely matches the register defines for the
28 Samsung S6D0151 */ 41 Samsung S6D0151 */
29#define R_START_OSC 0x00 42#define R_START_OSC 0x00
@@ -95,12 +108,11 @@ static void lcd_write_reg(unsigned reg, unsigned data)
95 lcd_send_data(data); 108 lcd_send_data(data);
96} 109}
97 110
111/* LCD init */
98void lcd_init_device(void) 112void lcd_init_device(void)
99{ 113{
100#if 0 114#if 0
101 /* This is the init done by the OF bootloader. 115 /* This is done by the OF bootloader, no need to redo */
102 Re-initializing the lcd causes it to flash
103 a white screen, so for now disable this. */
104 DEV_INIT1 &= ~0x3000; 116 DEV_INIT1 &= ~0x3000;
105 DEV_INIT1 = DEV_INIT1; 117 DEV_INIT1 = DEV_INIT1;
106 DEV_INIT2 &= ~0x400; 118 DEV_INIT2 &= ~0x400;
@@ -115,82 +127,272 @@ void lcd_init_device(void)
115 LCD1_CONTROL &= ~0x800; 127 LCD1_CONTROL &= ~0x800;
116 LCD1_CONTROL &= ~0x400; 128 LCD1_CONTROL &= ~0x400;
117 udelay(30000); 129 udelay(30000);
130#endif
131
132 power_on = true;
133 display_on = true;
134 invert = false;
135 flip = false;
136 contrast = DEFAULT_CONTRAST_SETTING;
137}
118 138
139#ifdef HAVE_LCD_SLEEP
140static void lcd_power_on(void)
141{
119 LCD1_CONTROL |= 0x1; 142 LCD1_CONTROL |= 0x1;
120 143
144 /** Power ON Sequence **/
145
146 /* Start Oscillation */
121 lcd_write_reg(R_START_OSC, 0x0001); 147 lcd_write_reg(R_START_OSC, 0x0001);
122 udelay(50000); 148
149 sleep(HZ/20); /* 50ms or more */
150
151 /* DSTB=0, SAP2-0=001, BT2-0=101, DC2-0=000, AP2-0=001, SLP=0, STB=0 */
152 lcd_write_reg(R_POWER_CONTROL1, 0x0d04);
123 153
154 /* VR1C=0, VRN14-10=10111, VRP14-10=11111 */
124 lcd_write_reg(R_GAMMA_CONTROL1, 0x171f); 155 lcd_write_reg(R_GAMMA_CONTROL1, 0x171f);
156
157 /* SVC3-0=0000, VRH5-4=01 */
125 lcd_write_reg(R_POWER_CONTROL2, 0x0001); 158 lcd_write_reg(R_POWER_CONTROL2, 0x0001);
126 lcd_write_reg(R_POWER_CONTROL3, 0x08cd); 159
127 lcd_write_reg(R_POWER_CONTROL4, 0x0416); 160 /* VCMR=1, PON=0, VRH3-0=1101 */
161 lcd_write_reg(R_POWER_CONTROL3, 0x080d);
162
163 /* VDV6-0=0000100, VCOMG=0, VCM6-0=xxxxxxx */
164 lcd_write_reg(R_POWER_CONTROL4, 0x0400 | contrast);
165
166 /* DSTB=0, SAP2-0=010, BT2-0=010, DC2-0=000, AP2-0=010, SLP=0, STB=0 */
128 lcd_write_reg(R_POWER_CONTROL1, 0x1208); 167 lcd_write_reg(R_POWER_CONTROL1, 0x1208);
129 udelay(50000);
130 168
169 sleep(HZ/20); /* 50ms or more */
170
171 /* VCMR=1, PON=1, VRH3-0=1100 */
131 lcd_write_reg(R_POWER_CONTROL3, 0x081c); 172 lcd_write_reg(R_POWER_CONTROL3, 0x081c);
132 udelay(200000);
133 173
134 lcd_write_reg(R_DRV_OUTPUT_CONTROL, 0x0a0c); 174 sleep(HZ/20); /* OF bootlaoder uses 200ms, no delay in OF firmware */
175
176 /* Instructions for other mode settings (in register order). */
177
178 lcd_write_reg(R_DRV_OUTPUT_CONTROL, flip ? 0x090c : 0x0a0c);
179
180 /* FL1-0=10, FDL=0 */
135 lcd_write_reg(R_INVERSION_CONTROL, 0x0200); 181 lcd_write_reg(R_INVERSION_CONTROL, 0x0200);
182
183 /* BGR=1, MDT1-0=00, I/D1-0=11, AM=0 */
136 lcd_write_reg(R_ENTRY_MODE, 0x1030); 184 lcd_write_reg(R_ENTRY_MODE, 0x1030);
185
186 /* PT1-0=00, SPT=0, GON=0, DTE=0, CL=0, REV=1, D1-0=01 */
137 lcd_write_reg(R_DISP_CONTROL, 0x0005); 187 lcd_write_reg(R_DISP_CONTROL, 0x0005);
188
189 /* FP3-0=0011, BT3-0=1010 */
138 lcd_write_reg(R_BLANK_PERIOD_CONTROL, 0x030a); 190 lcd_write_reg(R_BLANK_PERIOD_CONTROL, 0x030a);
191
192 /* DIV1-0=00, RTN3-0=0000 */
139 lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x0000); 193 lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x0000);
194
195 /* RM=0, DM1-0=00, RIM1-0=00 */
140 lcd_write_reg(R_EXT_INTERFACE_CONTROL, 0x0000); 196 lcd_write_reg(R_EXT_INTERFACE_CONTROL, 0x0000);
141 197
198 /* PKP1=0x0, PKP0=0x0 */
142 lcd_write_reg(R_GAMMA_FINE_ADJ_POS1, 0x0000); 199 lcd_write_reg(R_GAMMA_FINE_ADJ_POS1, 0x0000);
200
201 /* PKP3=0x2, PKP2=0x4 */
143 lcd_write_reg(R_GAMMA_FINE_ADJ_POS2, 0x0204); 202 lcd_write_reg(R_GAMMA_FINE_ADJ_POS2, 0x0204);
203
204 /* PKP5=0x0, PKP4=0x1 */
144 lcd_write_reg(R_GAMMA_FINE_ADJ_POS3, 0x0001); 205 lcd_write_reg(R_GAMMA_FINE_ADJ_POS3, 0x0001);
206
207 /* PRP1=0x6, PRP0=0x0 */
145 lcd_write_reg(R_GAMMA_GRAD_ADJ_POS, 0x0600); 208 lcd_write_reg(R_GAMMA_GRAD_ADJ_POS, 0x0600);
209
210 /* PKN1=0x6, PKN0=0x7 */
146 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG1, 0x0607); 211 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG1, 0x0607);
212
213 /* PKN3=0x3, PKN2=0x5 */
147 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG2, 0x0305); 214 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG2, 0x0305);
215
216 /* PKN5=0x7, PKN4=0x7 */
148 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG3, 0x0707); 217 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG3, 0x0707);
218
219 /* PRN1=0x0, PRN0=0x6 */
149 lcd_write_reg(R_GAMMA_GRAD_ADJ_NEG, 0x0006); 220 lcd_write_reg(R_GAMMA_GRAD_ADJ_NEG, 0x0006);
221
222 /* VRN0=0x4, VRP=0x0 */
150 lcd_write_reg(R_GAMMA_CONTROL3, 0x0400); 223 lcd_write_reg(R_GAMMA_CONTROL3, 0x0400);
151 224
225 /* SCN=0x0 */
152 lcd_write_reg(R_GATE_SCAN_START_POS, 0x0000); 226 lcd_write_reg(R_GATE_SCAN_START_POS, 0x0000);
227
228 /* SE1=LCD_HEIGHT-1, SS1=0x0 */
153 lcd_write_reg(R_1ST_SCR_DRV_POS, 0x9f00); 229 lcd_write_reg(R_1ST_SCR_DRV_POS, 0x9f00);
230
231 /* SE2=0x0, SS2=0x0 */
154 lcd_write_reg(R_2ND_SCR_DRV_POS, 0x0000); 232 lcd_write_reg(R_2ND_SCR_DRV_POS, 0x0000);
233
234 /* HEA=LCD_WIDTH-1, HSA=0x0 */
155 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0x7f00); 235 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0x7f00);
236
237 /* VEA=LCD_HEIGHT-1, VSA=0x0 */
156 lcd_write_reg(R_VERT_RAM_ADDR_POS, 0x9f00); 238 lcd_write_reg(R_VERT_RAM_ADDR_POS, 0x9f00);
157 239
240 /* Unknown registers */
158 lcd_write_reg(0x00a8, 0x0125); 241 lcd_write_reg(0x00a8, 0x0125);
159 lcd_write_reg(0x00a9, 0x0014); 242 lcd_write_reg(0x00a9, 0x0014);
160 lcd_write_reg(0x00a7, 0x0022); 243 lcd_write_reg(0x00a7, 0x0022);
161 244
245 power_on = true;
246}
247
248static void lcd_power_off(void)
249{
250 /* Display must be off first */
251 if (display_on)
252 lcd_display_off();
253
254 power_on = false;
255
256 /** Power OFF sequence **/
257
258 /* DSTB=0, SAP2-0=000, BT2-0=001, DC2-0=000, AP2-0=000, SLP=0, STB=0 */
259 lcd_write_reg(R_POWER_CONTROL1, 0x0100);
260
261 /* VCMR=1, PON=0, VRH3-0=1101 */
262 lcd_write_reg(R_POWER_CONTROL3, 0x080d);
263}
264
265void lcd_sleep(void)
266{
267 if (power_on)
268 lcd_power_off();
269
270 /* Set standby mode */
271
272 /* PT1-0=00, SPT=0, GON=1, DTE=1, CL=0, REV=1, D1-0=10 */
273 lcd_write_reg(R_DISP_CONTROL, 0x0036);
274
275 /* DSTB=0, SAP2-0=000, BT2-0=101, DC2-0=000, AP2-0=000, SLP=0, STB=1 */
276 lcd_write_reg(R_POWER_CONTROL1, 0x0501);
277
278 LCD1_CONTROL &= ~0xffff0001;
279}
280#endif
281
282#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
283static void lcd_display_off(void)
284{
285 display_on = false;
286
287 /** Display OFF sequence **/
288
289 /* PT1-0=10, SPT=0, GON=1, DTE=1, CL=0, REV=1, D1-0=10 */
290 lcd_write_reg(R_DISP_CONTROL, 0x1036);
291
292 sleep(HZ/25); /* 2 or more frames */
293
294 /* PT1-0=10, SPT=0, GON=1, DTE=0, CL=0, REV=1, D1-0=00 */
295 lcd_write_reg(R_DISP_CONTROL, 0x1034);
296
297 sleep(HZ/500); /* 1ms or more */
298
299 /* PT1-0=10, SPT=0, GON=0, DTE=0, CL=0, REV=1, D1-0=00 */
300 lcd_write_reg(R_DISP_CONTROL, 0x1004);
301
302 sleep(HZ/25); /* 2 or more frames */
303}
304#endif
305
306#if defined(HAVE_LCD_ENABLE)
307static void lcd_display_on(void)
308{
309 /* Be sure power is on first */
310 if (!power_on)
311 lcd_power_on();
312
313 /** Display ON Sequence **/
314
315 /* PT1-0=00, SPT=0, GON=1, DTE=0, CL=0, REV=0, D1-0=01 */
162 lcd_write_reg(R_DISP_CONTROL, 0x0021); 316 lcd_write_reg(R_DISP_CONTROL, 0x0021);
163 udelay(40000); 317
318 sleep(HZ/500); /* 1ms or more */
319
320 /* PT1-0=00, SPT=0, GON=1, DTE=0, CL=0, REV=0, D1-0=11 */
164 lcd_write_reg(R_DISP_CONTROL, 0x0023); 321 lcd_write_reg(R_DISP_CONTROL, 0x0023);
165 udelay(40000);
166 lcd_write_reg(R_DISP_CONTROL, 0x1037);
167 322
168 lcd_write_reg(R_RAM_ADDR_SET, 0x0000); 323 sleep(HZ/25); /* 2 or more frames */
324
325 /* PT1-0=10, SPT=0, GON=1, DTE=1, CL=0, REV=x, D1-0=11 */
326 lcd_write_reg(R_DISP_CONTROL, invert ? 0x1033 : 0x1037);
327
328 display_on = true;
329}
330
331void lcd_enable(bool on)
332{
333 if (on == display_on)
334 return;
335
336 if (on)
337 {
338 lcd_display_on();
339 /* Probably out of sync and we don't wanna pepper the code with
340 lcd_update() calls for this. */
341 lcd_update();
342 lcd_activation_call_hook();
343 }
344 else
345 {
346 lcd_display_off();
347 }
348}
169#endif 349#endif
350
351#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
352bool lcd_active(void)
353{
354 return display_on;
170} 355}
356#endif
171 357
172/*** hardware configuration ***/ 358/*** hardware configuration ***/
173#if 0
174int lcd_default_contrast(void) 359int lcd_default_contrast(void)
175{ 360{
176 return DEFAULT_CONTRAST_SETTING; 361 return DEFAULT_CONTRAST_SETTING;
177} 362}
178#endif
179 363
180void lcd_set_contrast(int val) 364void lcd_set_contrast(int val)
181{ 365{
182 (void)val; 366 contrast = val & 0x7f;
367
368 if (!display_on)
369 return;
370
371 /* VDV6-0=0000100, VCOMG=0, VCM6-0=xxxxxxx */
372 lcd_write_reg(R_POWER_CONTROL4, 0x0400 | contrast);
183} 373}
184 374
185void lcd_set_invert_display(bool yesno) 375void lcd_set_invert_display(bool yesno)
186{ 376{
187 (void)yesno; 377 invert = yesno;
378
379 if (!display_on)
380 return;
381
382 /* PT1-0=10, SPT=0, GON=1, DTE=1, CL=0, REV=x, D1-0=11 */
383 lcd_write_reg(R_DISP_CONTROL, invert ? 0x1033 : 0x1037);
188} 384}
189 385
190/* turn the display upside down (call lcd_update() afterwards) */ 386/* turn the display upside down (call lcd_update() afterwards) */
191void lcd_set_flip(bool yesno) 387void lcd_set_flip(bool yesno)
192{ 388{
193 (void)yesno; 389 flip = yesno;
390
391 if (!display_on)
392 return;
393
394 /* DPL=0, EPL=1, SM=0, GS=x, SS=x, NL4-0=01100 */
395 lcd_write_reg(R_DRV_OUTPUT_CONTROL, flip ? 0x090c : 0x0a0c);
194} 396}
195 397
196void lcd_yuv_set_options(unsigned options) 398void lcd_yuv_set_options(unsigned options)
@@ -224,21 +426,27 @@ void lcd_update(void)
224void lcd_update_rect(int x, int y, int width, int height) 426void lcd_update_rect(int x, int y, int width, int height)
225{ 427{
226 const fb_data *addr; 428 const fb_data *addr;
227 429
228 if (x + width >= LCD_WIDTH) 430 if (!display_on)
431 return;
432
433 if (x + width > LCD_WIDTH)
229 width = LCD_WIDTH - x; 434 width = LCD_WIDTH - x;
230 if (y + height >= LCD_HEIGHT) 435
436 if (y + height > LCD_HEIGHT)
231 height = LCD_HEIGHT - y; 437 height = LCD_HEIGHT - y;
232 438
233 if ((width <= 0) || (height <= 0)) 439 if ((width <= 0) || (height <= 0))
234 return; /* Nothing left to do. */ 440 return; /* Nothing left to do. */
235 441
236 addr = &lcd_framebuffer[y][x]; 442 addr = &lcd_framebuffer[y][x];
237 443
238 do { 444 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, ((x + width - 1) << 8) | x);
239 lcd_write_reg(R_RAM_ADDR_SET, ((y++ & 0xff) << 8) | (x & 0xff)); 445 lcd_write_reg(R_VERT_RAM_ADDR_POS, ((y + height -1) << 8) | y);
240 lcd_send_command(R_WRITE_DATA_2_GRAM); 446 lcd_write_reg(R_RAM_ADDR_SET, ((y & 0xff) << 8) | (x & 0xff));
447 lcd_send_command(R_WRITE_DATA_2_GRAM);
241 448
449 do {
242 int w = width; 450 int w = width;
243 do { 451 do {
244 lcd_send_data(*addr++); 452 lcd_send_data(*addr++);
diff --git a/firmware/target/arm/philips/sa9200/power-sa9200.c b/firmware/target/arm/philips/sa9200/power-sa9200.c
index e0bdfcf8ea..236dd72a72 100644
--- a/firmware/target/arm/philips/sa9200/power-sa9200.c
+++ b/firmware/target/arm/philips/sa9200/power-sa9200.c
@@ -26,6 +26,7 @@
26#include "as3514.h" 26#include "as3514.h"
27#include "power.h" 27#include "power.h"
28#include "synaptics-mep.h" 28#include "synaptics-mep.h"
29#include "lcd.h"
29#include "logf.h" 30#include "logf.h"
30 31
31void power_init(void) 32void power_init(void)
@@ -72,6 +73,12 @@ void power_off(void)
72{ 73{
73 char byte; 74 char byte;
74 75
76 /* Backlight off */
77 ascodec_write(AS3514_DCDC15, 0);
78
79 /* LCD off/sleep (otherwise the image slowly fades out) */
80 lcd_sleep();
81
75 /* Send shutdown command to PMU */ 82 /* Send shutdown command to PMU */
76 byte = ascodec_read(AS3514_SYSTEM); 83 byte = ascodec_read(AS3514_SYSTEM);
77 byte &= ~0x1; 84 byte &= ~0x1;