Exemple #1
0
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;
}
Exemple #2
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;
}
Exemple #4
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;	
}
Exemple #5
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);
}
Exemple #7
0
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;
}
Exemple #9
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);
}