summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/backlight.c5
-rw-r--r--firmware/drivers/lcd-h300.c344
-rw-r--r--firmware/export/lcd.h4
3 files changed, 269 insertions, 84 deletions
diff --git a/firmware/backlight.c b/firmware/backlight.c
index 491d2b5cc7..291c5da8e7 100644
--- a/firmware/backlight.c
+++ b/firmware/backlight.c
@@ -30,6 +30,9 @@
30#include "timer.h" 30#include "timer.h"
31#include "backlight.h" 31#include "backlight.h"
32 32
33#if CONFIG_BACKLIGHT == BL_IRIVER_H300
34#include "lcd.h" /* for lcd_enable() */
35#endif
33#ifdef HAVE_REMOTE_LCD 36#ifdef HAVE_REMOTE_LCD
34#include "lcd-remote.h" 37#include "lcd-remote.h"
35#endif 38#endif
@@ -211,6 +214,7 @@ static void __backlight_on(void)
211 and_l(~0x00020000, &GPIO1_OUT); 214 and_l(~0x00020000, &GPIO1_OUT);
212 } 215 }
213#elif CONFIG_BACKLIGHT == BL_IRIVER_H300 216#elif CONFIG_BACKLIGHT == BL_IRIVER_H300
217 lcd_enable(true);
214 or_l(0x00020000, &GPIO1_OUT); 218 or_l(0x00020000, &GPIO1_OUT);
215#elif CONFIG_BACKLIGHT == BL_RTC 219#elif CONFIG_BACKLIGHT == BL_RTC
216 /* Enable square wave */ 220 /* Enable square wave */
@@ -251,6 +255,7 @@ static void __backlight_off(void)
251 } 255 }
252#elif CONFIG_BACKLIGHT == BL_IRIVER_H300 256#elif CONFIG_BACKLIGHT == BL_IRIVER_H300
253 and_l(~0x00020000, &GPIO1_OUT); 257 and_l(~0x00020000, &GPIO1_OUT);
258 lcd_enable(false);
254#elif CONFIG_BACKLIGHT == BL_RTC 259#elif CONFIG_BACKLIGHT == BL_RTC
255 /* Disable square wave */ 260 /* Disable square wave */
256 rtc_write(0x0a, rtc_read(0x0a) & ~0x40); 261 rtc_write(0x0a, rtc_read(0x0a) & ~0x40);
diff --git a/firmware/drivers/lcd-h300.c b/firmware/drivers/lcd-h300.c
index 91a86defd4..bb2f9ec777 100644
--- a/firmware/drivers/lcd-h300.c
+++ b/firmware/drivers/lcd-h300.c
@@ -30,19 +30,68 @@
30#include "font.h" 30#include "font.h"
31#include "bidi.h" 31#include "bidi.h"
32 32
33void lcd_write_reg(int reg, int val) 33static bool display_on=false; /* is the display turned on? */
34
35/* register defines */
36#define R_START_OSC 0x00
37#define R_DRV_OUTPUT_CONTROL 0x01
38#define R_DRV_WAVEFORM_CONTROL 0x02
39#define R_ENTRY_MODE 0x03
40#define R_COMPARE_REG1 0x04
41#define R_COMPARE_REG2 0x05
42
43#define R_DISP_CONTROL1 0x07
44#define R_DISP_CONTROL2 0x08
45#define R_DISP_CONTROL3 0x09
46
47#define R_FRAME_CYCLE_CONTROL 0x0b
48#define R_EXT_DISP_IF_CONTROL 0x0c
49
50#define R_POWER_CONTROL1 0x10
51#define R_POWER_CONTROL2 0x11
52#define R_POWER_CONTROL3 0x12
53#define R_POWER_CONTROL4 0x13
54
55#define R_RAM_ADDR_SET 0x21
56#define R_WRITE_DATA_2_GRAM 0x22
57
58#define R_GAMMA_FINE_ADJ_POS1 0x30
59#define R_GAMMA_FINE_ADJ_POS2 0x31
60#define R_GAMMA_FINE_ADJ_POS3 0x32
61#define R_GAMMA_GRAD_ADJ_POS 0x33
62
63#define R_GAMMA_FINE_ADJ_NEG1 0x34
64#define R_GAMMA_FINE_ADJ_NEG2 0x35
65#define R_GAMMA_FINE_ADJ_NEG3 0x36
66#define R_GAMMA_GRAD_ADJ_NEG 0x37
67
68#define R_GAMMA_AMP_ADJ_RES_POS 0x38
69#define R_GAMMA_AMP_AVG_ADJ_RES_NEG 0x39
70
71#define R_GATE_SCAN_POS 0x40
72#define R_VERT_SCROLL_CONTROL 0x41
73#define R_1ST_SCR_DRV_POS 0x42
74#define R_2ND_SCR_DRV_POS 0x43
75#define R_HORIZ_RAM_ADDR_POS 0x44
76#define R_VERT_RAM_ADDR_POS 0x45
77
78
79/* called very frequently - inline! */
80inline void lcd_write_reg(int reg, int val)
34{ 81{
35 *(volatile unsigned short *)0xf0000000 = reg; 82 *(volatile unsigned short *)0xf0000000 = reg;
36 *(volatile unsigned short *)0xf0000002 = val; 83 *(volatile unsigned short *)0xf0000002 = val;
37} 84}
38 85
39void lcd_begin_write_gram(void) 86/* called very frequently - inline! */
87inline void lcd_begin_write_gram(void)
40{ 88{
41 *(volatile unsigned short *)0xf0000000 = 0x22; 89 *(volatile unsigned short *)0xf0000000 = R_WRITE_DATA_2_GRAM;
42} 90}
43 91
44void lcd_write_data(const unsigned short* p_bytes, int count) ICODE_ATTR; 92/* called very frequently - inline! */
45void lcd_write_data(const unsigned short* p_bytes, int count) 93inline void lcd_write_data(const unsigned short* p_bytes, int count) ICODE_ATTR;
94inline void lcd_write_data(const unsigned short* p_bytes, int count)
46{ 95{
47 while(count--) 96 while(count--)
48 *(volatile unsigned short *)0xf0000002 = *p_bytes++; 97 *(volatile unsigned short *)0xf0000002 = *p_bytes++;
@@ -94,69 +143,184 @@ void lcd_init_device(void)
94 or_l(0x00004000, &GPIO1_OUT); 143 or_l(0x00004000, &GPIO1_OUT);
95 sleep(1); 144 sleep(1);
96 145
97 lcd_write_reg(0x00, 0x0001); 146 lcd_write_reg(R_START_OSC, 0x0001); /* Start Oscilation */
98 sleep(1); 147 sleep(1);
99 lcd_write_reg(0x07, 0x0040); 148 lcd_write_reg(R_DISP_CONTROL1, 0x0040); /* zero all bits */
100 lcd_write_reg(0x12, 0x0000); 149 lcd_write_reg(R_POWER_CONTROL3, 0x0000);
101 lcd_write_reg(0x13, 0x0000); 150 lcd_write_reg(R_POWER_CONTROL4, 0x0000);
102 sleep(1); 151 sleep(1);
103 lcd_write_reg(0x11, 0x0003); 152 lcd_write_reg(R_POWER_CONTROL2, 0x0003); /* VciOUT = 0.83*VciLVL */
104 lcd_write_reg(0x12, 0x0008); 153 lcd_write_reg(R_POWER_CONTROL3, 0x0008); /* Vreg1OUT = REGP*1.90 */
105 lcd_write_reg(0x13, 0x3617); 154
106 lcd_write_reg(0x12, 0x0008); 155 /* Vcom-level amplitude = 1.23*Vreg1OUT
107 lcd_write_reg(0x10, 0x0004); 156 * VcomH-level amplitude = 0.84*Vreg1OUT */
108 lcd_write_reg(0x10, 0x0004); 157 lcd_write_reg(R_POWER_CONTROL4, 0x3617);
109 lcd_write_reg(0x11, 0x0002); 158 lcd_write_reg(R_POWER_CONTROL3, 0x0008); /* Vreg1OUT = REGP*1.90 */
110 lcd_write_reg(0x12, 0x0018); 159 lcd_write_reg(R_POWER_CONTROL1, 0x0004); /* Step-up circuit 1 ON */
111 lcd_write_reg(0x10, 0x0044); 160 lcd_write_reg(R_POWER_CONTROL1, 0x0004);
161
162 lcd_write_reg(R_POWER_CONTROL2, 0x0002); /* VciOUT = 0.87*VciLVL */
163 lcd_write_reg(R_POWER_CONTROL3, 0x0018); /* turn on VLOUT3 */
164 lcd_write_reg(R_POWER_CONTROL1, 0x0044); /* LCD power supply Op.Amp
165 const curr = 1 */
112 sleep(1); 166 sleep(1);
113 lcd_write_reg(0x10, 0x0144); 167
114 lcd_write_reg(0x10, 0x0540); 168 /* Step-up rate:
115 lcd_write_reg(0x13, 0x3218); 169 * VLOUT1 (DDVDH) = Vci1*2
116 lcd_write_reg(0x01, 0x001b); 170 * VLOUT4 (VCL) = Vci1*(-1)
117 lcd_write_reg(0x02, 0x0700); 171 * VLOUT2 (VGH) = DDVDH*3 = Vci1*6
118 lcd_write_reg(0x03, 0x7038); 172 * VLOUT3 (VGL) = - DDVDH*2 = Vci1*(-4) */
119 lcd_write_reg(0x04, 0x7030); 173 lcd_write_reg(R_POWER_CONTROL1, 0x0144);
120 lcd_write_reg(0x05, 0x0000); 174
121 lcd_write_reg(0x40, 0x0000); 175 /* Step-Up circuit 1 Off;
122 lcd_write_reg(0x41, 0x0000); 176 * VLOUT2 (VGH) = Vci1 + DDVDH*2 = Vci1*5
123 lcd_write_reg(0x42, 0xdb00); 177 * VLOUT3 (VGL) = -(Vci1+DDVDH) = Vci1*(-3) */
124 lcd_write_reg(0x43, 0x0000); 178 lcd_write_reg(R_POWER_CONTROL1, 0x0540);
125 lcd_write_reg(0x44, 0xaf00); 179
126 lcd_write_reg(0x45, 0xdb00); 180 /* Vcom-level ampl = Vreg1OUT*1.11
127 181 * VcomH-level ampl = Vreg1OUT*0.86 */
128 lcd_write_reg(0x0b, 0x0002); 182 lcd_write_reg(R_POWER_CONTROL4, 0x3218);
129 lcd_write_reg(0x0c, 0x0003); 183 /* ??Number lines invalid? */
184 lcd_write_reg(R_DRV_OUTPUT_CONTROL, 0x001b);
185
186 /* B/C = 1 ; n-line inversion form; polarity inverses at completion of
187 * driving n lines
188 * Exclusive OR = 1; polarity inversion occurs by applying an EOR to
189 * odd/even frame select signal and an n-line inversion signal.
190 * FLD = 01b (1 field interlaced scan, external display iface) */
191 lcd_write_reg(R_DRV_WAVEFORM_CONTROL, 0x0700);
192
193 /* Address counter updated in vertical direction; left to right;
194 * vertical increment horizontal increment.
195 * data format for 8bit transfer or spi = 65k (5,6,5)
196 * Reverse order of RGB to BGR for 18bit data written to GRAM
197 * Replace data on writing to GRAM */
198 lcd_write_reg(R_ENTRY_MODE, 0x7038);
199
200 /* ???? compare val = (1)1100 0011 0000b; the MSB bit is out of spec.*/
201 lcd_write_reg(R_COMPARE_REG1, 0x7030);
202 lcd_write_reg(R_COMPARE_REG2, 0x0000);
203
204 lcd_write_reg(R_GATE_SCAN_POS, 0x0000);
205 lcd_write_reg(R_VERT_SCROLL_CONTROL, 0x0000);
206
207 /* Gate Line = 0+1 = 1
208 * gate "end" line = 0xdb + 1 = 0xdc */
209 lcd_write_reg(R_1ST_SCR_DRV_POS, 0xdb00);
210 lcd_write_reg(R_2ND_SCR_DRV_POS, 0x0000);
211 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0xaf00);/* horiz ram addr 0 - 175 */
212 lcd_write_reg(R_VERT_RAM_ADDR_POS, 0xdb00);/* vert ram addr 0 - 219 */
213
214 /* 19 clocks,no equalization */
215 lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x0002);
216
217 /* Transfer mode for RGB interface disabled
218 * internal clock operation;
219 * System interface/VSYNC interface */
220 lcd_write_reg(R_EXT_DISP_IF_CONTROL, 0x0003);
130 sleep(1); 221 sleep(1);
131 lcd_write_reg(0x10, 0x4540); 222 lcd_write_reg(R_POWER_CONTROL1, 0x4540); /* Turn on the op-amp (1) */
132 lcd_write_reg(0x07, 0x0041); 223
224 /* Enable internal display operations, not showed on the ext. display yet
225 * Source: GND; Internal: ON; Gate-Driver control signals: ON*/
226 lcd_write_reg(R_DISP_CONTROL1, 0x0041);
133 sleep(1); 227 sleep(1);
134 lcd_write_reg(0x08, 0x0808); 228
135 lcd_write_reg(0x09, 0x003f); 229 /* Front porch lines: 8; Back porch lines: 8; */
230 lcd_write_reg(R_DISP_CONTROL2, 0x0808);
231
232 /* Scan mode by the gate driver in the non-display area: disabled;
233 * Cycle of scan by the gate driver - set to 31frames(518ms),disabled by
234 * above setting */
235 lcd_write_reg(R_DISP_CONTROL3, 0x003f);
136 sleep(1); 236 sleep(1);
137 lcd_write_reg(0x07, 0x0636); 237
238 /* Vertical scrolling disabled;
239 * Gate Output: VGH/VGL;
240 * Reversed grayscale image on;
241 * Source output: Non-lit display; internal disp.operation: ON, gate-driver
242 * control signals: ON
243 * Note: bit 6 (zero based) isn't set to 1 (according to the datasheet
244 * it should be) */
245 lcd_write_reg(R_DISP_CONTROL1, 0x0636);
138 sleep(1); 246 sleep(1);
139 lcd_write_reg(0x07, 0x0626); 247 lcd_write_reg(R_DISP_CONTROL1, 0x0626);/* Gate output:VGL; 6th bit not set*/
140 sleep(1); 248 sleep(1);
141 lcd_write_reg(0x30, 0x0003); 249 lcd_write_reg(R_GAMMA_FINE_ADJ_POS1, 0x0003);
142 lcd_write_reg(0x31, 0x0707); 250 lcd_write_reg(R_GAMMA_FINE_ADJ_POS2, 0x0707);
143 lcd_write_reg(0x32, 0x0007); 251 lcd_write_reg(R_GAMMA_FINE_ADJ_POS3, 0x0007);
144 lcd_write_reg(0x33, 0x0705); 252 lcd_write_reg(R_GAMMA_GRAD_ADJ_POS, 0x0705);
145 lcd_write_reg(0x34, 0x0007); 253 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG1, 0x0007);
146 lcd_write_reg(0x35, 0x0000); 254 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG2, 0x0000);
147 lcd_write_reg(0x36, 0x0407); 255 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG3, 0x0407);
148 lcd_write_reg(0x37, 0x0507); 256 lcd_write_reg(R_GAMMA_GRAD_ADJ_NEG, 0x0507);
149 lcd_write_reg(0x38, 0x1d09); 257 lcd_write_reg(R_GAMMA_AMP_ADJ_RES_POS, 0x1d09);
150 lcd_write_reg(0x39, 0x0303); 258 lcd_write_reg(R_GAMMA_AMP_AVG_ADJ_RES_NEG, 0x0303);
151 259
152 lcd_write_reg(0x13, 0x2610); 260 /* VcomH = Vreg1OUT*0.70
261 * Vcom amplitude = Vreg1OUT*0.78 */
262 lcd_write_reg(R_POWER_CONTROL4, 0x2610);
153 263
154 /* LCD ON */ 264 /* LCD ON
155 lcd_write_reg(0x07, 0x0061); 265 * Vertical scrolling: Originaly designated position/external display
266 * Reverse grayscale off;
267 * Internal display operation ON, Gate driver control signals: ON; Source
268 * output GND */
269 lcd_write_reg(R_DISP_CONTROL1, 0x0061);
156 sleep(1); 270 sleep(1);
157 lcd_write_reg(0x07, 0x0067); 271
272 /* init the GRAM, the framebuffer is already cleared in the
273 * device independent lcd_init() */
274 lcd_write_reg(R_RAM_ADDR_SET, 0);
275 lcd_begin_write_gram();
276 lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT);
277
278 /* Reverse grayscale on;
279 * Source output: display */
280 lcd_write_reg(R_DISP_CONTROL1, 0x0067);
158 sleep(1); 281 sleep(1);
159 lcd_write_reg(0x07, 0x0637); 282
283 /* Vertical Scrolling disabled
284 * Gate output: VGH/VGL
285 * 6th bit not set*/
286 lcd_write_reg(R_DISP_CONTROL1, 0x0637);
287}
288
289void lcd_enable(bool on)
290{
291 if(display_on!=on)
292 {
293 if(on)
294 {
295 lcd_init_device();
296 }
297 else
298 {
299 lcd_write_reg(R_FRAME_CYCLE_CONTROL,0x0002); /* No EQ, 19 clocks */
300
301 /* Gate Output VGH/VGL; Non-lit display internal disp. ON,
302 * gate-driver control ON; */
303 lcd_write_reg(R_DISP_CONTROL1,0x0072);
304 sleep(1);
305 lcd_write_reg(R_DISP_CONTROL1,0x0062); /* Gate Output: VGL */
306 sleep(1);
307
308 /* Gate Output VGH; Source Output: GND;
309 * internal display operation:halt
310 * Gate-Driver control signals: OFF */
311 lcd_write_reg(R_DISP_CONTROL1,0x0040);
312
313 /* Now, turn off the power */
314
315 /* Halt op. amp & step-up circuit */
316 lcd_write_reg(R_POWER_CONTROL1,0x0000);
317 lcd_write_reg(R_POWER_CONTROL3,0x0000); /* Turn OFF VLOUT3 */
318
319 /* halt negative volt ampl. */
320 lcd_write_reg(R_POWER_CONTROL4,0x0000);
321 }
322 display_on=on;
323 }
160} 324}
161 325
162/*** update functions ***/ 326/*** update functions ***/
@@ -173,6 +337,7 @@ void lcd_blit(const fb_data* data, int x, int by, int width,
173 (void)width; 337 (void)width;
174 (void)bheight; 338 (void)bheight;
175 (void)stride; 339 (void)stride;
340 /*if(display_on)*/
176} 341}
177 342
178 343
@@ -181,38 +346,49 @@ void lcd_blit(const fb_data* data, int x, int by, int width,
181void lcd_update(void) ICODE_ATTR; 346void lcd_update(void) ICODE_ATTR;
182void lcd_update(void) 347void lcd_update(void)
183{ 348{
184 /* Copy display bitmap to hardware */ 349 if(display_on){
185 lcd_write_reg(0x21, 0); 350 /* Copy display bitmap to hardware */
186 lcd_begin_write_gram(); 351 lcd_write_reg(R_RAM_ADDR_SET, 0);
187 lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT); 352 lcd_begin_write_gram();
353 lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT);
354 }
188} 355}
189 356
190/* Update a fraction of the display. */ 357/* Update a fraction of the display. */
191void lcd_update_rect(int, int, int, int) ICODE_ATTR; 358void lcd_update_rect(int, int, int, int) ICODE_ATTR;
192void lcd_update_rect(int x, int y, int width, int height) 359void lcd_update_rect(int x, int y, int width, int height)
193{ 360{
194 int ymax = y + height; 361 if(display_on) {
195 362 int ymax = y + height;
196 if(x + width > LCD_WIDTH) 363
197 width = LCD_WIDTH - x; 364 if(x + width > LCD_WIDTH)
198 if (width <= 0) 365 width = LCD_WIDTH - x;
199 return; /* nothing left to do, 0 is harmful to lcd_write_data() */ 366 if (width <= 0)
200 if(ymax >= LCD_HEIGHT) 367 return; /* nothing left to do, 0 is harmful to lcd_write_data() */
201 ymax = LCD_HEIGHT-1; 368 if(ymax >= LCD_HEIGHT)
202 369 ymax = LCD_HEIGHT-1;
203 /* set update window */ 370
204 lcd_write_reg(0x44, (ymax<<8) | y); /* horiz ram addr */ 371 /* set update window */
205 lcd_write_reg(0x45, ((x+width-1)<<8) | x); /* vert ram addr */ 372
206 lcd_write_reg(0x21, (x<<8) | y); 373 /* horiz ram addr */
207 lcd_begin_write_gram(); 374 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (ymax<<8) | y);
208 375
209 /* Copy specified rectangle bitmap to hardware */ 376 /* vert ram addr */
210 for (; y <= ymax; y++) 377 lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+width-1)<<8) | x);
211 { 378 lcd_write_reg(R_RAM_ADDR_SET, (x<<8) | y);
212 lcd_write_data ((unsigned short *)&lcd_framebuffer[y][x], width); 379 lcd_begin_write_gram();
213 } 380
214 381 /* Copy specified rectangle bitmap to hardware */
215 /* reset update window */ 382 for (; y <= ymax; y++)
216 lcd_write_reg(0x44, 0xaf00); /* horiz ram addr: 0 - 175 */ 383 {
217 lcd_write_reg(0x45, 0xdb00); /* vert ram addr: 0 - 219 */ 384 lcd_write_data ((unsigned short *)&lcd_framebuffer[y][x], width);
385 }
386
387 /* reset update window */
388 /* horiz ram addr: 0 - 175 */
389 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0xaf00);
390
391 /* vert ram addr: 0 - 219 */
392 lcd_write_reg(R_VERT_RAM_ADDR_POS, 0xdb00);
393 }
218} 394}
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 46f33d522a..6bb54f5dd0 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -187,6 +187,10 @@ extern fb_data lcd_framebuffer[LCD_HEIGHT/4][LCD_WIDTH];
187extern fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH]; 187extern fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH];
188#endif 188#endif
189 189
190#if CONFIG_BACKLIGHT==BL_IRIVER_H300
191extern void lcd_enable(bool on);
192#endif
193
190extern void lcd_set_invert_display(bool yesno); 194extern void lcd_set_invert_display(bool yesno);
191extern void lcd_set_flip(bool yesno); 195extern void lcd_set_flip(bool yesno);
192extern void lcd_roll(int pixels); 196extern void lcd_roll(int pixels);