3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 #ifdef PLATFORM_SC8800G
26 #include <asm/arch/sc8800g_reg_base.h>
27 #include <asm/arch/sc8800g_lcd.h>
30 #include <asm/arch/sc8810_reg_base.h>
31 #include <asm/arch/sc8810_lcd.h>
33 #include <asm/arch/mfp.h>
34 #include <asm/arch/adi_hal_internal.h>
35 #include <asm/arch/regs_ana.h>
36 #include <asm/arch/analog_reg_v3.h>
37 #ifdef PLATFORM_SC8800G
38 #include <asm/arch/sc8800g_reg_ahb.h>
39 #include <asm/arch/sc8800g_reg_global.h>
42 #include <asm/arch/sc8810_reg_ahb.h>
43 #include <asm/arch/sc8810_reg_global.h>
46 #include <asm/errno.h>
49 #define mdelay(a) udelay(a * 1000)
52 DECLARE_GLOBAL_DATA_PTR;
54 void *lcd_base; /* Start of framebuffer memory */
55 void *lcd_console_address; /* Start of console buffer */
67 #define FB_PRINT printk
72 #define SPRD_LCDC_BASE LCDC_CTL_BEGIN
74 #define LCDC_CTRL (SPRD_LCDC_BASE + 0x0000)
75 #define LCDC_DISP_SIZE (SPRD_LCDC_BASE + 0x0004)
76 #define LCDC_LCM_START (SPRD_LCDC_BASE + 0x0008)
77 #define LCDC_LCM_SIZE (SPRD_LCDC_BASE + 0x000c)
78 #define LCDC_BG_COLOR (SPRD_LCDC_BASE + 0x0010)
79 #define LCDC_FIFO_STATUS (SPRD_LCDC_BASE + 0x0014)
81 #define LCDC_IMG_CTRL (SPRD_LCDC_BASE + 0x0020)
82 #define LCDC_IMG_Y_BASE_ADDR (SPRD_LCDC_BASE + 0x0024)
83 #define LCDC_IMG_UV_BASE_ADDR (SPRD_LCDC_BASE + 0x0028)
84 #define LCDC_IMG_SIZE_XY (SPRD_LCDC_BASE + 0x002c)
85 #define LCDC_IMG_PITCH (SPRD_LCDC_BASE + 0x0030)
86 #define LCDC_IMG_DISP_XY (SPRD_LCDC_BASE + 0x0034)
88 #define LCDC_OSD1_CTRL (SPRD_LCDC_BASE + 0x0040)
89 #define LCDC_OSD2_CTRL (SPRD_LCDC_BASE + 0x0070)
90 #define LCDC_OSD3_CTRL (SPRD_LCDC_BASE + 0x0090)
91 #define LCDC_OSD4_CTRL (SPRD_LCDC_BASE + 0x00b0)
92 #define LCDC_OSD5_CTRL (SPRD_LCDC_BASE + 0x00d0)
94 #define LCDC_OSD1_BASE_ADDR (SPRD_LCDC_BASE + 0x0044)
95 #define LCDC_OSD1_ALPHA_BASE_ADDR (SPRD_LCDC_BASE + 0x0048)
96 #define LCDC_OSD1_SIZE_XY (SPRD_LCDC_BASE + 0x004c)
97 #define LCDC_OSD1_PITCH (SPRD_LCDC_BASE + 0x0050)
98 #define LCDC_OSD1_DISP_XY (SPRD_LCDC_BASE + 0x0054)
99 #define LCDC_OSD1_ALPHA (SPRD_LCDC_BASE + 0x0058)
100 #define LCDC_OSD1_GREY_RGB (SPRD_LCDC_BASE + 0x005c)
101 #define LCDC_OSD1_CK (SPRD_LCDC_BASE + 0x0060)
103 #define LCDC_IRQ_EN (SPRD_LCDC_BASE + 0x0120)
104 #define LCDC_IRQ_CLR (SPRD_LCDC_BASE + 0x0124)
105 #define LCDC_IRQ_STATUS (SPRD_LCDC_BASE + 0x0128)
106 #define LCDC_IRQ_RAW (SPRD_LCDC_BASE + 0x012c)
108 #define LCM_CTRL (SPRD_LCDC_BASE + 0x140)
109 #define LCM_PARAMETER0 (SPRD_LCDC_BASE + 0x144)
110 #define LCM_PARAMETER1 (SPRD_LCDC_BASE + 0x148)
111 #define LCM_IFMODE (SPRD_LCDC_BASE + 0x14c)
112 #define LCM_RGBMODE (SPRD_LCDC_BASE + 0x150)
113 #define LCM_RDDATA (SPRD_LCDC_BASE + 0x154)
114 #define LCM_STATUS (SPRD_LCDC_BASE + 0x158)
115 #define LCM_RSTN (SPRD_LCDC_BASE + 0x15c)
116 #define LCM_CD0 (SPRD_LCDC_BASE + 0x180)
117 #define LCM_DATA0 (SPRD_LCDC_BASE + 0x184)
118 #define LCM_CD1 (SPRD_LCDC_BASE + 0x190)
119 #define LCM_DATA1 (SPRD_LCDC_BASE + 0x194)
121 #define BITS_PER_PIXEL 16
123 //#include "sc8800g_rrm.h"
124 //#include "sc8800g_lcdc_manager.h" /* TEMP */
125 //#include "sc8800g_copybit_lcdc.h" /* TEMP */
126 /* TEMP, software make-up for lcdc's 4-byte-align only limitation */
127 //unsigned int fb_pa;
128 //unsigned int fb_va;
129 //unsigned int fb_va_cached;
132 struct sc8800fb_info {
133 // struct fb_info *fb;
136 struct lcd_spec *panel;
139 // struct rrmanager *rrm;
144 struct lcd_spec* panel;
148 //overlord for lcd adapt
149 static struct lcd_cfg lcd_panel[] = {
152 .panel = &lcd_panel_r61581,
157 .panel = &lcd_panel_rm68040,
161 .panel = &lcd_panel_hx8357,
165 vidinfo_t panel_info = {
172 static void __raw_bits_and(unsigned int v, unsigned int a)
174 __raw_writel((__raw_readl(a) & v), a);
178 static void __raw_bits_or(unsigned int v, unsigned int a)
180 __raw_writel((__raw_readl(a) | v), a);
183 static int32_t lcm_send_cmd (uint32_t cmd)
185 /* busy wait for ahb fifo full sign's disappearance */
186 while(__raw_readl(LCM_STATUS) & 0x2);
188 __raw_writel(cmd, LCM_CD0);
193 static int32_t lcm_send_cmd_data (uint32_t cmd, uint32_t data)
195 /* busy wait for ahb fifo full sign's disappearance */
196 while(__raw_readl(LCM_STATUS) & 0x2);
198 __raw_writel(cmd, LCM_CD0);
200 /* busy wait for ahb fifo full sign's disappearance */
201 while(__raw_readl(LCM_STATUS) & 0x2);
203 __raw_writel(data, LCM_DATA0);
208 static int32_t lcm_send_data (uint32_t data)
210 /* busy wait for ahb fifo full sign's disappearance */
211 while(__raw_readl(LCM_STATUS) & 0x2);
213 __raw_writel(data, LCM_DATA0);
218 static uint32_t lcm_read_data ()
220 volatile uint32_t i =32;
221 /* busy wait for ahb fifo full sign's disappearance */
222 while(__raw_readl(LCM_STATUS) & 0x2);
223 /* bit18 means 'read' */
224 __raw_writel(1<<18, LCM_DATA0);
226 /* busy wait for ahb fifo full sign's disappearance */
227 while(__raw_readl(LCM_STATUS) & 0x2);
231 return __raw_readl(LCM_RDDATA);
234 static struct ops_mcu lcm_mcu_ops = {
235 .send_cmd = lcm_send_cmd,
236 .send_cmd_data = lcm_send_cmd_data,
237 .send_data = lcm_send_data,
238 .read_data = lcm_read_data,
241 //extern struct lcdc_manager lm; /* TEMP */
242 //extern struct semaphore copybit_wait; /* TEMP */
243 //static irqreturn_t lcdc_isr(int irq, void *data)
246 // struct sc8800fb_info *fb = (struct sc8800fb_info *)data;
248 // val = __raw_readl(LCDC_IRQ_STATUS);
249 // if (val & (1<<0)){ /* lcdc done */
250 // FB_PRINT("--> lcdc_isr lm.mode=%d\n", lm.mode);
251 // __raw_bits_or((1<<0), LCDC_IRQ_CLR);
252 // if(lm.mode == LMODE_DISPLAY) /* TEMP */
253 // rrm_interrupt(fb->rrm);
255 // up(©bit_wait);
258 // return IRQ_HANDLED;
260 static void set_pins(void)
263 #define SPRD_CPC_BASE PIN_CTL_BASE
264 __raw_writel(0x1fff00, SPRD_CPC_BASE);
267 static unsigned long lcd_func_cfg[] = {
269 //MFP_CFG_X(LCD_CSN1,AF0,DS1,F_PULL_NONE,S_PULL_NONE,IO_Z),//LCD_CSN1
270 MFP_CFG_X(LCD_RSTN,AF0,DS1,F_PULL_NONE,S_PULL_UP,IO_Z),//LCD_RSTN
271 MFP_CFG_X(LCD_CD,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_CD
272 MFP_CFG_X(LCD_D0,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[0]
273 MFP_CFG_X(LCD_D1,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[1]
274 MFP_CFG_X(LCD_D2,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[2]
275 MFP_CFG_X(LCD_D3,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[3]
276 MFP_CFG_X(LCD_D4,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[4]
277 MFP_CFG_X(LCD_D5,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[5]
278 MFP_CFG_X(LCD_D6,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[6]
279 MFP_CFG_X(LCD_D7,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[7]
280 MFP_CFG_X(LCD_D8,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[8]
281 MFP_CFG_X(LCD_WRN,AF0,DS1,F_PULL_NONE,S_PULL_UP,IO_Z),//LCD_WRN
282 MFP_CFG_X(LCD_RDN,AF0,DS1,F_PULL_NONE,S_PULL_UP,IO_Z),//LCD_RDN
283 MFP_CFG_X(LCD_CSN0,AF0,DS1,F_PULL_NONE,S_PULL_UP,IO_Z),//LCD_CSN0
284 MFP_CFG_X(LCD_D9,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[9]
285 MFP_CFG_X(LCD_D10,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[10]
286 MFP_CFG_X(LCD_D11,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[11]
287 MFP_CFG_X(LCD_D12,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[12]
288 MFP_CFG_X(LCD_D13,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[13]
289 MFP_CFG_X(LCD_D14,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[14]
290 MFP_CFG_X(LCD_D15,AF0,DS1,F_PULL_NONE,S_PULL_DOWN,IO_Z),//LCD_D[15]
291 MFP_CFG_X(LCD_D16,AF0,DS1,F_PULL_NONE,S_PULL_NONE,IO_Z),//LCD_D[16]
292 MFP_CFG_X(LCD_D17,AF0,DS1,F_PULL_NONE,S_PULL_NONE,IO_Z),//LCD_D[17]
293 MFP_CFG_X(LCD_FMARK,AF0,DS1,F_PULL_NONE,S_PULL_NONE,IO_Z),//LCD_FMARK
297 sprd_mfp_config(lcd_func_cfg,ARRAY_SIZE(lcd_func_cfg));
299 static uint32_t panel_reset(struct lcd_spec *self)
302 __raw_writel(0x1, LCM_RSTN);
304 __raw_writel(0x0, LCM_RSTN);
306 __raw_writel(0x1, LCM_RSTN);
311 static void lcdc_mcu_init(struct sc8800fb_info *sc8800fb)
314 __raw_bits_or(1<<0, LCDC_CTRL);
317 __raw_bits_or(1<<1, LCDC_CTRL);
320 __raw_bits_and(~(1<<2), LCDC_CTRL);
322 FB_PRINT("@fool2[%s] LCDC_CTRL: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_CTRL));
325 __raw_writel(0x0, LCDC_BG_COLOR); //red
327 FB_PRINT("@fool2[%s] LCDC_BG_COLOR: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_BG_COLOR));
329 /* dithering enable*/
330 //__raw_bits_or(1<<4, LCDC_CTRL);
333 static int mount_panel(struct sc8800fb_info *sc8800fb, struct lcd_spec *panel)
335 /* TODO: check whether the mode/res are supported */
337 sc8800fb->panel = panel;
339 panel->info.mcu->ops = sc8800fb->ops;
341 panel->ops->lcd_reset = panel_reset;
345 //static int setup_fbmem(struct sc8800fb_info *sc8800fb, struct platform_device *pdev)
347 // uint32_t len, addr;
349 // len = sc8800fb->panel->width * sc8800fb->panel->height * (BITS_PER_PIXEL/8) * 2;
351 // /* the addr should be 8 byte align */
352 // addr = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, get_order(len));
356 // printk("sc8800g_fb got %d bytes mem at 0x%x\n", len, addr);
357 // sc8800fb->fb->fix.smem_start = __pa(addr);
358 // sc8800fb->fb->fix.smem_len = len;
359 // sc8800fb->fb->screen_base = (char*)addr;
361 // /* TEMP, software make-up for lcdc's 4-byte-align only limitation */
362 // fb_pa = sc8800fb->fb->fix.smem_start;
363 // fb_va_cached = sc8800fb->fb->screen_base;
364 // fb_va = (unsigned int)ioremap(sc8800fb->fb->fix.smem_start,
365 // sc8800fb->fb->fix.smem_len);
366 // printk("sc8800g_fb fb_va=0x%x\n", fb_va, sc8800fb->fb->fix.smem_len);
371 //static int sc8800fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
373 // if ((var->xres != info->var.xres) ||
374 // (var->yres != info->var.yres) ||
375 // (var->xres_virtual != info->var.xres_virtual) ||
376 // (var->yres_virtual != info->var.yres_virtual) ||
377 // (var->xoffset != info->var.xoffset) ||
378 // (var->bits_per_pixel != info->var.bits_per_pixel) ||
379 // (var->grayscale != info->var.grayscale))
384 static void real_set_layer(void *data)
386 struct sc8800fb_info *info = (struct sc8800fb_info *)data;
389 /* image layer base */
390 reg_val = info->smem_start;
391 reg_val = (reg_val>>2) & 0x3fffffff;
392 __raw_writel(reg_val, LCDC_OSD1_BASE_ADDR);
395 static void real_refresh(void *para)
397 struct sc8800fb_info *sc8800fb = (struct sc8800fb_info *)para;
399 //struct fb_info *info = sc8800fb->fb;
401 sc8800fb->panel->ops->lcd_invalidate(sc8800fb->panel);
403 reg_val = sc8800fb->panel->width * sc8800fb->panel->height;
404 reg_val |= (1<<20); /* for device 0 */
405 reg_val &=~ ((1<<26)|(1<<27) | (1<<28)); /* FIXME: hardcoded cs 1 */
406 __raw_writel(reg_val, LCM_CTRL);
408 __raw_bits_or((1<<3), LCDC_CTRL); /* start refresh */
411 //static int real_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
413 // rrm_refresh(LID_OSD1, NULL, info);
415 // FB_PRINT("@fool2[%s] LCDC_CTRL: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_CTRL));
416 // FB_PRINT("@fool2[%s] LCDC_DISP_SIZE: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_DISP_SIZE));
417 // FB_PRINT("@fool2[%s] LCDC_LCM_START: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_LCM_START));
418 // FB_PRINT("@fool2[%s] LCDC_LCM_SIZE: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_LCM_SIZE));
419 // FB_PRINT("@fool2[%s] LCDC_BG_COLOR: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_BG_COLOR));
421 // FB_PRINT("@fool2[%s] LCDC_OSD1_CTRL: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_CTRL));
422 // FB_PRINT("@fool2[%s] LCDC_OSD1_BASE_ADDR: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_BASE_ADDR));
423 // FB_PRINT("@fool2[%s] LCDC_OSD1_ALPHA_BASE_ADDR: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_ALPHA_BASE_ADDR));
424 // FB_PRINT("@fool2[%s] LCDC_OSD1_SIZE_XY: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_SIZE_XY));
425 // FB_PRINT("@fool2[%s] LCDC_OSD1_PITCH: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_PITCH));
426 // FB_PRINT("@fool2[%s] LCDC_OSD1_DISP_XY: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_DISP_XY));
427 // FB_PRINT("@fool2[%s] LCDC_OSD1_ALPHA: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_ALPHA));
428 // FB_PRINT("@fool2[%s] LCDC_OSD1_GREY_RGB: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_GREY_RGB));
429 // FB_PRINT("@fool2[%s] LCDC_OSD1_CK: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_CK));
431 // FB_PRINT("@fool2[%s] LCM_CTRL: 0x%x\n", __FUNCTION__, __raw_readl(LCM_CTRL));
432 // FB_PRINT("@fool2[%s] LCM_PARAMETER0: 0x%x\n", __FUNCTION__, __raw_readl(LCM_PARAMETER0));
433 // FB_PRINT("@fool2[%s] LCM_PARAMETER1: 0x%x\n", __FUNCTION__, __raw_readl(LCM_PARAMETER1));
434 // FB_PRINT("@fool2[%s] LCM_IFMODE: 0x%x\n", __FUNCTION__, __raw_readl(LCM_IFMODE));
435 // FB_PRINT("@fool2[%s] LCM_RGBMODE: 0x%x\n", __FUNCTION__, __raw_readl(LCM_RGBMODE));
439 //static struct fb_ops sc8800fb_ops = {
440 // .owner = THIS_MODULE,
441 // .fb_check_var = sc8800fb_check_var,
442 // .fb_pan_display = real_pan_display,
443 // .fb_fillrect = cfb_fillrect,
444 // .fb_copyarea = cfb_copyarea,
445 // .fb_imageblit = cfb_imageblit,
448 static unsigned PP[16];
449 //static void setup_fb_info(struct sc8800fb_info *sc8800fb)
451 // struct fb_info *fb= sc8800fb->fb;
454 // fb->fbops = &sc8800fb_ops;
455 // fb->flags = FBINFO_DEFAULT;
457 // /* finish setting up the fb_info struct */
458 // strncpy(fb->fix.id, "sc8800fb", 16);
459 // fb->fix.ypanstep = 1;
460 // fb->fix.type = FB_TYPE_PACKED_PIXELS;
461 // fb->fix.visual = FB_VISUAL_TRUECOLOR;
462 // fb->fix.line_length = sc8800fb->panel->width * 16/8;
464 // fb->var.xres = sc8800fb->panel->width;
465 // fb->var.yres = sc8800fb->panel->height;
466 // fb->var.width = sc8800fb->panel->width;
467 // fb->var.height = sc8800fb->panel->height;
468 // fb->var.xres_virtual = sc8800fb->panel->width;
469 // fb->var.yres_virtual = sc8800fb->panel->height * 2;
470 // fb->var.bits_per_pixel = BITS_PER_PIXEL;
471 // fb->var.accel_flags = 0;
473 // fb->var.yoffset = 0;
475 // fb->var.red.offset = 11;
476 // fb->var.red.length = 5;
477 // fb->var.red.msb_right = 0;
478 // fb->var.green.offset = 5;
479 // fb->var.green.length = 6;
480 // fb->var.green.msb_right = 0;
481 // fb->var.blue.offset = 0;
482 // fb->var.blue.length = 5;
483 // fb->var.blue.msb_right = 0;
485 // r = fb_alloc_cmap(&fb->cmap, 16, 0);
486 // fb->pseudo_palette = PP;
489 // for (r = 1; r < 16; r++)
490 // PP[r] = 0xffffffff;
492 static void lcdc_lcm_configure(struct sc8800fb_info *sc8800fb)
496 //wait until AHB FIFO is empty
497 while(!(__raw_readl(LCM_STATUS) & (1<<2)));
499 //__raw_writel(0, LCDC_LCM0PARAMETER0); /* LCM_PARAMETER0 */
501 /* CS0 bus mode [BIT0]: 8080/6800 */
502 switch (sc8800fb->panel->info.mcu->bus_mode) {
513 __raw_writel((bits&0x1), LCM_IFMODE);
514 FB_PRINT("@fool2[%s] LCM_IFMODE: 0x%x\n", __FUNCTION__, __raw_readl(LCM_IFMODE));
516 /* CS0 bus width [BIT1:0] */
517 switch (sc8800fb->panel->info.mcu->bus_width) {
534 __raw_writel((bits&0x3), LCM_RGBMODE);
535 FB_PRINT("@fool2[%s] LCM_RGBMODE: 0x%x\n", __FUNCTION__, __raw_readl(LCM_RGBMODE));
538 uint32_t CHIP_GetMcuClk (void)
540 uint32_t clk_mcu_sel;
541 uint32_t clk_mcu = 0;
543 clk_mcu_sel = __raw_readl(AHB_ARM_CLK);
544 clk_mcu_sel = (clk_mcu_sel >> 23) & 0x3;
566 static void lcdc_update_lcm_timing(struct sc8800fb_info *sc8800fb)
569 uint32_t ahb_div,ahb_clk;
570 uint32_t ahb_clk_cycle;
571 uint32_t rcss, rlpw, rhpw, wcss, wlpw, whpw;
573 reg_value = __raw_readl(AHB_ARM_CLK);
575 ahb_div = ( reg_value>>4 ) & 0x7;
577 ahb_div = ahb_div + 1;
579 if(__raw_readl (AHB_ARM_CLK) & (1<<30))
581 ahb_div = ahb_div << 1;
583 if(__raw_readl (AHB_ARM_CLK) & (1<<31))
587 ahb_clk = CHIP_GetMcuClk()/ahb_div;
589 FB_PRINT("@fool2[%s] ahb_clk: 0x%x\n", __FUNCTION__, ahb_clk);
591 /* LCD_UpdateTiming() */
592 ahb_clk_cycle = (100000000 >> 17)/(ahb_clk >> 20 );
594 rcss = ((sc8800fb->panel->info.mcu->timing->rcss/ahb_clk_cycle+1)<3)?
595 (sc8800fb->panel->info.mcu->timing->rcss/ahb_clk_cycle+1):3;
596 rlpw = ((sc8800fb->panel->info.mcu->timing->rlpw/ahb_clk_cycle+1)<14)?
597 (sc8800fb->panel->info.mcu->timing->rlpw/ahb_clk_cycle+1):14;
598 rhpw = ((sc8800fb->panel->info.mcu->timing->rhpw/ahb_clk_cycle+1)<14)?
599 (sc8800fb->panel->info.mcu->timing->rhpw/ahb_clk_cycle+1):14;
600 wcss = ((sc8800fb->panel->info.mcu->timing->wcss/ahb_clk_cycle+1)<3)?
601 (sc8800fb->panel->info.mcu->timing->wcss/ahb_clk_cycle+1):3;
602 wlpw = ((sc8800fb->panel->info.mcu->timing->wlpw/ahb_clk_cycle+1)<14)?
603 (sc8800fb->panel->info.mcu->timing->wlpw/ahb_clk_cycle+1):14;
604 whpw = ((sc8800fb->panel->info.mcu->timing->whpw/ahb_clk_cycle+1)<14)?
605 (sc8800fb->panel->info.mcu->timing->whpw/ahb_clk_cycle+1):14;
607 //wait until AHB FIFO if empty
608 while(!(__raw_readl(LCM_STATUS) & (1<<2)));
610 /* LCDC_ChangePulseWidth() */
611 __raw_writel(whpw |(wlpw<<4) |(wcss<<8) | (rhpw<<10) | (rlpw<<14) |(rcss<<18),LCM_PARAMETER0); /* FIXME: hardcoded for !CS0 */
613 //__raw_writel( 0x77555, LCDC_LCMPARAMETER0); /* @fool2, tmp */
614 FB_PRINT("@fool2[%s] LCM_PARAMETER0: 0x%x\n", __FUNCTION__, __raw_readl(LCM_PARAMETER0));
616 static inline int set_lcdsize( void )
620 //reg_val = ( info->var.xres & 0x3ff) | (( info->var.yres & 0x3ff )<<16);
621 reg_val = ( 640 & 0x3ff) | (( 640 & 0x3ff )<<16);
622 __raw_writel(reg_val, LCDC_DISP_SIZE);
624 FB_PRINT("@fool2[%s] LCDC_DISP_SIZE: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_DISP_SIZE));
628 static inline int set_lcmrect( struct sc8800fb_info *info)
632 __raw_writel(0, LCDC_LCM_START);
634 reg_val = ( info->panel->width & 0x3ff) | (( info->panel->height & 0x3ff )<<16);
635 __raw_writel(reg_val, LCDC_LCM_SIZE);
637 FB_PRINT("@fool2[%s] LCDC_LCM_START: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_LCM_START));
638 FB_PRINT("@fool2[%s] LCDC_LCM_SIZE: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_LCM_SIZE));
642 int set_lcdc_layers(struct sc8800fb_info *info)
645 /******************* OSD1 layer setting **********************/
649 * 1. there's only one fbdev, and only block0 is used
650 * 2. the pan operation is a sync one
653 __raw_bits_and(~(1<<0),LCDC_IMG_CTRL);
654 __raw_bits_and(~(1<<0),LCDC_OSD2_CTRL);
655 __raw_bits_and(~(1<<0),LCDC_OSD3_CTRL);
656 __raw_bits_and(~(1<<0),LCDC_OSD4_CTRL);
657 __raw_bits_and(~(1<<0),LCDC_OSD5_CTRL);
658 /*enable OSD1 layer*/
659 __raw_bits_or((1<<0),LCDC_OSD1_CTRL);
662 __raw_bits_and(~(1<<1),LCDC_OSD1_CTRL); //disable
664 /*alpha mode select*/
665 __raw_bits_or((1<<2),LCDC_OSD1_CTRL); //block alpha
668 __raw_bits_and(~(1<<6),LCDC_OSD1_CTRL); //RGB565
669 __raw_bits_or(1<<5,LCDC_OSD1_CTRL);
670 __raw_bits_and(~(1<<4),LCDC_OSD1_CTRL);
671 __raw_bits_or(1<<3,LCDC_OSD1_CTRL);
674 __raw_bits_or(1<<8,LCDC_OSD1_CTRL); //little endian
675 __raw_bits_and(~(1<<7),LCDC_OSD1_CTRL);
679 __raw_bits_or(1<<10,LCDC_IMG_CTRL);
680 __raw_bits_and(~(1<<9),LCDC_IMG_CTRL);
683 FB_PRINT("@fool2[%s] LCDC_OSD1_CTRL: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_CTRL));
685 /* OSD1 layer base */
686 //reg_val = (info->var.yoffset)?info->fix.smem_start: (info->fix.smem_start+ info->fix.smem_len/2);
687 reg_val = info->smem_start;
688 reg_val = (reg_val >>2)& 0x3fffffff;
689 __raw_writel(reg_val, LCDC_OSD1_BASE_ADDR);
691 FB_PRINT("@fool2[%s] LCDC_OSD1_BASE_ADDR: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_BASE_ADDR));
693 /*OSD1 layer alpha value*/
694 __raw_writel(0xff, LCDC_OSD1_ALPHA);
696 FB_PRINT("@fool2[%s] LCDC_OSD1_ALPHA: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_ALPHA));
699 //__raw_writel(reg_val, LCDC_OSD1_ALPHA_BASE_ADDR);
702 reg_val = ( info->panel->width & 0x3ff) | (( info->panel->height & 0x3ff )<<16);
703 __raw_writel(reg_val, LCDC_OSD1_SIZE_XY);
705 FB_PRINT("@fool2[%s] LCDC_OSD1_SIZE_XY: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_SIZE_XY));
707 /*OSD1 layer start position*/
708 __raw_writel(0, LCDC_OSD1_DISP_XY);
710 FB_PRINT("@fool2[%s] LCDC_OSD1_DISP_XY: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_DISP_XY));
713 reg_val = ( info->panel->width & 0x3ff) ;
714 __raw_writel(reg_val, LCDC_OSD1_PITCH);
716 FB_PRINT("@fool2[%s] LCDC_OSD1_PITCH: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_OSD1_PITCH));
718 /*OSD1 color_key value*/
724 /******************** Image layer settting **********************/
728 * 1. there's only one fbdev, and only block0 is used
729 * 2. the pan operation is a sync one
732 __raw_bits_and(~(1<<0),LCDC_OSD1_CTRL);
733 __raw_bits_and(~(1<<0),LCDC_OSD2_CTRL);
734 __raw_bits_and(~(1<<0),LCDC_OSD3_CTRL);
735 __raw_bits_and(~(1<<0),LCDC_OSD4_CTRL);
736 __raw_bits_and(~(1<<0),LCDC_OSD5_CTRL);
737 /*enable imge layer*/
738 __raw_bits_or((1<<0),LCDC_IMG_CTRL);
741 __raw_bits_or(1<<6,LCDC_IMG_CTRL);
742 __raw_bits_and(~(1<<5),LCDC_IMG_CTRL);
743 //__raw_bits_or(1<<7,LCDC_IMG_CTRL);
744 //__raw_bits_and(~(1<<8),LCDC_IMG_CTRL);
747 __raw_bits_or(1<<1,LCDC_IMG_CTRL); //RGB565
748 __raw_bits_and(~(1<<2),LCDC_IMG_CTRL);
749 __raw_bits_or(1<<3,LCDC_IMG_CTRL);
750 __raw_bits_and(~(1<<4),LCDC_IMG_CTRL);
752 FB_PRINT("@fool2[%s] LCDC_IMG_CTRL: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_IMG_CTRL));
754 /* image layer base */
755 reg_val = (info->var.yoffset)?info->fix.smem_start: (info->fix.smem_start+ info->fix.smem_len/2);
756 reg_val = (reg_val >>2)& 0x3fffffff;
757 __raw_writel(reg_val, LCDC_IMG_Y_BASE_ADDR);
759 FB_PRINT("@fool2[%s] LCDC_IMG_Y_BASE_ADDR: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_IMG_Y_BASE_ADDR));
762 reg_val = ( info->var.xres & 0x3ff) | (( info->var.yres & 0x3ff )<<16);
763 __raw_writel(reg_val, LCDC_IMG_SIZE_XY);
765 FB_PRINT("@fool2[%s] LCDC_IMG_SIZE_XY: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_IMG_SIZE_XY));
767 /*image layer start position*/
768 __raw_writel(0, LCDC_IMG_DISP_XY);
770 /*image layer pitch*/
771 reg_val = ( info->var.xres & 0x3ff) ;
772 __raw_writel(reg_val, LCDC_IMG_PITCH);
774 FB_PRINT("@fool2[%s] LCDC_IMG_DISP_XY: 0x%x\n", __FUNCTION__, __raw_readl(LCDC_IMG_DISP_XY));
778 /*LCDC workplane size*/
781 /*LCDC LCM rect size*/
787 static void hw_early_init(struct sc8800fb_info *sc8800fb)
792 //select LCD clock source
793 __raw_bits_and(~(1<<6), GR_PLL_SCR); //pll_src=96M
794 __raw_bits_and(~(1<<7), GR_PLL_SCR);
797 __raw_bits_and(~(1<<0), GR_GEN4); //div=0
798 __raw_bits_and(~(1<<1), GR_GEN4);
799 __raw_bits_and(~(1<<2), GR_GEN4);
802 __raw_bits_or(1<<3, AHB_CTL0);
805 __raw_bits_or(1<<3, AHB_SOFT_RST);
807 __raw_bits_and(~(1<<3), AHB_SOFT_RST);
810 /* enable LCDC_DONE IRQ */
811 __raw_bits_or((1<<0), LCDC_IRQ_EN);
813 /* init lcdc mcu mode using default configuration */
814 lcdc_mcu_init(sc8800fb);
817 static void hw_init(struct sc8800fb_info *sc8800fb)
819 /* only MCU mode is supported currently */
820 if (LCD_MODE_RGB == sc8800fb->panel->mode)
823 //__raw_bits_or((1<<0), LCDC_DAC_CONTROL_REG); /*close tv_out */
825 panel_reset(sc8800fb->panel);
827 /* set lcdc-lcd interface parameters */
828 lcdc_lcm_configure(sc8800fb);
830 /* set timing parameters for LCD */
831 lcdc_update_lcm_timing(sc8800fb);
834 static void hw_later_init(struct sc8800fb_info *sc8800fb)
836 /* init mounted lcd panel */
837 sc8800fb->panel->ops->lcd_init(sc8800fb->panel);
839 set_lcdc_layers(sc8800fb);
843 void set_backlight(uint32_t value)
846 ANA_REG_AND(WHTLED_CTL, ~(WHTLED_PD_SET | WHTLED_PD_RST));
847 ANA_REG_OR(WHTLED_CTL, WHTLED_PD_RST);
848 ANA_REG_MSK_OR (WHTLED_CTL, ( (value << WHTLED_V_SHIFT) &WHTLED_V_MSK), WHTLED_V_MSK);
851 struct sc8800fb_info *sc8800fb;
853 static uint32_t lcd_id_to_kernel = 0;
855 void save_lcd_id_to_kernel(uint32_t id)
857 lcd_id_to_kernel = id;
860 uint32_t load_lcd_id_to_kernel()
862 return lcd_id_to_kernel;
865 static int find_adapt_from_saved()
868 //we will decide how to save lcdid later
870 uint32_t id = savedvalue;
871 for(i = 0;i<(sizeof(lcd_panel))/(sizeof(lcd_panel[0]));i++)
873 if(id == lcd_panel[i].lcd_id)
875 save_lcd_id_to_kernel(id);
883 static int lcd_readid_default(struct lcd_spec *self)
886 //default id reg is 0
887 self->info.mcu->ops->send_cmd(0x0);
889 if(self->info.mcu->bus_width == 8)
891 dummy = (self->info.mcu->ops->read_data())&0xff;
893 dummy |= (self->info.mcu->ops->read_data())&0xff;
897 dummy = (self->info.mcu->ops->read_data())&0xffff;
903 static int find_adapt_from_readid(struct sc8800fb_info *sc8800fb)
907 for(i = 0;i<(sizeof(lcd_panel))/(sizeof(lcd_panel[0]));i++)
910 mount_panel(sc8800fb,lcd_panel[i].panel);
911 //hw init to every panel
914 if(sc8800fb->panel->ops->lcd_readid)
916 id = sc8800fb->panel->ops->lcd_readid(sc8800fb->panel);
920 id = lcd_readid_default(sc8800fb->panel);
922 //if the id is right?
923 if(id == lcd_panel[i].lcd_id)
925 save_lcd_id_to_kernel(id);
933 static int sc8800fb_probe(void * lcdbase)
935 //struct fb_info *fb;
939 FB_PRINT("@fool2[%s]\n", __FUNCTION__);
940 FB_PRINT("sc8800g_fb initialize!\n");
942 //lm_init(4); /* TEMP */
944 //fb = framebuffer_alloc(sizeof(struct sc8800fb_info), &pdev->dev);
947 //sc8800fb = fb->par;
949 //sc8800fb->ops = &lcm_mcu_ops;
950 //sc8800fb->rrm = rrm_init(real_refresh, (void*)sc8800fb);
951 //rrm_layer_init(LID_OSD1, 2, real_set_layer);
953 sc8800fb = malloc(sizeof(struct sc8800fb_info));
955 printk("not enough memory\n");
958 sc8800fb->ops = &lcm_mcu_ops;
960 //we maybe readid ,so hardware should be init
961 hw_early_init(sc8800fb);
963 //only test 6810 ,do not want get troubles on other plateform
964 #ifdef CONFIG_LCD_SP6810A
966 lcd_adapt = find_adapt_from_saved();
969 lcd_adapt = find_adapt_from_readid(sc8800fb);
976 #ifdef CONFIG_LCD_SP8805GA
979 #ifdef CONFIG_LCD_OPENPHONE
983 ret = mount_panel(sc8800fb, lcd_panel[lcd_adapt].panel);
985 printk("unsupported panel!!");
989 sc8800fb->smem_start = lcdbase;
990 sc8800fb->smem_len = sc8800fb->panel->width * sc8800fb->panel->height;
992 //ret = setup_fbmem(sc8800fb, pdev);
996 //setup_fb_info(sc8800fb);
998 //ret = register_framebuffer(fb);
1000 // framebuffer_release(fb);
1005 hw_later_init(sc8800fb);
1006 real_set_layer(sc8800fb);
1008 //copybit_lcdc_init(); /* TEMP */
1010 /* FIXME: put the BL stuff to where it belongs. */
1011 //set_backlight(50);
1014 if(0){ /* in-kernel test code */
1015 int size = sc8800fb->panel->width * sc8800fb->panel->height;
1016 short adie_chip_id = ANA_REG_GET(ANA_ADIE_CHIP_ID);
1019 if (adie_chip_id == 0) {
1020 unsigned short *ptr=(unsigned short*)sc8800fb->smem_start;
1021 FB_PRINT("adi v0 buffur prt is 0x%x\n", ptr);
1023 int len = size /3 ; /* 1/3 frame pixels */
1026 for(offset=0;offset< len;offset++)
1027 (* (volatile unsigned short *)(ptr++))= 0xf800; //red
1028 for(offset=0;offset< len;offset++)
1029 (* (volatile unsigned short *)(ptr++))= 0x07e0; //green
1030 for(offset=0;offset< len;offset++)
1031 (* (volatile unsigned short *)(ptr++))= 0x001f; //blue
1033 unsigned short *ptr=(unsigned short*)sc8800fb->smem_start;
1034 FB_PRINT("adi v1 buffur prt is 0x%x\n", ptr);
1035 int len = size ; /* 1/3 frame pixels */
1038 for(offset=0;offset< len;offset++)
1039 (* (volatile unsigned short *)(ptr++))= 0xf800; //red
1044 //real_pan_display(&sc8800fb->fb->var, &test_info);
1045 real_refresh(sc8800fb);
1056 void lcd_initcolregs(void)
1060 void lcd_disable(void)
1065 /* References in this function refer to respective Linux kernel sources */
1066 void lcd_enable(void)
1070 void lcd_ctrl_init(void *lcdbase)
1072 sc8800fb_probe(lcdbase);
1075 void lcd_display(void)
1077 real_refresh(sc8800fb);
1079 #ifdef CONFIG_LCD_INFO
1081 extern nand_info_t nand_info[];
1083 void lcd_show_board_info(void)
1085 ulong dram_size, nand_size;
1090 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
1091 dram_size += gd->bd->bi_dram[i].size;
1093 for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
1094 nand_size += nand_info[i].size;
1096 lcd_printf("\n%s\n", U_BOOT_VERSION);
1097 lcd_printf(" %ld MB SDRAM, %ld MB NAND\n",
1100 lcd_printf(" Board : esd ARM9 \n");
1101 lcd_printf(" Mach-type : %lu\n", gd->bd->bi_arch_number);
1103 #endif /* CONFIG_LCD_INFO */