2 * Copyright (C) 2010 Spreadtrum
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
17 #include <asm/errno.h>
19 #include <asm/arch/sc8810_reg_base.h>
20 #include <asm/arch/sc8810_lcd.h>
21 #include <asm/arch/lcdc_reg_v3.h>
22 #include <asm/arch/lcm_reg_v3.h>
24 #include <asm/arch/mfp.h>
25 #include <asm/arch/adi_hal_internal.h>
26 #include <asm/arch/regs_ana.h>
27 #include <asm/arch/analog_reg_v3.h>
29 #include <asm/arch/sc8810_reg_ahb.h>
30 #include <asm/arch/sc8810_reg_global.h>
32 #include <asm/arch/gpio_drvapi.h>
34 #include <asm/arch/regs_global.h>
35 #include <asm/arch/regs_cpc.h>
36 #include <asm/arch/ldo.h>
37 #include "sprdfb_panel.c"
38 #define mdelay(a) udelay(a * 1000)
41 DECLARE_GLOBAL_DATA_PTR;
43 void *lcd_base; /* Start of framebuffer memory */
44 void *lcd_console_address; /* Start of console buffer */
53 //#define TEST_RRM /* enable rrm test */
56 #define FB_PRINT printk
62 #define SPRD_GREG_BASE GREG_BASE
64 #define GR_PLL_SRC (SPRD_GREG_BASE + 0x70)
65 #define BITS_PER_PIXEL 16
67 #define LCDC_CYCLES(t, ahb, div) ((t) * (ahb) + (div) - 1) / (div)
68 #define MAX_LCDC_TIMING_VALUE 15
70 struct sc8810fb_info {
73 struct lcd_spec *panel;
77 uint32_t register_timing;
83 extern void FB_LDO_TurnOnLDO();
85 #ifdef CONFIG_LCD_WVGA
86 vidinfo_t panel_info = {
93 #ifdef CONFIG_LCD_HVGA
94 vidinfo_t panel_info = {
101 #ifdef CONFIG_LCD_QVGA
102 vidinfo_t panel_info = {
108 static void __raw_bits_and(unsigned int v, unsigned int a)
110 __raw_writel((__raw_readl(a) & v), a);
114 static void __raw_bits_or(unsigned int v, unsigned int a)
116 __raw_writel((__raw_readl(a) | v), a);
119 static int32_t lcm_send_cmd (uint32_t cmd)
121 /* busy wait for ahb fifo full sign's disappearance */
122 while(__raw_readl(LCM_CTRL) & BIT20);
124 __raw_writel(cmd, LCM_CD0);
129 static int32_t lcm_send_cmd_data (uint32_t cmd, uint32_t data)
131 /* busy wait for ahb fifo full sign's disappearance */
132 while(__raw_readl(LCM_CTRL) & BIT20);
134 __raw_writel(cmd, LCM_CD0);
136 /* busy wait for ahb fifo full sign's disappearance */
137 while(__raw_readl(LCM_CTRL) & BIT20);
139 __raw_writel(data, LCM_DATA0);
144 static int32_t lcm_send_data (uint32_t data)
146 /* busy wait for ahb fifo full sign's disappearance */
147 while(__raw_readl(LCM_CTRL) & BIT20);
149 __raw_writel(data, LCM_DATA0);
154 static uint32_t lcm_read_data (void)
156 /* busy wait for ahb fifo full sign's disappearance */
157 while(__raw_readl(LCM_CTRL) & BIT20);
158 __raw_writel(1 << 24, LCM_DATA0);
161 while(__raw_readl(LCM_CTRL) & BIT20);
163 return __raw_readl(LCM_RDDATA);
166 static struct ops_mcu lcm_mcu_ops = {
167 .send_cmd = lcm_send_cmd,
168 .send_cmd_data = lcm_send_cmd_data,
169 .send_data = lcm_send_data,
170 .read_data = lcm_read_data,
173 static int32_t panel_reset()
175 #if (CONFIG_MACH_CORI || CONFIG_MACH_MINT || CONFIG_MACH_KYLEW)
177 __raw_writel(0, LCM_RSTN);
179 __raw_writel(1, LCM_RSTN);
182 __raw_writel(0, LCM_RSTN);
184 __raw_writel(1, LCM_RSTN);
191 static void lcdc_mcu_init(void)
193 uint32_t reg_val = 0;
195 /* LCDC module enable */
198 /* FMARK mode ï¼?disable */
203 /* dithering enable ï¼?the logo is in the rgb565 buffer */
206 __raw_writel(reg_val, LCDC_CTRL);
208 FB_PRINT("[%s] LCDC_CTRL: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_CTRL));
211 __raw_writel(0xffffff, LCDC_BG_COLOR);
214 static uint32_t lcdc_calc_lcm_timing(struct timing_mcu *timing)
217 uint32_t rcss, rlpw, rhpw, wcss, wlpw, whpw;
219 /* can not get ahb clock rate; do later */
220 ahb_clk = 250; // 250 MHz
222 FB_PRINT("[%s] ahb_clk: 0x%x\n", __FUNCTION__, ahb_clk);
224 /************************************************
225 * we assume : t = ? ns, AHB = ? MHz so
226 * 1ns cycle : AHB /1000
227 * tns cycles : t * AHB / 1000
229 *****************************************/
230 rcss = LCDC_CYCLES(timing->rcss, ahb_clk, 1000);//ceiling
232 if (rcss > MAX_LCDC_TIMING_VALUE) {
233 rcss = MAX_LCDC_TIMING_VALUE ; // max 15 cycles
236 rlpw = LCDC_CYCLES(timing->rlpw, ahb_clk , 1000);
237 if (rlpw > MAX_LCDC_TIMING_VALUE) {
238 rlpw = MAX_LCDC_TIMING_VALUE ;
241 rhpw = LCDC_CYCLES(timing->rhpw, ahb_clk , 1000);
242 if (rhpw > MAX_LCDC_TIMING_VALUE) {
243 rhpw = MAX_LCDC_TIMING_VALUE ;
246 wcss = LCDC_CYCLES(timing->wcss, ahb_clk, 1000);
247 if (wcss > MAX_LCDC_TIMING_VALUE) {
248 wcss = MAX_LCDC_TIMING_VALUE ;
251 wlpw = LCDC_CYCLES(timing->wlpw, ahb_clk, 1000);
252 if (wlpw > MAX_LCDC_TIMING_VALUE) {
253 wlpw = MAX_LCDC_TIMING_VALUE ;
256 whpw = LCDC_CYCLES(timing->whpw, ahb_clk, 1000) - 1;
257 if (whpw > MAX_LCDC_TIMING_VALUE) {
258 whpw = MAX_LCDC_TIMING_VALUE ;
261 /* LCDC_ChangePulseWidth() */
262 return whpw | (wlpw << 4) | (wcss << 8)
263 | (rhpw << 16) |(rlpw << 20) | (rcss << 24);
268 #ifdef CONFIG_FB_LCDC_CS1
270 static void lcdc_update_lcm_timing(uint32_t value)
272 __raw_writel(value, LCM_PARAMETER1);
274 FB_PRINT("[%s] LCM_PARAMETER1: 0x%x\n", __FUNCTION__, __raw_readl(LCM_PARAMETER1));
279 static void lcdc_update_lcm_timing(uint32_t value)
281 /* LCD_UpdateTiming() */
283 __raw_writel(value, LCM_PARAMETER0); /* FIXME: hardcoded for !CS0 */
285 FB_PRINT("[%s] LCM_PARAMETER0: 0x%x\n", __FUNCTION__, __raw_readl(LCM_PARAMETER0));
290 static int mount_panel(struct sc8810fb_info *fb, struct lcd_spec *panel)
294 panel->info.mcu->ops = fb->ops;
296 panel->ops->lcd_reset = panel_reset;
299 struct timing_mcu *timing = panel->info.mcu->timing;
300 fb->register_timing = lcdc_calc_lcm_timing(timing);
302 fb->gram_timing = lcdc_calc_lcm_timing(timing);
307 static void real_set_layer(struct sc8810fb_info *fb)
311 /* image layer base */
312 reg_val = fb->smem_start;
313 __raw_writel(reg_val, LCDC_OSD1_BASE_ADDR);
316 static void real_refresh(struct sc8810fb_info *fb)
318 fb->panel->ops->lcd_invalidate(fb->panel);
319 /* set timing parameters for LCD */
320 lcdc_update_lcm_timing(fb->gram_timing);
322 __raw_bits_or((1<<3), LCDC_CTRL); /* start refresh */
324 while(!(__raw_readl(LCDC_IRQ_RAW) & (1<<0))); /* wait util lcdc done */
326 __raw_bits_or((1<<0), LCDC_IRQ_CLR);
328 /* set timing parameters for LCD */
329 lcdc_update_lcm_timing(fb->register_timing);
333 #ifdef CONFIG_FB_LCDC_CS1
335 static void lcdc_lcm_configure(struct sc8810fb_info *fb)
337 uint32_t reg_val = 0;
338 /* CS0 bus mode [BIT0]: 8080/6800 */
339 switch (fb->panel->info.mcu->bus_mode) {
349 /* CS0 bus width [BIT1:0] */
350 switch (fb->panel->info.mcu->bus_width) {
354 reg_val |= ((1 << 9) | (1 << 12));
360 reg_val |= ((3 << 9) | (1 << 12));
363 reg_val |= ((4 << 9) | (2 << 12));
370 reg_val |= (1 << 16);
371 __raw_writel(reg_val, LCM_CTRL);
373 FB_PRINT("[%s] LCM_CTRL: 0x%x\n", __FUNCTION__, __raw_readl(LCM_CTRL));
378 static void lcdc_lcm_configure(struct sc8810fb_info *fb)
380 uint32_t reg_val = 0;
381 /* CS0 bus mode [BIT0]: 8080/6800 */
382 switch (fb->panel->info.mcu->bus_mode) {
392 /* CS0 bus width [BIT1:0] */
393 switch (fb->panel->info.mcu->bus_width) {
397 reg_val |= ((1 << 1) | (1 << 4));
403 reg_val |= ((3 << 1) | (1 << 4));
406 reg_val |= ((4 << 1) | (2 << 4));
412 __raw_writel(reg_val, LCM_CTRL);
414 FB_PRINT("[%s] LCM_CTRL: 0x%x\n", __FUNCTION__, __raw_readl(LCM_CTRL));
419 static inline int set_lcdsize(struct lcd_spec *panel)
423 reg_val = ( panel->width & 0xfff) | (( panel->height & 0xfff )<<16);
424 __raw_writel(reg_val, LCDC_DISP_SIZE);
426 FB_PRINT("[%s] LCDC_DISP_SIZE: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_DISP_SIZE));
431 static inline int set_lcmrect( struct lcd_spec *panel)
435 __raw_writel(0, LCDC_LCM_START);
437 reg_val = ( panel->width & 0xfff) | (( panel->height & 0xfff )<<16);
438 __raw_writel(reg_val, LCDC_LCM_SIZE);
440 FB_PRINT("[%s] LCDC_LCM_START: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_LCM_START));
441 FB_PRINT("[%s] LCDC_LCM_SIZE: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_LCM_SIZE));
446 int set_lcdc_layers(struct sc8810fb_info *fb)
448 uint32_t reg_val = 0;
450 __raw_bits_and(~(1<<0),LCDC_IMG_CTRL);
451 __raw_bits_and(~(1<<0),LCDC_OSD2_CTRL);
452 __raw_bits_and(~(1<<0),LCDC_OSD3_CTRL);
453 __raw_bits_and(~(1<<0),LCDC_OSD4_CTRL);
454 __raw_bits_and(~(1<<0),LCDC_OSD5_CTRL);
455 /*enable OSD1 layer*/
456 //__raw_bits_or((1<<0),LCDC_OSD1_CTRL);
460 //__raw_bits_and(~(1<<1),LCDC_OSD1_CTRL); //disable
462 /*alpha mode select*/
463 //__raw_bits_or((1<<2),LCDC_OSD1_CTRL); //block alpha
466 reg_val |= (5 << 3); //RGB565
467 reg_val |= (2 << 7); //B2B3B0B1
469 __raw_writel(reg_val, LCDC_OSD1_CTRL);
471 FB_PRINT("[%s] LCDC_OSD1_CTRL: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_CTRL));
473 /* OSD1 layer base */
474 reg_val = fb->smem_start;
475 __raw_writel(reg_val, LCDC_OSD1_BASE_ADDR);
477 //FB_PRINT("[%s] LCDC_OSD1_BASE_ADDR: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_BASE_ADDR));
479 /*OSD1 layer alpha value*/
480 __raw_writel(0xff, LCDC_OSD1_ALPHA);
482 FB_PRINT("[%s] LCDC_OSD1_ALPHA: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_ALPHA));
485 //__raw_writel(reg_val, LCDC_OSD1_ALPHA_BASE_ADDR);
488 reg_val = ( fb->panel->width & 0xfff) | (( fb->panel->height & 0xfff )<<16);
489 __raw_writel(reg_val, LCDC_OSD1_SIZE_XY);
491 FB_PRINT("[%s] LCDC_OSD1_SIZE_XY: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_SIZE_XY));
493 /*OSD1 layer start position*/
494 __raw_writel(0, LCDC_OSD1_DISP_XY);
496 FB_PRINT("[%s] LCDC_OSD1_DISP_XY: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_DISP_XY));
499 reg_val = ( fb->panel->width & 0xfff) ;
500 __raw_writel(reg_val, LCDC_OSD1_PITCH);
502 FB_PRINT("[%s] LCDC_OSD1_PITCH: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_PITCH));
504 /*LCDC workplane size*/
505 set_lcdsize(fb->panel);
507 /*LCDC LCM rect size*/
508 set_lcmrect(fb->panel);
513 static void hw_early_init(struct sc8810fb_info *fb)
515 //select LCDC clock source
516 __raw_bits_and(~(1<<6), GR_PLL_SRC); //pll_src=96M
517 __raw_bits_and(~(1<<7), GR_PLL_SRC);
520 __raw_bits_and(~(1<<0), GR_GEN4); //div=0
521 __raw_bits_and(~(1<<1), GR_GEN4);
522 __raw_bits_and(~(1<<2), GR_GEN4);
525 __raw_bits_or((1<<3), AHB_CTL0);
528 __raw_bits_or((1<<3), AHB_SOFT_RST);
530 __raw_bits_and(~(1<<3), AHB_SOFT_RST);
532 __raw_bits_and(~(1<<0), LCDC_IRQ_EN);
533 __raw_bits_or((1<<0), LCDC_IRQ_CLR);
535 /* init lcdc mcu mode using default configuration */
539 static void hw_init(struct sc8810fb_info *fb)
541 /* only MCU mode is supported currently */
542 if (LCD_MODE_RGB == fb->panel->mode)
546 panel_reset(fb->panel);
548 /* set lcdc-lcd interface parameters */
549 lcdc_lcm_configure(fb);
551 /* set timing parameters for LCD */
552 lcdc_update_lcm_timing(fb->register_timing);
556 static void hw_later_init(struct sc8810fb_info *fb)
558 /* init mounted lcd panel */
559 fb->panel->ops->lcd_init(fb->panel);
564 #define WHTLED_CTL ANA_LED_CTL
565 #define WHTLED_PD_SET BIT_0
566 #define WHTLED_PD_RST BIT_1
567 #define WHTLED_V_SHIFT 2
568 #define WHTLED_V_MSK (0x1F << WHTLED_V_SHIFT)
570 static void LCD_SetPwmRatio(unsigned short value)
572 __raw_bits_or(CLK_PWM0_EN, GR_CLK_EN);
573 __raw_bits_or(CLK_PWM0_SEL, GR_CLK_EN);
574 __raw_bits_or(PIN_PWM0_MOD_VALUE, CPC_LCD_PWM_REG);
575 __raw_writel(LCD_PWM_PRESCALE_VALUE, SPRD_PWM0_PRESCALE);
576 __raw_writel(value, SPRD_PWM0_CNT);
577 __raw_writel(PWM_REG_MSK_VALUE, SPRD_PWM0_PAT_LOW);
578 __raw_writel(PWM_REG_MSK_VALUE, SPRD_PWM0_PAT_HIG);
580 __raw_bits_or(LCD_PWM0_EN, SPRD_PWM0_PRESCALE);
583 void LCD_SetBackLightBrightness( unsigned long value)
585 unsigned long duty_mod= 0;
586 if(value > LCD_PWM_MOD_VALUE)
587 value = LCD_PWM_MOD_VALUE;
593 duty_mod = (value << 8) | LCD_PWM_MOD_VALUE;
594 LCD_SetPwmRatio(duty_mod);
597 static struct sc8810fb_info sc8810fb = {0};
599 static uint32_t lcd_id_to_kernel = 0;
601 void save_lcd_id_to_kernel(uint32_t id)
603 lcd_id_to_kernel = id;
606 uint32_t load_lcd_id_to_kernel()
608 return lcd_id_to_kernel;
611 static int lcd_readid_default(struct lcd_spec *self)
614 //default id reg is 0
615 self->info.mcu->ops->send_cmd(0x0);
617 if(self->info.mcu->bus_width == 8) {
618 dummy = (self->info.mcu->ops->read_data())&0xff;
620 dummy |= (self->info.mcu->ops->read_data())&0xff;
622 dummy = (self->info.mcu->ops->read_data());
628 static int find_adapt_from_readid(struct sc8810fb_info *fb)
632 for(i = 0;i<(sizeof(lcd_panel))/(sizeof(lcd_panel[0]));i++) {
634 mount_panel(fb,lcd_panel[i].panel);
635 //hw init to every panel
638 if(fb->panel->ops->lcd_readid) {
639 id = fb->panel->ops->lcd_readid(fb->panel);
641 id = lcd_readid_default(fb->panel);
643 //if the id is right?
644 if(id == lcd_panel[i].lcd_id) {
645 save_lcd_id_to_kernel(id);
653 static int sc8810fb_probe(void * lcdbase)
657 struct sc8810fb_info *fb= &sc8810fb;
659 FB_PRINT("[%s]\n", __FUNCTION__);
662 fb->ops = &lcm_mcu_ops;
663 //we maybe readid ,so hardware should be init
666 lcd_adapt = find_adapt_from_readid(fb);
668 if(lcd_adapt == -1) {
672 ret = mount_panel(fb, lcd_panel[lcd_adapt].panel);
674 printk("unsupported panel!!");
678 fb->smem_start = (uint32_t)lcdbase;
679 fb->smem_len = fb->panel->width * fb->panel->height;
687 void lcd_initcolregs(void)
691 void lcd_disable(void)
696 /* References in this function refer to respective Linux kernel sources */
697 void lcd_enable(void)
701 void lcd_ctrl_init(void *lcdbase)
703 sc8810fb_probe(lcdbase);
706 void lcd_display(void)
708 real_refresh(&sc8810fb);
711 #ifdef CONFIG_LCD_INFO
713 extern nand_info_t nand_info[];
715 void lcd_show_board_info(void)
717 ulong dram_size, nand_size;
722 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
723 dram_size += gd->bd->bi_dram[i].size;
725 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
726 nand_size += nand_info[i].size;
728 lcd_printf("\n%s\n", U_BOOT_VERSION);
729 lcd_printf(" %ld MB SDRAM, %ld MB NAND\n",
732 lcd_printf(" Board : esd ARM9 \n");
733 lcd_printf(" Mach-type : %lu\n", gd->bd->bi_arch_number);
735 #endif /* CONFIG_LCD_INFO */