int s3cfb_set_clock(struct s3cfb_global *ctrl, unsigned long rate) { struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev); unsigned int cfg, maxclk, src_clk, vclk, div, remainder, remainder_div; u64 div64; //fimd_clk_reset(); if (pdata->interface_mode == FIMD_CPU_INTERFACE) { /* in case of CPU Interface, it can use up to 100MHz. */ maxclk = 100 * 1000000; } else { /* * In case of RGB Interface max clock should be 86MHz * because of pad tolerance. */ maxclk = 86 * 1000000; } /* fixed clock source: hclk */ cfg = readl(ctrl->regs + S3C_VIDCON0); cfg &= ~(S3C_VIDCON0_CLKSEL_MASK | S3C_VIDCON0_CLKVALUP_MASK | S3C_VIDCON0_CLKVAL_F(0xFF) | S3C_VIDCON0_VCLKEN_MASK | S3C_VIDCON0_CLKDIR_MASK); cfg |= (S3C_VIDCON0_CLKSEL_SCLK | S3C_VIDCON0_CLKVALUP_ALWAYS | S3C_VIDCON0_VCLKEN_NORMAL | S3C_VIDCON0_CLKDIR_DIVIDED); if (rate) vclk = rate; else vclk = ctrl->fb[pdata->default_win]->var.pixclock; src_clk = ctrl->clock->parent->rate; if (vclk > maxclk) vclk = maxclk; div64 = (u64) src_clk; /* get quotient and remainder. */ remainder = do_div(div64, vclk); div = (u32) div64; remainder *= 10; remainder_div = remainder / vclk; /* round about one places of decimals. */ if (remainder_div >= 5) div++; if (pdata->machine_is_p1p2) cfg |= S3C_VIDCON0_CLKVAL_F(3); else cfg |= S3C_VIDCON0_CLKVAL_F(11 - 1); writel(cfg, ctrl->regs + S3C_VIDCON0); //sehun_lcd dev_info(ctrl->dev, " source clock: %d, vclk: %d, vclk div: %d\n", src_clk, vclk, div); return 0; }
int s3cfb_set_clock(struct s3cfb_global *ctrl) { struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev); u32 cfg, maxclk, src_clk, vclk, div; maxclk = 86 * 1000000; /* fixed clock source: hclk */ cfg = readl(ctrl->regs + S3C_VIDCON0); cfg &= ~(S3C_VIDCON0_CLKSEL_MASK | S3C_VIDCON0_CLKVALUP_MASK | S3C_VIDCON0_VCLKEN_MASK | S3C_VIDCON0_CLKDIR_MASK | S3C_VIDCON0_CLKVAL_F(-1)); cfg |= (S3C_VIDCON0_CLKVALUP_ALWAYS | S3C_VIDCON0_VCLKEN_NORMAL | S3C_VIDCON0_CLKDIR_DIVIDED); if (strcmp(pdata->clk_name, "sclk_fimd") == 0) { cfg |= S3C_VIDCON0_CLKSEL_SCLK; src_clk = clk_get_rate(ctrl->clock); printk(KERN_INFO "FIMD src sclk = %d\n", src_clk); } else { cfg |= S3C_VIDCON0_CLKSEL_HCLK; src_clk = ctrl->clock->parent->rate; printk(KERN_INFO "FIMD src hclk = %d\n", src_clk); } vclk = ctrl->pixclock_hz; if (vclk > maxclk) { dev_info(ctrl->dev, "vclk(%d) should be smaller than %d\n", vclk, maxclk); /* vclk = maxclk; */ } div = src_clk / vclk; if (src_clk % vclk) div++; if ((src_clk/div) > maxclk) dev_info(ctrl->dev, "vclk(%d) should be smaller than %d Hz\n", src_clk/div, maxclk); cfg |= S3C_VIDCON0_CLKVAL_F(div - 1); writel(cfg, ctrl->regs + S3C_VIDCON0); dev_dbg(ctrl->dev, "parent clock: %d, vclk: %d, vclk div: %d\n", src_clk, vclk, div); s3cfb_readjust_pixclock(ctrl, src_clk, div); return 0; }
int s3cfb_set_clock(struct s3cfb_global *ctrl) { struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev); unsigned int cfg, maxclk, src_clk, vclk, div; maxclk = 66 * 1000000; /* fixed clock source: hclk */ cfg = readl(ctrl->regs + S3C_VIDCON0); cfg &= ~(S3C_VIDCON0_CLKSEL_MASK | S3C_VIDCON0_CLKVALUP_MASK | S3C_VIDCON0_VCLKEN_MASK | S3C_VIDCON0_CLKDIR_MASK); cfg |= (S3C_VIDCON0_CLKSEL_HCLK | S3C_VIDCON0_CLKVALUP_ALWAYS | S3C_VIDCON0_VCLKEN_NORMAL | S3C_VIDCON0_CLKDIR_DIVIDED); src_clk = ctrl->clock->parent->rate; vclk = ctrl->fb[pdata->default_win]->var.pixclock; if (vclk > maxclk) vclk = maxclk; div = src_clk / vclk; if (src_clk % vclk) div++; cfg |= S3C_VIDCON0_CLKVAL_F(div - 1); writel(cfg, ctrl->regs + S3C_VIDCON0); dev_dbg(ctrl->dev, "parent clock: %d, vclk: %d, vclk div: %d\n", src_clk, vclk, div); return 0; }
int s3c_fimd_set_clock(struct s3c_fimd_global *ctrl) { struct s3c_platform_fimd *plat; u32 cfg, maxclk, src_clk, vclk, div; plat = to_fimd_plat(ctrl->dev) maxclk = 66 * 1000000; /* fixed clock source: hclk */ cfg = readl(ctrl->regs + S3C_VIDCON0); cfg &= ~(S3C_VIDCON0_CLKSEL_MASK | S3C_VIDCON0_CLKVALUP_MASK | \ S3C_VIDCON0_VCLKEN_MASK | S3C_VIDCON0_CLKDIR_MASK); cfg |= (S3C_VIDCON0_CLKSEL_HCLK | S3C_VIDCON0_CLKVALUP_ALWAYS | \ S3C_VIDCON0_VCLKEN_NORMAL | S3C_VIDCON0_CLKDIR_DIVIDED); src_clk = ctrl->clock->parent->rate; vclk = plat->clockrate; if (vclk > maxclk) vclk = maxclk; div = (int) (src_clk / vclk); cfg |= S3C_VIDCON0_CLKVAL_F(div - 1); writel(cfg, ctrl->regs + S3C_VIDCON0); return 0; }
int get_divider(struct fb_info *fb) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); struct lcdfreq_info *lcdfreq = fbdev->data; struct clksrc_clk *sclk; struct clk *clk; u32 rate, reg, i; u8 fimd_div; sclk = container_of(fbdev->clock, struct clksrc_clk, clk); clk = clk_get_parent(clk_get_parent(fbdev->clock)); rate = clk_get_rate(clk); lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv = DIV_ROUND_CLOSEST(rate, lcdfreq->table[LEVEL_NORMAL].vclk); lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv = DIV_ROUND_CLOSEST(rate, lcdfreq->table[LEVEL_LIMIT].vclk); fimd_div = gcd(lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv, lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv); if ((!fimd_div) || (fimd_div > 16)) { dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); goto err; } lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv /= fimd_div; lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv /= fimd_div; dev_info(fb->dev, "%s rate is %d, fimd divider=%d\n", clk->name, rate, fimd_div); fimd_div--; for (i = 0; i < LCDFREQ_LEVEL_END; i++) { if (lcdfreq->table[i].cmu_clkdiv > 16) { dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); goto err; } dev_info(fb->dev, "%dhz div is %d\n", lcdfreq->table[i].hz, lcdfreq->table[i].cmu_clkdiv); lcdfreq->table[i].cmu_clkdiv--; } reg = (readl(fbdev->regs + S3C_VIDCON0) & (S3C_VIDCON0_CLKVAL_F(0xff))) >> 6; if (fimd_div != reg) { dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); goto err; } reg = (readl(sclk->reg_div.reg)) >> sclk->reg_div.shift; reg &= 0xf; if (lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv != reg) { dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); goto err; } return 0; err: return -EINVAL; }
/******************************************************************************* * * Init video chip with common Linux graphic modes (lilo) */ void *video_hw_init (void) { S5PC11X_FB * const fb = S5PC11X_GetBase_FB(); GraphicDevice *pGD = (GraphicDevice *)&smi; int videomode; unsigned long t1, hsynch, vsynch; char *penv; int tmp, i, bits_per_pixel; struct ctfb_res_modes *res_mode; struct ctfb_res_modes var_mode; int clkval; /* Search for video chip */ printf("Video: "); tmp = 0; videomode = CFG_SYS_DEFAULT_VIDEO_MODE; /* get video mode via environment */ if ((penv = getenv ("videomode")) != NULL) { /* deceide if it is a string */ if (penv[0] <= '9') { videomode = (int) simple_strtoul (penv, NULL, 16); tmp = 1; } } else { tmp = 1; } if (tmp) { /* parameter are vesa modes */ /* search params */ for (i = 0; i < VESA_MODES_COUNT; i++) { if (vesa_modes[i].vesanr == videomode) break; } if (i == VESA_MODES_COUNT) { printf ("no VESA Mode found, switching to mode 0x%x ", CFG_SYS_DEFAULT_VIDEO_MODE); i = 0; } res_mode = (struct ctfb_res_modes *)&res_mode_init[vesa_modes[i].resindex]; bits_per_pixel = vesa_modes[i].bits_per_pixel; } else { res_mode = (struct ctfb_res_modes *) &var_mode; bits_per_pixel = video_get_params (res_mode, penv); } /* calculate hsynch and vsynch freq (info only) */ t1 = (res_mode->left_margin + res_mode->xres + res_mode->right_margin + res_mode->hsync_len) / 8; t1 *= 8; t1 *= res_mode->pixclock; t1 /= 1000; hsynch = 1000000000L / t1; t1 *= (res_mode->upper_margin + res_mode->yres + res_mode->lower_margin + res_mode->vsync_len); t1 /= 1000; vsynch = 1000000000L / t1; /* fill in Graphic device struct */ sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres, res_mode->yres, bits_per_pixel, (hsynch / 1000), (vsynch / 1000)); printf ("%s\n", pGD->modeIdent); pGD->winSizeX = res_mode->xres; pGD->winSizeY = res_mode->yres; pGD->plnSizeX = res_mode->xres; pGD->plnSizeY = res_mode->yres; switch (bits_per_pixel) { case 8: pGD->gdfBytesPP = 1; pGD->gdfIndex = GDF__8BIT_INDEX; break; case 15: pGD->gdfBytesPP = 2; pGD->gdfIndex = GDF_15BIT_555RGB; break; case 16: pGD->gdfBytesPP = 2; pGD->gdfIndex = GDF_16BIT_565RGB; break; case 24: pGD->gdfBytesPP = 3; pGD->gdfIndex = GDF_24BIT_888RGB; break; case 32: pGD->gdfBytesPP = 4; pGD->gdfIndex = GDF_32BIT_X888RGB; break; } #if 0 /* statically configure settings */ pGD->winSizeX = pGD->plnSizeX = 240; pGD->winSizeY = pGD->plnSizeY = 320; pGD->gdfBytesPP = 2; pGD->gdfIndex = GDF_16BIT_565RGB; #endif pGD->frameAdrs = LCD_VIDEO_ADDR; pGD->memSize = VIDEO_MEM_SIZE; /* Clear video memory */ memset((void *)pGD->frameAdrs, 0x00, pGD->memSize); board_video_init(pGD); t1 = res_mode->pixclock; t1 /= 1000; t1 = 1000000000L / t1; clkval = (CONFIG_SYS_VIDEO_VCLOCK_HZ / t1) - 1; /* 配置视频输出格式和显示使能/禁止。*/ fb->VIDCON0 = ( S3C_VIDCON0_VIDOUT_RGB | S3C_VIDCON0_PNRMODE_RGB_P | S3C_VIDCON0_CLKVALUP_ALWAYS | S3C_VIDCON0_CLKVAL_F(clkval)| S3C_VIDCON0_VCLKEN_NORMAL | S3C_VIDCON0_CLKDIR_DIVIDED| S3C_VIDCON0_CLKSEL_HCLK ); /* RGB I/F控制信号。*/ fb->VIDCON1 = ( S3C_VIDCON1_IVSYNC_INVERT | S3C_VIDCON1_IHSYNC_INVERT); /* 配置视频输出时序和显示尺寸。*/ fb->VIDTCON0 = ( S3C_VIDTCON0_VBPD(res_mode->upper_margin) | S3C_VIDTCON0_VFPD(res_mode->lower_margin) | S3C_VIDTCON0_VSPW(res_mode->vsync_len)); fb->VIDTCON1 = ( S3C_VIDTCON1_HBPD(res_mode->left_margin) | S3C_VIDTCON1_HFPD(res_mode->right_margin) | S3C_VIDTCON1_HSPW(res_mode->hsync_len)); fb->VIDTCON2 = ( S3C_VIDTCON2_LINEVAL(pGD->winSizeY - 1) | S3C_VIDTCON2_HOZVAL(pGD->winSizeX - 1)); #if defined(LCD_VIDEO_BACKGROUND) fb->WINCON0 = (S3C_WINCON_BPPMODE_16BPP_565 | S3C_WINCON_ENWIN_ENABLE | S3C_WINCON_HAWSWP_ENABLE); fb->VIDOSD0A = ( S3C_VIDOSD_LEFT_X(0) | S3C_VIDOSD_TOP_Y(0)); fb->VIDOSD0B = ( S3C_VIDOSD_RIGHT_X(pGD->winSizeX - 1) | S3C_VIDOSD_BOTTOM_Y(pGD->winSizeY - 1)); /* 指定视频窗口0的大小控制寄存器。*/ fb->VIDOSD0C = S3C_VIDOSD_SIZE(pGD->winSizeY * pGD->winSizeX); #endif /* 窗口格式设置 */ fb->WINCON1 = (S3C_WINCON_BPPMODE_16BPP_565 | S3C_WINCON_ENWIN_ENABLE | S3C_WINCON_HAWSWP_ENABLE); /* 指定OSD图像的左上角像素的横向屏幕坐标。*/ fb->VIDOSD1A = ( S3C_VIDOSD_LEFT_X(0) | S3C_VIDOSD_TOP_Y(0)); /* 指定横屏右下角的OSD图像的像素坐标。*/ fb->VIDOSD1B = ( S3C_VIDOSD_RIGHT_X(pGD->winSizeX - 1) | S3C_VIDOSD_BOTTOM_Y(pGD->winSizeY - 1)); #if defined(LCD_VIDEO_BACKGROUND) fb->VIDOSD1C = ( S3C_VIDOSD_ALPHA0_R(LCD_VIDEO_BACKGROUND_ALPHA) | S3C_VIDOSD_ALPHA0_G(LCD_VIDEO_BACKGROUND_ALPHA) | S3C_VIDOSD_ALPHA0_B(LCD_VIDEO_BACKGROUND_ALPHA) ); #endif /* 指定视频窗口1的大小控制寄存器。*/ fb->VIDOSD1D = S3C_VIDOSD_SIZE(pGD->winSizeY * pGD->winSizeX); fb->SHADOWCON = S3C_WINSHMAP_CH_ENABLE(1); //Enables Channel 1 #if defined(LCD_VIDEO_BACKGROUND) /* config Display framebuffer addr for background*/ /* 指定窗口0的缓冲区起始地址寄存器,缓冲器0。*/ fb->VIDW00ADD0B0 = LCD_VIDEO_BACKGROUND_ADDR; /* This marks the end of the frame buffer. */ /* 指定窗口0的缓冲区,缓冲区结束地址寄存器0。*/ fb->VIDW00ADD1B0 = (S3C_VIDW00ADD0B0 &0xffffffff) + (pGD->winSizeX+0) * pGD->winSizeY * (pGD->gdfBytesPP); /* 指定窗口0的缓冲区大小寄存器。*/ fb->VIDW00ADD2= ((pGD->winSizeX * pGD->gdfBytesPP) & 0x1fff); #endif /* config Display framebuffer addr for console*/ fb->VIDW01ADD0B0 = pGD->frameAdrs; /* This marks the end of the frame buffer. */ fb->VIDW01ADD1B0 = (S3C_VIDW01ADD0B0 &0xffffffff) + (pGD->winSizeX+0) * pGD->winSizeY * (pGD->gdfBytesPP); fb->VIDW01ADD2= ((pGD->winSizeX * pGD->gdfBytesPP) & 0x1fff); /* Enable Display */ fb->VIDCON0 |= (S3C_VIDCON0_ENVID_ENABLE | S3C_VIDCON0_ENVID_F_ENABLE); /* ENVID = 1 ENVID_F = 1*/ fb->TRIGCON = 3;//(TRGMODE_I80 | SWTRGCMD_I80);TRIGCON = 3 /* Enable Display */ //VIDCON0 |= (VIDCON0_ENVID_ENABLE | VIDCON0_ENVID_F_ENABLE); /* ENVID = 1 ENVID_F = 1*/ //TRIGCON = (TRGMODE_I80 | SWTRGCMD_I80); //TRIGCON = 3 printf("Video: video_hw_init complete \n"); return ((void*)&smi); }
int s3cfb_init_registers(s3cfb_info_t *fbi) { struct clk *lcd_clock; struct fb_var_screeninfo *var = &fbi->fb.var; unsigned long flags = 0, page_width = 0, offset = 0; unsigned long video_phy_temp_f1 = fbi->screen_dma_f1; unsigned long video_phy_temp_f2 = fbi->screen_dma_f2; int win_num = fbi->win_id; local_irq_save(flags); page_width = var->xres * s3cfb_fimd.bytes_per_pixel; offset = (var->xres_virtual - var->xres) * s3cfb_fimd.bytes_per_pixel; if (win_num == 0) { #if defined(CONFIG_MACH_VOLANS) s3cfb_fimd.vidcon0 = s3cfb_fimd.vidcon0 | (S3C_VIDCON0_ENVID_ENABLE | S3C_VIDCON0_ENVID_F_ENABLE); #else s3cfb_fimd.vidcon0 = s3cfb_fimd.vidcon0 & ~(S3C_VIDCON0_ENVID_ENABLE | S3C_VIDCON0_ENVID_F_ENABLE); #endif writel(s3cfb_fimd.vidcon0, S3C_VIDCON0); lcd_clock = clk_get(NULL, "lcd"); s3cfb_fimd.vidcon0 |= S3C_VIDCON0_CLKVAL_F((int) ((clk_get_rate(lcd_clock) / s3cfb_fimd.pixclock) - 1)); #if defined(CONFIG_FB_S3C_VIRTUAL_SCREEN) offset = 0; s3cfb_fimd.vidw00add0b0 = video_phy_temp_f1; s3cfb_fimd.vidw00add0b1 = video_phy_temp_f2; s3cfb_fimd.vidw00add1b0 = S3C_VIDWxxADD1_VBASEL_F((unsigned long) video_phy_temp_f1 + (page_width + offset) * (var->yres)); s3cfb_fimd.vidw00add1b1 = S3C_VIDWxxADD1_VBASEL_F((unsigned long) video_phy_temp_f2 + (page_width + offset) * (var->yres)); #endif } writel(video_phy_temp_f1, S3C_VIDW00ADD0B0 + (0x08 * win_num)); writel(S3C_VIDWxxADD1_VBASEL_F((unsigned long) video_phy_temp_f1 + (page_width + offset) * (var->yres)), S3C_VIDW00ADD1B0 + (0x08 * win_num)); writel(S3C_VIDWxxADD2_OFFSIZE_F(offset) | (S3C_VIDWxxADD2_PAGEWIDTH_F(page_width)), S3C_VIDW00ADD2 + (0x04 * win_num)); if (win_num < 2) { writel(video_phy_temp_f2, S3C_VIDW00ADD0B1 + (0x08 * win_num)); writel(S3C_VIDWxxADD1_VBASEL_F((unsigned long) video_phy_temp_f2 + (page_width + offset) * (var->yres)), S3C_VIDW00ADD1B1 + (0x08 * win_num)); } switch (win_num) { case 0: writel(s3cfb_fimd.wincon0, S3C_WINCON0); writel(s3cfb_fimd.vidcon0, S3C_VIDCON0); writel(s3cfb_fimd.vidcon1, S3C_VIDCON1); writel(s3cfb_fimd.vidtcon0, S3C_VIDTCON0); writel(s3cfb_fimd.vidtcon1, S3C_VIDTCON1); writel(s3cfb_fimd.vidtcon2, S3C_VIDTCON2); writel(s3cfb_fimd.dithmode, S3C_DITHMODE); writel(s3cfb_fimd.vidintcon0, S3C_VIDINTCON0); writel(s3cfb_fimd.vidintcon1, S3C_VIDINTCON1); writel(s3cfb_fimd.vidosd0a, S3C_VIDOSD0A); writel(s3cfb_fimd.vidosd0b, S3C_VIDOSD0B); writel(s3cfb_fimd.vidosd0c, S3C_VIDOSD0C); writel(s3cfb_fimd.wpalcon, S3C_WPALCON); if(FB_WIN_ID == 0) s3cfb_onoff_win(fbi, ON); else s3cfb_onoff_win(fbi, OFF); break; case 1: writel(s3cfb_fimd.wincon1, S3C_WINCON1); writel(s3cfb_fimd.vidosd1a, S3C_VIDOSD1A); writel(s3cfb_fimd.vidosd1b, S3C_VIDOSD1B); writel(s3cfb_fimd.vidosd1c, S3C_VIDOSD1C); writel(s3cfb_fimd.vidosd1d, S3C_VIDOSD1D); writel(s3cfb_fimd.wpalcon, S3C_WPALCON); if(FB_WIN_ID == 1) s3cfb_onoff_win(fbi, ON); else s3cfb_onoff_win(fbi, OFF); break; case 2: writel(s3cfb_fimd.wincon2, S3C_WINCON2); writel(s3cfb_fimd.vidosd2a, S3C_VIDOSD2A); writel(s3cfb_fimd.vidosd2b, S3C_VIDOSD2B); writel(s3cfb_fimd.vidosd2c, S3C_VIDOSD2C); writel(s3cfb_fimd.vidosd2d, S3C_VIDOSD2D); writel(s3cfb_fimd.wpalcon, S3C_WPALCON); if(FB_WIN_ID == 2) s3cfb_onoff_win(fbi, ON); else s3cfb_onoff_win(fbi, OFF); break; case 3: writel(s3cfb_fimd.wincon3, S3C_WINCON3); writel(s3cfb_fimd.vidosd3a, S3C_VIDOSD3A); writel(s3cfb_fimd.vidosd3b, S3C_VIDOSD3B); writel(s3cfb_fimd.vidosd3c, S3C_VIDOSD3C); writel(s3cfb_fimd.wpalcon, S3C_WPALCON); if(FB_WIN_ID == 3) s3cfb_onoff_win(fbi, ON); else s3cfb_onoff_win(fbi, OFF); break; case 4: writel(s3cfb_fimd.wincon4, S3C_WINCON4); writel(s3cfb_fimd.vidosd4a, S3C_VIDOSD4A); writel(s3cfb_fimd.vidosd4b, S3C_VIDOSD4B); writel(s3cfb_fimd.vidosd4c, S3C_VIDOSD4C); writel(s3cfb_fimd.wpalcon, S3C_WPALCON); if(FB_WIN_ID == 4) s3cfb_onoff_win(fbi, ON); else s3cfb_onoff_win(fbi, OFF); break; } local_irq_restore(flags); return 0; }
int s3cfb_set_clock(struct s3cfb_global *ctrl) { struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev); u32 cfg, maxclk, src_clk, vclk, div; /* spec is under 100MHz */ maxclk = 100 * 1000000; cfg = readl(ctrl->regs + S3C_VIDCON0); if (pdata->hw_ver == 0x70) { cfg &= ~(S3C_VIDCON0_CLKVALUP_MASK | S3C_VIDCON0_VCLKEN_MASK); cfg |= (S3C_VIDCON0_CLKVALUP_ALWAYS | S3C_VIDCON0_VCLKEN_FREERUN); src_clk = clk_get_rate(ctrl->clock); printk(KERN_DEBUG "FIMD src sclk = %d\n", src_clk); } else { cfg &= ~(S3C_VIDCON0_CLKSEL_MASK | S3C_VIDCON0_CLKVALUP_MASK | S3C_VIDCON0_VCLKEN_MASK | S3C_VIDCON0_CLKDIR_MASK); cfg |= (S3C_VIDCON0_CLKVALUP_ALWAYS | S3C_VIDCON0_VCLKEN_NORMAL | S3C_VIDCON0_CLKDIR_DIVIDED); if (strcmp(pdata->clk_name, "sclk_fimd") == 0) { cfg |= S3C_VIDCON0_CLKSEL_SCLK; src_clk = clk_get_rate(ctrl->clock); printk(KERN_DEBUG "FIMD src sclk = %d\n", src_clk); } else { cfg |= S3C_VIDCON0_CLKSEL_HCLK; src_clk = ctrl->clock->parent->rate; printk(KERN_DEBUG "FIMD src hclk = %d\n", src_clk); } } vclk = PICOS2KHZ(ctrl->fb[pdata->default_win]->var.pixclock) * 1000; if (vclk > maxclk) { dev_info(ctrl->dev, "vclk(%d) should be smaller than %d\n", vclk, maxclk); /* vclk = maxclk; */ } div = DIV_ROUND_CLOSEST(src_clk, vclk); if (div == 0) { dev_err(ctrl->dev, "div(%d) should be non-zero\n", div); div = 1; } if ((src_clk/div) > maxclk) dev_info(ctrl->dev, "vclk(%d) should be smaller than %d Hz\n", src_clk/div, maxclk); cfg &= ~S3C_VIDCON0_CLKVAL_F(0xff); cfg |= S3C_VIDCON0_CLKVAL_F(div - 1); writel(cfg, ctrl->regs + S3C_VIDCON0); dev_info(ctrl->dev, "parent clock: %d, vclk: %d, vclk div: %d\n", src_clk, vclk, div); return 0; }
void lcd_ctrl_init_70(void *lcdbase) { ulong freq_lcdclk; ulong freq_Hclk; ulong fb_size; unsigned char nn; unsigned short *pp; int i; GPICON_REG = 0xaaaaaaaa; GPIPUD_REG = 0xaaaaaaaa; GPJCON_REG = 0xaaaaaaaa; GPJPUD_REG = 0xaaaaaaaa; lcd_disable(); S3C_WINCON0 &= (~(S3C_WINCONx_ENWIN_F_ENABLE)); MIFPCON_REG &= (~SEL_BYPASS_MASK); SPCON_REG &= (~LCD_SEL_MASK); SPCON_REG |= (RGB_IF_STYLE_MASK); freq_lcdclk = S3CFB_PIXEL_CLOCK; freq_Hclk = get_HCLK(); nn = (unsigned char)(freq_Hclk / freq_lcdclk) - 1; if(freq_lcdclk < freq_Hclk/2) { S3C_VIDCON0 = S3C_VIDCON0_INTERLACE_F_PROGRESSIVE + S3C_VIDCON0_VIDOUT_RGB_IF + \ S3C_VIDCON0_PNRMODE_RGB_P + S3C_VIDCON0_CLKVALUP_ST_FRM + S3C_VIDCON0_CLKVAL_F(nn) + \ S3C_VIDCON0_CLKDIR_DIVIDED + S3C_VIDCON0_CLKSEL_F_HCLK; }else { S3C_VIDCON0 = S3C_VIDCON0_INTERLACE_F_PROGRESSIVE + S3C_VIDCON0_VIDOUT_RGB_IF + \ S3C_VIDCON0_PNRMODE_RGB_P + S3C_VIDCON0_CLKVALUP_ST_FRM + S3C_VIDCON0_CLKVAL_F(0) + \ S3C_VIDCON0_CLKDIR_DIRECTED + S3C_VIDCON0_CLKSEL_F_HCLK; } nn = 0; if(S3CFB_IVCLK) { nn += S3C_VIDCON1_IVCLK_RISE_EDGE; } if(S3CFB_IHSYNC) { nn += S3C_VIDCON1_IHSYNC_INVERT; } if(S3CFB_IVSYNC) { nn += S3C_VIDCON1_IVSYNC_INVERT; } if(S3CFB_IVDEN) { nn += S3C_VIDCON1_IVDEN_INVERT; } S3C_VIDCON1 = (unsigned int)nn; S3C_VIDCON2 = 0; S3C_VIDTCON0 = S3C_VIDTCON0_VBPD(S3CFB_VBP - 1) | S3C_VIDTCON0_VFPD(S3CFB_VFP - 1) | S3C_VIDTCON0_VSPW(S3CFB_VSW - 1); S3C_VIDTCON1 = S3C_VIDTCON1_HBPD(S3CFB_HBP - 1) | S3C_VIDTCON1_HFPD(S3CFB_HFP -1) | S3C_VIDTCON1_HSPW(S3CFB_HSW - 1); S3C_VIDTCON2 = S3C_VIDTCON2_LINEVAL(S3CFB_VRES - 1) | S3C_VIDTCON2_HOZVAL(S3CFB_HRES - 1); #if LCD_BPP == LCD_COLOR32 S3C_WINCON0 = S3C_WINCONx_BPPMODE_F_24BPP_888; S3C_WINCON1 = S3C_WINCONx_BPPMODE_F_24BPP_888 | S3C_WINCONx_BLD_PIX_PIXEL; #else S3C_WINCON0 = S3C_WINCONx_BPPMODE_F_16BPP_565 | S3C_WINCONx_HAWSWP_ENABLE; S3C_WINCON1 = S3C_WINCONx_BPPMODE_F_16BPP_565 | S3C_WINCONx_HAWSWP_ENABLE | S3C_WINCONx_BLD_PIX_PIXEL; #endif S3C_WINCON2 = 0; S3C_WINCON3 = 0; S3C_WINCON4 = 0; S3C_VIDOSD0A = S3C_VIDOSDxA_OSD_LTX_F(0) + S3C_VIDOSDxA_OSD_LTY_F(0); S3C_VIDOSD0B = S3C_VIDOSDxB_OSD_RBX_F(S3CFB_HRES - 1) | S3C_VIDOSDxB_OSD_RBY_F(S3CFB_VRES - 1); S3C_VIDOSD0C = S3C_VIDOSD0C_OSDSIZE(S3CFB_HRES*S3CFB_VRES); S3C_VIDOSD1A = S3C_VIDOSDxA_OSD_LTX_F(0) + S3C_VIDOSDxA_OSD_LTY_F(0); S3C_VIDOSD1B = S3C_VIDOSDxB_OSD_RBX_F(S3CFB_HRES - 1) | S3C_VIDOSDxB_OSD_RBY_F(S3CFB_VRES - 1); S3C_VIDOSD1C = 0xDDD000;/*alpha blending*/ S3C_VIDOSD1D = S3C_VIDOSD0C_OSDSIZE(S3CFB_HRES*S3CFB_VRES); S3C_VIDOSD2A = 0; S3C_VIDOSD2B = 0; S3C_VIDOSD2C = 0; S3C_VIDOSD2D = 0; S3C_VIDOSD3A = 0; S3C_VIDOSD3B = 0; S3C_VIDOSD3C = 0; S3C_VIDOSD4A = 0; S3C_VIDOSD4B = 0; S3C_VIDOSD4C = 0; fb_size = calc_fbsize(); S3C_VIDW00ADD0B0 = virt_to_phys(lcdbase); S3C_VIDW00ADD0B1 = 0; S3C_VIDW01ADD0B0 = virt_to_phys(osd_frame_buffer); S3C_VIDW01ADD0B1 = 0; S3C_VIDW02ADD0 = 0; S3C_VIDW03ADD0 = 0; S3C_VIDW04ADD0 = 0; S3C_VIDW00ADD1B0 = virt_to_phys((unsigned int)(lcdbase) + fb_size); S3C_VIDW00ADD1B1 = 0; S3C_VIDW01ADD1B0 = virt_to_phys(osd_frame_buffer) + fb_size; S3C_VIDW01ADD1B1 = 0; S3C_VIDW02ADD1 = 0; S3C_VIDW03ADD1 = 0; S3C_VIDW04ADD1 = 0; S3C_VIDW00ADD2 = 0;//S3C_VIDWxxADD2_OFFSIZE_F(0) | (S3C_VIDWxxADD2_PAGEWIDTH_F(panel_info.vl_col*panel_info.vl_bpix/8)); S3C_VIDW01ADD2 = 0;//S3C_VIDWxxADD2_OFFSIZE_F(0) | (S3C_VIDWxxADD2_PAGEWIDTH_F(panel_info.vl_col*panel_info.vl_bpix/8)); S3C_VIDW02ADD2 = 0; S3C_VIDW03ADD2 = 0; S3C_VIDW04ADD2 = 0; S3C_W1KEYCON0 = S3C_WxKEYCON0_KEYBLEN_ENABLE | S3C_WxKEYCON0_KEYEN_F_ENABLE | S3C_WxKEYCON0_COMPKEY(0xFFFF); S3C_W1KEYCON1 = 0x00000000;/*color key*/ #if 1 memset(lcdbase,0x00,fb_size*2); #else pp = lcdbase; for(i=0;i< S3CFB_HRES * S3CFB_VRES;i++) { *pp = 0xf100; pp++; } #endif lcd_enable(); S3C_WINCON0 |= S3C_WINCONx_ENWIN_F_ENABLE; S3C_WINCON1 |= S3C_WINCONx_ENWIN_F_ENABLE; return (0); }