summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/export/config/ipod6g.h4
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/backlight-ipod6g.c10
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/lcd-ipod6g.c267
3 files changed, 235 insertions, 46 deletions
diff --git a/firmware/export/config/ipod6g.h b/firmware/export/config/ipod6g.h
index 16e114bf9b..1941074d57 100644
--- a/firmware/export/config/ipod6g.h
+++ b/firmware/export/config/ipod6g.h
@@ -93,8 +93,8 @@
93/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE 93/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE
94 should be defined as well. */ 94 should be defined as well. */
95#ifndef BOOTLOADER 95#ifndef BOOTLOADER
96//TODO: #define HAVE_LCD_SLEEP 96#define HAVE_LCD_SLEEP
97//TODO: #define HAVE_LCD_SLEEP_SETTING 97#define HAVE_LCD_SLEEP_SETTING
98#endif 98#endif
99 99
100#define CONFIG_KEYPAD IPOD_4G_PAD 100#define CONFIG_KEYPAD IPOD_4G_PAD
diff --git a/firmware/target/arm/s5l8702/ipod6g/backlight-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/backlight-ipod6g.c
index dc21d161de..481a2643bb 100644
--- a/firmware/target/arm/s5l8702/ipod6g/backlight-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/backlight-ipod6g.c
@@ -44,7 +44,7 @@ void _backlight_on(void)
44 { 44 {
45 lcd_awake(); 45 lcd_awake();
46 lcd_update(); 46 lcd_update();
47 sleep(HZ/8); 47 sleep(HZ/20);
48 } 48 }
49#endif 49#endif
50 pmu_write(0x29, 1); 50 pmu_write(0x29, 1);
@@ -57,9 +57,11 @@ void _backlight_off(void)
57 57
58bool _backlight_init(void) 58bool _backlight_init(void)
59{ 59{
60 pmu_write(0x2a, 6); 60 /* LEDCTL: overvoltage protection enabled, OCP limit is 500mA */
61 pmu_write(0x28, 0x20); 61 pmu_write(0x2a, 0x05);
62 pmu_write(0x2b, 20); 62
63 pmu_write(0x2b, 0x14); /* T_dimstep = 16 * value / 32768 */
64 _backlight_set_brightness(DEFAULT_BRIGHTNESS_SETTING);
63 65
64 _backlight_on(); 66 _backlight_on();
65 67
diff --git a/firmware/target/arm/s5l8702/ipod6g/lcd-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/lcd-ipod6g.c
index e7a9cf4141..c1071e31b1 100644
--- a/firmware/target/arm/s5l8702/ipod6g/lcd-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/lcd-ipod6g.c
@@ -53,15 +53,159 @@ static struct dma_lli lcd_lli[(LCD_WIDTH * LCD_HEIGHT - 1) / 0xfff] CACHEALIGN_A
53static struct semaphore lcd_wakeup; 53static struct semaphore lcd_wakeup;
54static struct mutex lcd_mutex; 54static struct mutex lcd_mutex;
55static uint16_t lcd_dblbuf[LCD_HEIGHT][LCD_WIDTH]; 55static uint16_t lcd_dblbuf[LCD_HEIGHT][LCD_WIDTH];
56static bool lcd_ispowered;
56 57
58#define SLEEP 0
59#define CMD16 1
60#define DATA16 2
61#define REG15 3
62#define END 0xff
57 63
58static inline void s5l_lcd_write_cmd_data(int cmd, int data) 64/* powersave sequences */
65
66unsigned short lcd_sleep_sequence_01[] =
67{
68 CMD16, 0x028, /* Display Off */
69 SLEEP, 0x005, /* 50 ms */
70 CMD16, 0x010, /* Sleep In Mode */
71 SLEEP, 0x005, /* 50 ms */
72 END
73};
74
75unsigned short lcd_deep_stby_sequence_23[] =
76{
77 /* Display Off */
78 REG15, 0x007, 0x0172,
79 REG15, 0x030, 0x03ff,
80 SLEEP, 0x00a,
81 REG15, 0x007, 0x0120,
82 REG15, 0x030, 0x0000,
83 REG15, 0x100, 0x0780,
84 REG15, 0x007, 0x0000,
85 REG15, 0x101, 0x0260,
86 REG15, 0x102, 0x00a9,
87 SLEEP, 0x003,
88 REG15, 0x100, 0x0700,
89
90 /* Deep Standby Mode */
91 REG15, 0x100, 0x0704,
92 SLEEP, 0x005,
93 END
94};
95
96#ifdef HAVE_LCD_SLEEP
97/* init sequences */
98
99unsigned short lcd_init_sequence_01[] =
100{
101 CMD16, 0x011, /* Sleep Out Mode */
102 SLEEP, 0x006, /* 60 ms */
103 CMD16, 0x029, /* Display On */
104 END
105};
106
107unsigned short lcd_init_sequence_23[] =
108{
109 /* Display settings */
110 REG15, 0x008, 0x0808,
111 REG15, 0x010, 0x0013,
112 REG15, 0x011, 0x0300,
113 REG15, 0x012, 0x0101,
114 REG15, 0x013, 0x0a03,
115 REG15, 0x014, 0x0a0e,
116 REG15, 0x015, 0x0a19,
117 REG15, 0x016, 0x2402,
118 REG15, 0x018, 0x0001,
119 REG15, 0x090, 0x0021,
120
121 /* Gamma settings */
122 REG15, 0x300, 0x0307,
123 REG15, 0x301, 0x0003,
124 REG15, 0x302, 0x0402,
125 REG15, 0x303, 0x0303,
126 REG15, 0x304, 0x0300,
127 REG15, 0x305, 0x0407,
128 REG15, 0x306, 0x1c04,
129 REG15, 0x307, 0x0307,
130 REG15, 0x308, 0x0003,
131 REG15, 0x309, 0x0402,
132 REG15, 0x30a, 0x0303,
133 REG15, 0x30b, 0x0300,
134 REG15, 0x30c, 0x0407,
135 REG15, 0x30d, 0x1c04,
136
137 REG15, 0x310, 0x0707,
138 REG15, 0x311, 0x0407,
139 REG15, 0x312, 0x0306,
140 REG15, 0x313, 0x0303,
141 REG15, 0x314, 0x0300,
142 REG15, 0x315, 0x0407,
143 REG15, 0x316, 0x1c01,
144 REG15, 0x317, 0x0707,
145 REG15, 0x318, 0x0407,
146 REG15, 0x319, 0x0306,
147 REG15, 0x31a, 0x0303,
148 REG15, 0x31b, 0x0300,
149 REG15, 0x31c, 0x0407,
150 REG15, 0x31d, 0x1c01,
151
152 REG15, 0x320, 0x0206,
153 REG15, 0x321, 0x0102,
154 REG15, 0x322, 0x0404,
155 REG15, 0x323, 0x0303,
156 REG15, 0x324, 0x0300,
157 REG15, 0x325, 0x0407,
158 REG15, 0x326, 0x1c1f,
159 REG15, 0x327, 0x0206,
160 REG15, 0x328, 0x0102,
161 REG15, 0x329, 0x0404,
162 REG15, 0x32a, 0x0303,
163 REG15, 0x32b, 0x0300,
164 REG15, 0x32c, 0x0407,
165 REG15, 0x32d, 0x1c1f,
166
167 /* GRAM and Base Imagen settings (ili9326ds) */
168 REG15, 0x400, 0x001d,
169 REG15, 0x401, 0x0001,
170 REG15, 0x205, 0x0060,
171
172 /* Power settings */
173 REG15, 0x007, 0x0001,
174 REG15, 0x031, 0x0071,
175 REG15, 0x110, 0x0001,
176 REG15, 0x100, 0x17b0,
177 REG15, 0x101, 0x0220,
178 REG15, 0x102, 0x00bd,
179 REG15, 0x103, 0x1500,
180 REG15, 0x105, 0x0103,
181 REG15, 0x106, 0x0105,
182
183 /* Display On */
184 REG15, 0x007, 0x0021,
185 REG15, 0x001, 0x0110,
186 REG15, 0x003, 0x0230,
187 REG15, 0x002, 0x0500,
188 REG15, 0x007, 0x0031,
189 REG15, 0x030, 0x0007,
190 SLEEP, 0x003,
191 REG15, 0x030, 0x03ff,
192 SLEEP, 0x006,
193 REG15, 0x007, 0x0072,
194 SLEEP, 0x00f,
195 REG15, 0x007, 0x0173,
196 END
197};
198#endif
199
200static inline void s5l_lcd_write_reg(int cmd, unsigned int data)
59{ 201{
60 while (LCD_STATUS & 0x10); 202 while (LCD_STATUS & 0x10);
61 LCD_WCMD = cmd; 203 LCD_WCMD = cmd;
62 204
63 while (LCD_STATUS & 0x10); 205 while (LCD_STATUS & 0x10);
64 LCD_WDATA = (data & 0xff) | ((data & 0x7f00) << 1); 206 /* 16-bit/1-transfer data format (ili9320ds s7.2.2) */
207 LCD_WDATA = (data & 0x78ff) |
208 ((data & 0x0300) << 1) | ((data & 0x0400) << 5);
65} 209}
66 210
67static inline void s5l_lcd_write_cmd(unsigned short cmd) 211static inline void s5l_lcd_write_cmd(unsigned short cmd)
@@ -76,6 +220,32 @@ static inline void s5l_lcd_write_data(unsigned short data)
76 LCD_WDATA = data; 220 LCD_WDATA = data;
77} 221}
78 222
223static void lcd_run_sequence(unsigned short *seq)
224{
225 unsigned short tmp;
226
227 while (1) switch (*seq++)
228 {
229 case SLEEP:
230 sleep(*seq++);
231 break;
232 case CMD16:
233 s5l_lcd_write_cmd(*seq++);
234 break;
235 case DATA16:
236 s5l_lcd_write_data(*seq++);
237 break;
238 case REG15:
239 tmp = *seq++; /* avoid compiler warning */
240 s5l_lcd_write_reg(tmp, *seq++);
241 break;
242 case END:
243 default:
244 /* bye */
245 return;
246 }
247}
248
79/*** hardware configuration ***/ 249/*** hardware configuration ***/
80 250
81int lcd_default_contrast(void) 251int lcd_default_contrast(void)
@@ -100,50 +270,57 @@ void lcd_set_flip(bool yesno)
100 270
101bool lcd_active(void) 271bool lcd_active(void)
102{ 272{
103 return true; 273 return lcd_ispowered;
104} 274}
105 275
106void lcd_shutdown(void) 276void lcd_shutdown(void)
107{ 277{
108 mutex_lock(&lcd_mutex);
109 pmu_write(0x2b, 0); /* Kill the backlight, instantly. */ 278 pmu_write(0x2b, 0); /* Kill the backlight, instantly. */
110 pmu_write(0x29, 0); 279 pmu_write(0x29, 0);
111 280
112 if (lcd_type & 2) 281 lcd_sleep();
113 { 282}
114 s5l_lcd_write_cmd_data(0x7, 0x172); 283
115 s5l_lcd_write_cmd_data(0x30, 0x3ff); 284void lcd_sleep(void)
116 sleep(HZ / 10); 285{
117 s5l_lcd_write_cmd_data(0x7, 0x120); 286 mutex_lock(&lcd_mutex);
118 s5l_lcd_write_cmd_data(0x30, 0x0); 287
119 s5l_lcd_write_cmd_data(0x100, 0x780); 288 lcd_run_sequence((lcd_type & 2) ? lcd_deep_stby_sequence_23
120 s5l_lcd_write_cmd_data(0x7, 0x0); 289 : lcd_sleep_sequence_01);
121 s5l_lcd_write_cmd_data(0x101, 0x260); 290
122 s5l_lcd_write_cmd_data(0x102, 0xa9); 291 /* mask lcd controller clock gate */
123 sleep(HZ / 30); 292 PWRCON(0) |= (1 << 1);
124 s5l_lcd_write_cmd_data(0x100, 0x700); 293
125 s5l_lcd_write_cmd_data(0x100, 0x704); 294 lcd_ispowered = false;
126 } 295
127 else if (lcd_type == 1)
128 {
129 s5l_lcd_write_cmd(0x28);
130 s5l_lcd_write_cmd(0x10);
131 sleep(HZ / 10);
132 }
133 else
134 {
135 s5l_lcd_write_cmd(0x28);
136 sleep(HZ / 20);
137 s5l_lcd_write_cmd(0x10);
138 sleep(HZ / 20);
139 }
140 mutex_unlock(&lcd_mutex); 296 mutex_unlock(&lcd_mutex);
141} 297}
142 298
143#ifdef HAVE_LCD_SLEEP 299#ifdef HAVE_LCD_SLEEP
144void lcd_sleep(void) 300void lcd_awake(void)
145{ 301{
146 lcd_shutdown(); 302 mutex_lock(&lcd_mutex);
303
304 /* unmask lcd controller clock gate */
305 PWRCON(0) &= ~(1 << 1);
306
307 if (lcd_type & 2) {
308 /* release from deep standby mode (ili9320ds s12.3) */
309 for (int i = 0; i < 6; i++) {
310 s5l_lcd_write_cmd(0x000);
311 udelay(1000);
312 }
313
314 lcd_run_sequence(lcd_init_sequence_23);
315 }
316 else
317 lcd_run_sequence(lcd_init_sequence_01);
318
319 lcd_ispowered = true;
320
321 mutex_unlock(&lcd_mutex);
322
323 send_event(LCD_EVENT_ACTIVATION, NULL);
147} 324}
148#endif 325#endif
149 326
@@ -156,6 +333,8 @@ void lcd_init_device(void)
156 lcd_type = (PDAT6 & 0x30) >> 4; 333 lcd_type = (PDAT6 & 0x30) >> 4;
157 while (!(LCD_STATUS & 0x2)); 334 while (!(LCD_STATUS & 0x2));
158 LCD_CONFIG = 0x80100db0; 335 LCD_CONFIG = 0x80100db0;
336
337 lcd_ispowered = true;
159} 338}
160 339
161/*** Update functions ***/ 340/*** Update functions ***/
@@ -190,13 +369,13 @@ static void displaylcd_setup(int x, int y, int width, int height)
190 int ye = (y + height) - 1; /* max vert */ 369 int ye = (y + height) - 1; /* max vert */
191 370
192 if (lcd_type & 2) { 371 if (lcd_type & 2) {
193 s5l_lcd_write_cmd_data(R_HORIZ_ADDR_START_POS, x); 372 s5l_lcd_write_reg(R_HORIZ_ADDR_START_POS, x);
194 s5l_lcd_write_cmd_data(R_HORIZ_ADDR_END_POS, xe); 373 s5l_lcd_write_reg(R_HORIZ_ADDR_END_POS, xe);
195 s5l_lcd_write_cmd_data(R_VERT_ADDR_START_POS, y); 374 s5l_lcd_write_reg(R_VERT_ADDR_START_POS, y);
196 s5l_lcd_write_cmd_data(R_VERT_ADDR_END_POS, ye); 375 s5l_lcd_write_reg(R_VERT_ADDR_END_POS, ye);
197 376
198 s5l_lcd_write_cmd_data(R_HORIZ_GRAM_ADDR_SET, x); 377 s5l_lcd_write_reg(R_HORIZ_GRAM_ADDR_SET, x);
199 s5l_lcd_write_cmd_data(R_VERT_GRAM_ADDR_SET, y); 378 s5l_lcd_write_reg(R_VERT_GRAM_ADDR_SET, y);
200 379
201 s5l_lcd_write_cmd(R_WRITE_DATA_TO_GRAM); 380 s5l_lcd_write_cmd(R_WRITE_DATA_TO_GRAM);
202 } else { 381 } else {
@@ -252,6 +431,10 @@ void lcd_update_rect(int x, int y, int width, int height)
252 fb_data* p = &lcd_framebuffer[y][x]; 431 fb_data* p = &lcd_framebuffer[y][x];
253 uint16_t* out = lcd_dblbuf[0]; 432 uint16_t* out = lcd_dblbuf[0];
254 433
434#ifdef HAVE_LCD_SLEEP
435 if (!lcd_active()) return;
436#endif
437
255 displaylcd_setup(x, y, width, height); 438 displaylcd_setup(x, y, width, height);
256 439
257 /* Copy display bitmap to hardware */ 440 /* Copy display bitmap to hardware */
@@ -287,6 +470,10 @@ void lcd_blit_yuv(unsigned char * const src[3],
287 unsigned int z; 470 unsigned int z;
288 unsigned char const * yuv_src[3]; 471 unsigned char const * yuv_src[3];
289 472
473#ifdef HAVE_LCD_SLEEP
474 if (!lcd_active()) return;
475#endif
476
290 width = (width + 1) & ~1; /* ensure width is even */ 477 width = (width + 1) & ~1; /* ensure width is even */
291 478
292 int pixels = width * height; 479 int pixels = width * height;