From 67f00224fb8bbf92ffe952d163f35ed437b698d5 Mon Sep 17 00:00:00 2001 From: Linus Nielsen Feltzing Date: Tue, 20 Dec 2005 23:15:27 +0000 Subject: patch #1385256 by Hristo Kovachev - Turn off H300 LCD while backlight is off git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8268 a1c6a512-1295-4272-9138-f99709370657 --- firmware/backlight.c | 5 + firmware/drivers/lcd-h300.c | 344 +++++++++++++++++++++++++++++++++----------- firmware/export/lcd.h | 4 + 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 @@ #include "timer.h" #include "backlight.h" +#if CONFIG_BACKLIGHT == BL_IRIVER_H300 +#include "lcd.h" /* for lcd_enable() */ +#endif #ifdef HAVE_REMOTE_LCD #include "lcd-remote.h" #endif @@ -211,6 +214,7 @@ static void __backlight_on(void) and_l(~0x00020000, &GPIO1_OUT); } #elif CONFIG_BACKLIGHT == BL_IRIVER_H300 + lcd_enable(true); or_l(0x00020000, &GPIO1_OUT); #elif CONFIG_BACKLIGHT == BL_RTC /* Enable square wave */ @@ -251,6 +255,7 @@ static void __backlight_off(void) } #elif CONFIG_BACKLIGHT == BL_IRIVER_H300 and_l(~0x00020000, &GPIO1_OUT); + lcd_enable(false); #elif CONFIG_BACKLIGHT == BL_RTC /* Disable square wave */ 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 @@ #include "font.h" #include "bidi.h" -void lcd_write_reg(int reg, int val) +static bool display_on=false; /* is the display turned on? */ + +/* register defines */ +#define R_START_OSC 0x00 +#define R_DRV_OUTPUT_CONTROL 0x01 +#define R_DRV_WAVEFORM_CONTROL 0x02 +#define R_ENTRY_MODE 0x03 +#define R_COMPARE_REG1 0x04 +#define R_COMPARE_REG2 0x05 + +#define R_DISP_CONTROL1 0x07 +#define R_DISP_CONTROL2 0x08 +#define R_DISP_CONTROL3 0x09 + +#define R_FRAME_CYCLE_CONTROL 0x0b +#define R_EXT_DISP_IF_CONTROL 0x0c + +#define R_POWER_CONTROL1 0x10 +#define R_POWER_CONTROL2 0x11 +#define R_POWER_CONTROL3 0x12 +#define R_POWER_CONTROL4 0x13 + +#define R_RAM_ADDR_SET 0x21 +#define R_WRITE_DATA_2_GRAM 0x22 + +#define R_GAMMA_FINE_ADJ_POS1 0x30 +#define R_GAMMA_FINE_ADJ_POS2 0x31 +#define R_GAMMA_FINE_ADJ_POS3 0x32 +#define R_GAMMA_GRAD_ADJ_POS 0x33 + +#define R_GAMMA_FINE_ADJ_NEG1 0x34 +#define R_GAMMA_FINE_ADJ_NEG2 0x35 +#define R_GAMMA_FINE_ADJ_NEG3 0x36 +#define R_GAMMA_GRAD_ADJ_NEG 0x37 + +#define R_GAMMA_AMP_ADJ_RES_POS 0x38 +#define R_GAMMA_AMP_AVG_ADJ_RES_NEG 0x39 + +#define R_GATE_SCAN_POS 0x40 +#define R_VERT_SCROLL_CONTROL 0x41 +#define R_1ST_SCR_DRV_POS 0x42 +#define R_2ND_SCR_DRV_POS 0x43 +#define R_HORIZ_RAM_ADDR_POS 0x44 +#define R_VERT_RAM_ADDR_POS 0x45 + + +/* called very frequently - inline! */ +inline void lcd_write_reg(int reg, int val) { *(volatile unsigned short *)0xf0000000 = reg; *(volatile unsigned short *)0xf0000002 = val; } -void lcd_begin_write_gram(void) +/* called very frequently - inline! */ +inline void lcd_begin_write_gram(void) { - *(volatile unsigned short *)0xf0000000 = 0x22; + *(volatile unsigned short *)0xf0000000 = R_WRITE_DATA_2_GRAM; } -void lcd_write_data(const unsigned short* p_bytes, int count) ICODE_ATTR; -void lcd_write_data(const unsigned short* p_bytes, int count) +/* called very frequently - inline! */ +inline void lcd_write_data(const unsigned short* p_bytes, int count) ICODE_ATTR; +inline void lcd_write_data(const unsigned short* p_bytes, int count) { while(count--) *(volatile unsigned short *)0xf0000002 = *p_bytes++; @@ -94,69 +143,184 @@ void lcd_init_device(void) or_l(0x00004000, &GPIO1_OUT); sleep(1); - lcd_write_reg(0x00, 0x0001); + lcd_write_reg(R_START_OSC, 0x0001); /* Start Oscilation */ sleep(1); - lcd_write_reg(0x07, 0x0040); - lcd_write_reg(0x12, 0x0000); - lcd_write_reg(0x13, 0x0000); + lcd_write_reg(R_DISP_CONTROL1, 0x0040); /* zero all bits */ + lcd_write_reg(R_POWER_CONTROL3, 0x0000); + lcd_write_reg(R_POWER_CONTROL4, 0x0000); sleep(1); - lcd_write_reg(0x11, 0x0003); - lcd_write_reg(0x12, 0x0008); - lcd_write_reg(0x13, 0x3617); - lcd_write_reg(0x12, 0x0008); - lcd_write_reg(0x10, 0x0004); - lcd_write_reg(0x10, 0x0004); - lcd_write_reg(0x11, 0x0002); - lcd_write_reg(0x12, 0x0018); - lcd_write_reg(0x10, 0x0044); + 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); + + 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); - lcd_write_reg(0x10, 0x0144); - lcd_write_reg(0x10, 0x0540); - lcd_write_reg(0x13, 0x3218); - lcd_write_reg(0x01, 0x001b); - lcd_write_reg(0x02, 0x0700); - lcd_write_reg(0x03, 0x7038); - lcd_write_reg(0x04, 0x7030); - lcd_write_reg(0x05, 0x0000); - lcd_write_reg(0x40, 0x0000); - lcd_write_reg(0x41, 0x0000); - lcd_write_reg(0x42, 0xdb00); - lcd_write_reg(0x43, 0x0000); - lcd_write_reg(0x44, 0xaf00); - lcd_write_reg(0x45, 0xdb00); - - lcd_write_reg(0x0b, 0x0002); - lcd_write_reg(0x0c, 0x0003); + + /* 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) */ + lcd_write_reg(R_DRV_WAVEFORM_CONTROL, 0x0700); + + /* Address counter updated in vertical direction; left to right; + * vertical increment horizontal increment. + * data format for 8bit transfer or spi = 65k (5,6,5) + * Reverse order of RGB to BGR for 18bit data written to GRAM + * 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); + + /* 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 */ + + /* 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 */ + lcd_write_reg(R_EXT_DISP_IF_CONTROL, 0x0003); sleep(1); - lcd_write_reg(0x10, 0x4540); - lcd_write_reg(0x07, 0x0041); + 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); - lcd_write_reg(0x08, 0x0808); - lcd_write_reg(0x09, 0x003f); + + /* 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 */ + lcd_write_reg(R_DISP_CONTROL3, 0x003f); sleep(1); - lcd_write_reg(0x07, 0x0636); + + /* 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(0x07, 0x0626); + lcd_write_reg(R_DISP_CONTROL1, 0x0626);/* Gate output:VGL; 6th bit not set*/ sleep(1); - lcd_write_reg(0x30, 0x0003); - lcd_write_reg(0x31, 0x0707); - lcd_write_reg(0x32, 0x0007); - lcd_write_reg(0x33, 0x0705); - lcd_write_reg(0x34, 0x0007); - lcd_write_reg(0x35, 0x0000); - lcd_write_reg(0x36, 0x0407); - lcd_write_reg(0x37, 0x0507); - lcd_write_reg(0x38, 0x1d09); - lcd_write_reg(0x39, 0x0303); + 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); + lcd_write_reg(R_GAMMA_GRAD_ADJ_POS, 0x0705); + lcd_write_reg(R_GAMMA_FINE_ADJ_NEG1, 0x0007); + lcd_write_reg(R_GAMMA_FINE_ADJ_NEG2, 0x0000); + lcd_write_reg(R_GAMMA_FINE_ADJ_NEG3, 0x0407); + 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); - lcd_write_reg(0x13, 0x2610); + /* VcomH = Vreg1OUT*0.70 + * Vcom amplitude = Vreg1OUT*0.78 */ + lcd_write_reg(R_POWER_CONTROL4, 0x2610); - /* LCD ON */ - lcd_write_reg(0x07, 0x0061); + /* 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); - lcd_write_reg(0x07, 0x0067); + + /* 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); + + /* Reverse grayscale on; + * Source output: display */ + lcd_write_reg(R_DISP_CONTROL1, 0x0067); sleep(1); - lcd_write_reg(0x07, 0x0637); + + /* Vertical Scrolling disabled + * Gate output: VGH/VGL + * 6th bit not set*/ + lcd_write_reg(R_DISP_CONTROL1, 0x0637); +} + +void lcd_enable(bool on) +{ + if(display_on!=on) + { + if(on) + { + lcd_init_device(); + } + 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 */ + + /* Halt op. amp & step-up circuit */ + lcd_write_reg(R_POWER_CONTROL1,0x0000); + lcd_write_reg(R_POWER_CONTROL3,0x0000); /* Turn OFF VLOUT3 */ + + /* halt negative volt ampl. */ + lcd_write_reg(R_POWER_CONTROL4,0x0000); + } + display_on=on; + } } /*** update functions ***/ @@ -173,6 +337,7 @@ void lcd_blit(const fb_data* data, int x, int by, int width, (void)width; (void)bheight; (void)stride; + /*if(display_on)*/ } @@ -181,38 +346,49 @@ void lcd_blit(const fb_data* data, int x, int by, int width, void lcd_update(void) ICODE_ATTR; void lcd_update(void) { - /* Copy display bitmap to hardware */ - lcd_write_reg(0x21, 0); - lcd_begin_write_gram(); - lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT); + if(display_on){ + /* Copy display bitmap to hardware */ + lcd_write_reg(R_RAM_ADDR_SET, 0); + lcd_begin_write_gram(); + lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT); + } } /* Update a fraction of the display. */ void lcd_update_rect(int, int, int, int) ICODE_ATTR; void lcd_update_rect(int x, int y, int width, int height) { - int ymax = y + height; - - if(x + width > LCD_WIDTH) - width = LCD_WIDTH - x; - if (width <= 0) - return; /* nothing left to do, 0 is harmful to lcd_write_data() */ - if(ymax >= LCD_HEIGHT) - ymax = LCD_HEIGHT-1; - - /* set update window */ - lcd_write_reg(0x44, (ymax<<8) | y); /* horiz ram addr */ - lcd_write_reg(0x45, ((x+width-1)<<8) | x); /* vert ram addr */ - lcd_write_reg(0x21, (x<<8) | y); - lcd_begin_write_gram(); - - /* Copy specified rectangle bitmap to hardware */ - for (; y <= ymax; y++) - { - lcd_write_data ((unsigned short *)&lcd_framebuffer[y][x], width); - } - - /* reset update window */ - lcd_write_reg(0x44, 0xaf00); /* horiz ram addr: 0 - 175 */ - lcd_write_reg(0x45, 0xdb00); /* vert ram addr: 0 - 219 */ + if(display_on) { + int ymax = y + height; + + if(x + width > LCD_WIDTH) + width = LCD_WIDTH - x; + if (width <= 0) + return; /* nothing left to do, 0 is harmful to lcd_write_data() */ + if(ymax >= LCD_HEIGHT) + ymax = LCD_HEIGHT-1; + + /* set update window */ + + /* horiz ram addr */ + 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_begin_write_gram(); + + /* Copy specified rectangle bitmap to hardware */ + for (; y <= ymax; y++) + { + 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); + } } 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]; extern fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH]; #endif +#if CONFIG_BACKLIGHT==BL_IRIVER_H300 +extern void lcd_enable(bool on); +#endif + extern void lcd_set_invert_display(bool yesno); extern void lcd_set_flip(bool yesno); extern void lcd_roll(int pixels); -- cgit v1.2.3