S3C2440上LCD驱动(FrameBuffer)实例开发讲解(二)
分成红、绿、蓝三基色)*/
fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
break;
case 1:/*1BPP时,设置为黑白色(分黑、白两种色,FB_VISUAL_MONO01代表黑,FB_VISUAL_MONO10代表白)*/
fbinfo->fix.visual = FB_VISUAL_MONO01;
break;
default:/*默认设置为伪彩色,采用索引颜色显示*/
fbinfo->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
}
/*设置fb_info中固定参数中一行的字节数,公式:1行字节数=(1行像素个数*每像素位数BPP)/8 */
fbinfo->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
/*修改以上参数后,重新激活fb_info中的参数配置(即:使修改后的参数在硬件上生效)*/
my2440fb_activate_var(fbinfo);
return 0;
}
/*重新激活fb_info中的参数配置*/
static void my2440fb_activate_var(struct fb_info *fbinfo)
{
/*获得结构体变量*/
struct my2440fb_var *fbvar = fbinfo->par;
void __iomem *regs = fbvar->lcd_base;
/*获得fb_info可变参数*/
struct fb_var_screeninfo *var = &fbinfo->var;
/*计算LCD控制寄存器1中的CLKVAL值, 根据数据手册中该寄存器的描述,计算公式如下:
* STN屏:VCLK = HCLK / (CLKVAL * 2), CLKVAL要求>= 2
* TFT屏:VCLK = HCLK / [(CLKVAL + 1) * 2], CLKVAL要求>= 0*/
int clkdiv = my2440fb_calc_pixclk(fbvar, var->pixclock) / 2;
/*获得屏幕的类型*/
int type = fbvar->regs.lcdcon1 & S3C2410_LCDCON1_TFT;
if (type == S3C2410_LCDCON1_TFT)
{
/*根据数据手册按照TFT屏的要求配置LCD控制寄存器1-5*/
my2440fb_config_tft_lcd_regs(fbinfo, &fbvar->regs);
--clkdiv;
if (clkdiv < 0)
{
clkdiv = 0;
}
}
else
{
/*根据数据手册按照STN屏的要求配置LCD控制寄存器1-5*/
my2440fb_config_stn_lcd_regs(fbinfo, &fbvar->regs);
if (clkdiv < 2)
{
clkdiv = 2;
}
}
/*设置计算的LCD控制寄存器1中的CLKVAL值*/
fbvar->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv);
/*将各参数值写入LCD控制寄存器1-5中*/
writel(fbvar->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID, regs + S3C2410_LCDCON1);
writel(fbvar->regs.lcdcon2, regs + S3C2410_LCDCON2);
writel(fbvar->regs.lcdcon3, regs + S3C2410_LCDCON3);
writel(fbvar->regs.lcdcon4, regs + S3C2410_LCDCON4);
writel(fbvar->regs.lcdcon5, regs + S3C2410_LCDCON5);
/*配置帧缓冲起始地址寄存器1-3*/
my2440fb_set_lcdaddr(fbinfo);
fbvar->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID,
writel(fbvar->regs.lcdcon1, regs + S3C2410_LCDCON1);
}
/*计算LCD控制寄存器1中的CLKVAL值*/
static unsigned int my2440fb_calc_pixclk(struct my2440fb_var *fbvar, unsigned long pixclk)
{
/*获得LCD的时钟*/
unsigned long clk = clk_get_rate(fbvar->lcd_clock);
/* 像素时钟单位是皮秒,而时钟的单位是赫兹,所以计算公式为:
* Hz -> picoseconds is / 10^-12
*/
unsigned long long div = (unsigned long long)clk * pixclk;
div >>= 12;/* div / 2^12 */
do_div(div, 625 * 625UL * 625); /* div / 5^12, do_div宏定义在asm/div64.h中*/
return div;
}
/*根据数据手册按照TFT屏的要求配置LCD控制寄存器1-5*/
static void my2440fb_config_tft_lcd_regs(const struct fb_info *fbinfo, struct s3c2410fb_hw *regs)
{
const struct my2440fb_var *fbvar = fbinfo->par;
const struct fb_var_screeninfo *var = &fbinfo->var;
/*根据色位模式设置LCD控制寄存器1和5,参考数据手册*/
switch (var->bits_per_pixel)
{
case 1:/*1BPP*/
regs->lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
break;
case 2:/*2BPP*/
regs->lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
break;
case 4:/*4BPP*/
regs->lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
break;
case 8:/*8BPP*/
regs->lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
regs->lcdcon5 |= S3C2410_LCDCON5_BSWP | S3C2410_LCDCON5_FRM565;
regs->lcdcon5 &= ~S3C2410_LCDCON5_HWSWP;
break;
case 16:/*16BPP*/
regs->lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
regs->lcdcon5 &= ~S3C2410_LCDCON5_BSWP;
regs->lcdcon5 |= S3C2410_LCDCON5_HWSWP;
break;
case 32:/*32BPP*/
regs->lc
- 嵌入式Web服务器移植与测试(03-03)
- 基于S3C2440的嵌入式IPv6防火墙设计(09-02)
- 基于OpenWrt的移动机器人系统设计(01-17)
- 基于S3C2440处理器Linux平台的物流配送系统设计(02-05)
- 基于嵌入式的杯突试验机测控系统设计与实现(02-12)
- 基于ARM的多路同步的A/D和D/A设计(06-29)