From cb9e316d4de6d919965aaf8124b35bbe23e5baa9 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Fri, 17 Mar 2006 15:42:06 +0000 Subject: H300: Cut-down LCD init & working display flip. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9078 a1c6a512-1295-4272-9138-f99709370657 --- firmware/drivers/lcd-h300.c | 277 ++++++++++++++++++++------------------------ 1 file changed, 127 insertions(+), 150 deletions(-) diff --git a/firmware/drivers/lcd-h300.c b/firmware/drivers/lcd-h300.c index 046bd3a9cb..0bdb123d41 100644 --- a/firmware/drivers/lcd-h300.c +++ b/firmware/drivers/lcd-h300.c @@ -30,7 +30,9 @@ #include "font.h" #include "bidi.h" -static bool display_on=false; /* is the display turned on? */ +static bool display_on = false; /* is the display turned on? */ +static bool display_flipped = false; +static int xoffset = 0; /* needed for flip */ /* register defines */ #define R_START_OSC 0x00 @@ -101,72 +103,76 @@ void lcd_set_invert_display(bool yesno) (void)yesno; } -/* turn the display upside down (call lcd_update() afterwards) */ -void lcd_set_flip(bool yesno) +static void flip_lcd(bool yesno) { - (void)yesno; + if (yesno) + { + lcd_write_reg(R_DRV_OUTPUT_CONTROL, 0x031b); /* 224 lines, GS=SS=1 */ + lcd_write_reg(R_GATE_SCAN_POS, 0x0002); /* 16 lines offset */ + lcd_write_reg(R_1ST_SCR_DRV_POS, 0xdf04); /* 4..223 */ + } + else + { + lcd_write_reg(R_DRV_OUTPUT_CONTROL, 0x001b); /* 224 lines, GS=SS=0 */ + lcd_write_reg(R_GATE_SCAN_POS, 0x0000); + lcd_write_reg(R_1ST_SCR_DRV_POS, 0xdb00); /* 0..219 */ + } } -/* LCD init */ -void lcd_init_device(void) +/* turn the display upside down (call lcd_update() afterwards) */ +void lcd_set_flip(bool yesno) { - /* GPO46 is LCD RESET */ - or_l(0x00004000, &GPIO1_OUT); - or_l(0x00004000, &GPIO1_ENABLE); - or_l(0x00004000, &GPIO1_FUNCTION); + display_flipped = yesno; + xoffset = yesno ? 4 : 0; - /* Reset LCD */ - sleep(1); - and_l(~0x00004000, &GPIO1_OUT); - sleep(1); - or_l(0x00004000, &GPIO1_OUT); - sleep(1); + if (display_on) + flip_lcd(yesno); +} +static void _display_on(void) +{ + /** Sequence according to datasheet, p. 132 **/ + lcd_write_reg(R_START_OSC, 0x0001); /* Start Oscilation */ sleep(1); - lcd_write_reg(R_DISP_CONTROL1, 0x0040); /* zero all bits */ - lcd_write_reg(R_POWER_CONTROL3, 0x0000); - lcd_write_reg(R_POWER_CONTROL4, 0x0000); + + /* zero everything*/ + lcd_write_reg(R_POWER_CONTROL1, 0x0000); /* STB = 0, SLP = 0 */ + lcd_write_reg(R_DISP_CONTROL1, 0x0000); /* GON = 0, DTE = 0, D1-0 = 00b */ + lcd_write_reg(R_POWER_CONTROL3, 0x0000); /* PON = 0 */ + lcd_write_reg(R_POWER_CONTROL4, 0x0000); /* VCOMG = 0 */ sleep(1); - lcd_write_reg(R_POWER_CONTROL2, 0x0003); /* VciOUT = 0.83*VciLVL */ - lcd_write_reg(R_POWER_CONTROL3, 0x0008); /* Vreg1OUT = REGP*1.90 */ - - /* Vcom-level amplitude = 1.23*Vreg1OUT - * VcomH-level amplitude = 0.84*Vreg1OUT */ - lcd_write_reg(R_POWER_CONTROL4, 0x3617); - lcd_write_reg(R_POWER_CONTROL3, 0x0008); /* Vreg1OUT = REGP*1.90 */ - lcd_write_reg(R_POWER_CONTROL1, 0x0004); /* Step-up circuit 1 ON */ - lcd_write_reg(R_POWER_CONTROL1, 0x0004); + + /* initialise power supply */ - lcd_write_reg(R_POWER_CONTROL2, 0x0002); /* VciOUT = 0.87*VciLVL */ - lcd_write_reg(R_POWER_CONTROL3, 0x0018); /* turn on VLOUT3 */ - lcd_write_reg(R_POWER_CONTROL1, 0x0044); /* LCD power supply Op.Amp - const curr = 1 */ - sleep(1); + /* DC12-10 = 000b: Step-up1 = clock/8, + * DC02-00 = 000b: Step-up2 = clock/16, + * VC2-0 = 010b: VciOUT = 0.87 * VciLVL */ + lcd_write_reg(R_POWER_CONTROL2, 0x0002); - /* Step-up rate: - * VLOUT1 (DDVDH) = Vci1*2 - * VLOUT4 (VCL) = Vci1*(-1) - * VLOUT2 (VGH) = DDVDH*3 = Vci1*6 - * VLOUT3 (VGL) = - DDVDH*2 = Vci1*(-4) */ - lcd_write_reg(R_POWER_CONTROL1, 0x0144); - - /* Step-Up circuit 1 Off; - * VLOUT2 (VGH) = Vci1 + DDVDH*2 = Vci1*5 - * VLOUT3 (VGL) = -(Vci1+DDVDH) = Vci1*(-3) */ - lcd_write_reg(R_POWER_CONTROL1, 0x0540); - - /* Vcom-level ampl = Vreg1OUT*1.11 - * VcomH-level ampl = Vreg1OUT*0.86 */ - lcd_write_reg(R_POWER_CONTROL4, 0x3218); - /* ??Number lines invalid? */ - lcd_write_reg(R_DRV_OUTPUT_CONTROL, 0x001b); - - /* B/C = 1 ; n-line inversion form; polarity inverses at completion of - * driving n lines - * Exclusive OR = 1; polarity inversion occurs by applying an EOR to - * odd/even frame select signal and an n-line inversion signal. - * FLD = 01b (1 field interlaced scan, external display iface) */ + /* VRH3-0 = 1000b: Vreg1OUT = REGP * 1.90 */ + lcd_write_reg(R_POWER_CONTROL3, 0x0008); + + /* VDV4-0 = 00110b: VcomA = Vreg1OUT * 0.76, + * VCM4-0 = 10000b: VcomH = Vreg1OUT * 0.70*/ + lcd_write_reg(R_POWER_CONTROL4, 0x0610); + + lcd_write_reg(R_POWER_CONTROL1, 0x0044); /* AP2-0 = 100b, DK = 1 */ + lcd_write_reg(R_POWER_CONTROL3, 0x0018); /* PON = 1 */ + + sleep(4); /* Step-up circuit stabilising time */ + + /* start power supply */ + + lcd_write_reg(R_POWER_CONTROL1, 0x0540); /* BT2-0 = 101b, DK = 0 */ + lcd_write_reg(R_POWER_CONTROL4, 0x2610); /* VCOMG = 1 */ + + /* other settings */ + + /* B/C = 1: n-line inversion form + * EOR = 1: polarity inversion occurs by applying an EOR to odd/even + * frame select signal and an n-line inversion signal. + * FLD = 01b: 1 field interlaced scan, external display iface */ lcd_write_reg(R_DRV_WAVEFORM_CONTROL, 0x0700); /* Address counter updated in vertical direction; left to right; @@ -176,55 +182,27 @@ void lcd_init_device(void) * Replace data on writing to GRAM */ lcd_write_reg(R_ENTRY_MODE, 0x7038); - /* ???? compare val = (1)1100 0011 0000b; the MSB bit is out of spec.*/ - lcd_write_reg(R_COMPARE_REG1, 0x7030); - lcd_write_reg(R_COMPARE_REG2, 0x0000); - - lcd_write_reg(R_GATE_SCAN_POS, 0x0000); - lcd_write_reg(R_VERT_SCROLL_CONTROL, 0x0000); + flip_lcd(display_flipped); - /* Gate Line = 0+1 = 1 - * gate "end" line = 0xdb + 1 = 0xdc */ - lcd_write_reg(R_1ST_SCR_DRV_POS, 0xdb00); lcd_write_reg(R_2ND_SCR_DRV_POS, 0x0000); - lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0xaf00);/* horiz ram addr 0 - 175 */ - lcd_write_reg(R_VERT_RAM_ADDR_POS, 0xdb00);/* vert ram addr 0 - 219 */ + lcd_write_reg(R_VERT_SCROLL_CONTROL, 0x0000); /* 19 clocks,no equalization */ lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x0002); /* Transfer mode for RGB interface disabled * internal clock operation; - * System interface/VSYNC interface */ + * System interface/VSYNC interface */ lcd_write_reg(R_EXT_DISP_IF_CONTROL, 0x0003); - sleep(1); - lcd_write_reg(R_POWER_CONTROL1, 0x4540); /* Turn on the op-amp (1) */ - - /* Enable internal display operations, not showed on the ext. display yet - * Source: GND; Internal: ON; Gate-Driver control signals: ON*/ - lcd_write_reg(R_DISP_CONTROL1, 0x0041); - sleep(1); /* Front porch lines: 8; Back porch lines: 8; */ lcd_write_reg(R_DISP_CONTROL2, 0x0808); /* Scan mode by the gate driver in the non-display area: disabled; - * Cycle of scan by the gate driver - set to 31frames(518ms),disabled by - * above setting */ + * Cycle of scan by the gate driver - set to 31frames(518ms), + * disabled by above setting */ lcd_write_reg(R_DISP_CONTROL3, 0x003f); - sleep(1); - /* Vertical scrolling disabled; - * Gate Output: VGH/VGL; - * Reversed grayscale image on; - * Source output: Non-lit display; internal disp.operation: ON, gate-driver - * control signals: ON - * Note: bit 6 (zero based) isn't set to 1 (according to the datasheet - * it should be) */ - lcd_write_reg(R_DISP_CONTROL1, 0x0636); - sleep(1); - lcd_write_reg(R_DISP_CONTROL1, 0x0626);/* Gate output:VGL; 6th bit not set*/ - sleep(1); lcd_write_reg(R_GAMMA_FINE_ADJ_POS1, 0x0003); lcd_write_reg(R_GAMMA_FINE_ADJ_POS2, 0x0707); lcd_write_reg(R_GAMMA_FINE_ADJ_POS3, 0x0007); @@ -235,73 +213,72 @@ void lcd_init_device(void) lcd_write_reg(R_GAMMA_GRAD_ADJ_NEG, 0x0507); lcd_write_reg(R_GAMMA_AMP_ADJ_RES_POS, 0x1d09); lcd_write_reg(R_GAMMA_AMP_AVG_ADJ_RES_NEG, 0x0303); - - /* VcomH = Vreg1OUT*0.70 - * Vcom amplitude = Vreg1OUT*0.78 */ - lcd_write_reg(R_POWER_CONTROL4, 0x2610); - - /* LCD ON - * Vertical scrolling: Originaly designated position/external display - * Reverse grayscale off; - * Internal display operation ON, Gate driver control signals: ON; Source - * output GND */ - lcd_write_reg(R_DISP_CONTROL1, 0x0061); - sleep(1); - /* init the GRAM, the framebuffer is already cleared in the - * device independent lcd_init() */ - lcd_write_reg(R_RAM_ADDR_SET, 0); - lcd_begin_write_gram(); - lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT); + display_on=true; /* must be done before calling lcd_update() */ + lcd_update(); + + sleep(4); /* op-amp stabilising time */ - /* Reverse grayscale on; - * Source output: display */ - lcd_write_reg(R_DISP_CONTROL1, 0x0067); + /** Sequence according to datasheet, p. 130 **/ + + lcd_write_reg(R_POWER_CONTROL1, 0x4540); /* SAP2-0=100, BT2-0=101, AP2-0=100 */ + lcd_write_reg(R_DISP_CONTROL1, 0x0005); /* GON=0, DTE=0, REV=1, D1-0=01 */ + sleep(2); + + lcd_write_reg(R_DISP_CONTROL1, 0x0025); /* GON=1, DTE=0, REV=1, D1-0=01 */ + lcd_write_reg(R_DISP_CONTROL1, 0x0027); /* GON=1, DTE=0, REV=1, D1-0=11 */ + sleep(2); + + lcd_write_reg(R_DISP_CONTROL1, 0x0037); /* GON=1, DTE=1, REV=1, D1-0=11 */ +} + +/* LCD init */ +void lcd_init_device(void) +{ + /* GPO46 is LCD RESET */ + or_l(0x00004000, &GPIO1_OUT); + or_l(0x00004000, &GPIO1_ENABLE); + or_l(0x00004000, &GPIO1_FUNCTION); + + /* Reset LCD */ + and_l(~0x00004000, &GPIO1_OUT); + sleep(1); + or_l(0x00004000, &GPIO1_OUT); sleep(1); - /* Vertical Scrolling disabled - * Gate output: VGH/VGL - * 6th bit not set*/ - lcd_write_reg(R_DISP_CONTROL1, 0x0637); - /* ok, the display is finally on */ - display_on=true; + _display_on(); } void lcd_enable(bool on) { if(display_on!=on) - { + { if(on) { - lcd_init_device(); + _display_on(); } else { - lcd_write_reg(R_FRAME_CYCLE_CONTROL,0x0002); /* No EQ, 19 clocks */ - - /* Gate Output VGH/VGL; Non-lit display internal disp. ON, - * gate-driver control ON; */ - lcd_write_reg(R_DISP_CONTROL1,0x0072); - sleep(1); - lcd_write_reg(R_DISP_CONTROL1,0x0062); /* Gate Output: VGL */ - sleep(1); - - /* Gate Output VGH; Source Output: GND; - * internal display operation:halt - * Gate-Driver control signals: OFF */ - lcd_write_reg(R_DISP_CONTROL1,0x0040); - - /* Now, turn off the power */ + /** Off sequence according to datasheet, p. 130 **/ + + lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x0002); /* EQ=0, 18 clks/line */ + lcd_write_reg(R_DISP_CONTROL1, 0x0036); /* GON=1, DTE=1, REV=1, D1-0=10 */ + sleep(2); + + lcd_write_reg(R_DISP_CONTROL1, 0x0026); /* GON=1, DTE=0, REV=1, D1-0=10 */ + sleep(2); + + lcd_write_reg(R_DISP_CONTROL1, 0x0000); /* GON=0, DTE=0, D1-0=00 */ - /* Halt op. amp & step-up circuit */ - lcd_write_reg(R_POWER_CONTROL1,0x0000); - lcd_write_reg(R_POWER_CONTROL3,0x0000); /* Turn OFF VLOUT3 */ + lcd_write_reg(R_POWER_CONTROL1, 0x0000); /* SAP2-0=000, AP2-0=000 */ + lcd_write_reg(R_POWER_CONTROL3, 0x0000); /* PON=0 */ + lcd_write_reg(R_POWER_CONTROL4, 0x0000); /* VCOMG=0 */ + + /* datasheet p. 131 */ + lcd_write_reg(R_POWER_CONTROL1, 0x0001); /* STB=1: standby mode */ - /* halt negative volt ampl. */ - lcd_write_reg(R_POWER_CONTROL4,0x0000); display_on=false; } - /* display_on = on */ } } @@ -319,7 +296,7 @@ void lcd_blit(const fb_data* data, int x, int by, int width, (void)width; (void)bheight; (void)stride; - /*if(display_on)*/ + /*if(display_on)*/ } @@ -329,8 +306,15 @@ void lcd_update(void) ICODE_ATTR; void lcd_update(void) { if(display_on){ + /* reset update window */ + /* horiz ram addr: 0 - 175 */ + lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0xaf00); + + /* vert ram addr: 0 - 219 */ + lcd_write_reg(R_VERT_RAM_ADDR_POS,((xoffset+219)<<8) | xoffset); + /* Copy display bitmap to hardware */ - lcd_write_reg(R_RAM_ADDR_SET, 0); + lcd_write_reg(R_RAM_ADDR_SET, xoffset << 8); lcd_begin_write_gram(); lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT); } @@ -353,11 +337,11 @@ void lcd_update_rect(int x, int y, int width, int height) /* set update window */ /* horiz ram addr */ - lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (ymax<<8) | y); + lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (ymax << 8) | y); /* vert ram addr */ - lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+width-1)<<8) | x); - lcd_write_reg(R_RAM_ADDR_SET, (x<<8) | y); + lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+xoffset+width-1) << 8) | (x+xoffset)); + lcd_write_reg(R_RAM_ADDR_SET, ((x+xoffset) << 8) | y); lcd_begin_write_gram(); /* Copy specified rectangle bitmap to hardware */ @@ -365,12 +349,5 @@ void lcd_update_rect(int x, int y, int width, int height) { lcd_write_data ((unsigned short *)&lcd_framebuffer[y][x], width); } - - /* reset update window */ - /* horiz ram addr: 0 - 175 */ - lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0xaf00); - - /* vert ram addr: 0 - 219 */ - lcd_write_reg(R_VERT_RAM_ADDR_POS, 0xdb00); } } -- cgit v1.2.3