S3C2440上LCD驱动(FrameBuffer)实例开发讲解(二)
= 1;
}
}
}
/*LCD各寄存器进行初始化*/
static int my2440fb_init_registers(struct fb_info *fbinfo)
{
unsigned long flags;
void __iomem *tpal;
void __iomem *lpcsel;
/*从lcd_fb_probe探测函数设置的私有变量结构体中再获得LCD相关信息的数据*/
struct my2440fb_var *fbvar = fbinfo->par;
struct s3c2410fb_mach_info *mach_info = fbvar->dev->platform_data;
/*获得临时调色板寄存器基地址,S3C2410_TPAL宏定义在mach-s3c2410/include/mach/regs-lcd.h中。
注意对于lpcsel这是一个针对三星TFT屏的一个专用寄存器,如果用的不是三星的TFT屏应该不用管它。*/
tpal = fbvar->lcd_base + S3C2410_TPAL;
lpcsel = fbvar->lcd_base + S3C2410_LPCSEL;
/*在修改下面寄存器值之前先屏蔽中断,将中断状态保存到flags中*/
local_irq_save(flags);
/*这里就是在上一篇章中讲到的把IO端口C和D配置成LCD模式*/
modify_gpio(S3C2410_GPCUP, mach_info->gpcup, mach_info->gpcup_mask);
modify_gpio(S3C2410_GPCCON, mach_info->gpccon, mach_info->gpccon_mask);
modify_gpio(S3C2410_GPDUP, mach_info->gpdup, mach_info->gpdup_mask);
modify_gpio(S3C2410_GPDCON, mach_info->gpdcon, mach_info->gpdcon_mask);
/*恢复被屏蔽的中断*/
local_irq_restore(flags);
writel(0x00, tpal);/*临时调色板寄存器使能禁止*/
writel(mach_info->lpcsel, lpcsel);/*在上一篇中讲到过,它是三星TFT屏的一个寄存器,这里可以不管*/
return 0;
}
/*该函数实现修改GPIO端口的值,注意第三个参数mask的作用是将要设置的寄存器值先清零*/
static inline void modify_gpio(void __iomem *reg, unsigned long set, unsigned long mask)
{
unsigned long tmp;
tmp = readl(reg) & ~mask;
writel(tmp | set, reg);
}
/*检查fb_info中的可变参数*/
static int my2440fb_check_var(struct fb_info *fbinfo)
{
unsigned i;
/*从lcd_fb_probe探测函数设置的平台数据中再获得LCD相关信息的数据*/
struct fb_var_screeninfo *var = &fbinfo->var;/*fb_info中的可变参数*/
struct my2440fb_var *fbvar = fbinfo->par;/*在lcd_fb_probe探测函数中设置的私有结构体数据*/
struct s3c2410fb_mach_info *mach_info = fbvar->dev->platform_data;/*LCD的配置结构体数据,这个配置结构体的赋值在上一篇章的"3. 帧缓冲设备作为平台设备"中*/
struct s3c2410fb_display *display = NULL;
struct s3c2410fb_display *default_display = mach_info->displays + mach_info->default_display;
int type = default_display->type;/*LCD的类型,看上一篇章的"3. 帧缓冲设备作为平台设备"中的type赋值是TFT类型*/
/*验证X/Y解析度*/
if (var->yres == default_display->yres &&
var->xres == default_display->xres &&
var->bits_per_pixel == default_display->bpp)
{
display = default_display;
}
else
{
for (i = 0; i < mach_info->num_displays; i++)
{
if (type == mach_info->displays[i].type &&
var->yres == mach_info->displays[i].yres &&
var->xres == mach_info->displays[i].xres &&
var->bits_per_pixel == mach_info->displays[i].bpp)
{
display = mach_info->displays + i;
break;
}
}
}
if (!display)
{
return -EINVAL;
}
/*配置LCD配置寄存器1中的5-6位(配置成TFT类型)和配置LCD配置寄存器5*/
fbvar->regs.lcdcon1 = display->type;
fbvar->regs.lcdcon5 = display->lcdcon5;
/* 设置屏幕的虚拟解析像素和高度宽度 */
var->xres_virtual = display->xres;
var->yres_virtual = display->yres;
var->height = display->height;
var->width = display->width;
/* 设置时钟像素,行、帧切换值,水平同步、垂直同步长度值 */
var->pixclock = display->pixclock;
var->left_margin = display->left_margin;
var->right_margin = display->right_margin;
var->upper_margin = display->upper_margin;
var->lower_margin = display->lower_margin;
var->vsync_len = display->vsync_len;
var->hsync_len = display->hsync_len;
- 嵌入式Web服务器移植与测试(03-03)
- 基于S3C2440的嵌入式IPv6防火墙设计(09-02)
- 基于OpenWrt的移动机器人系统设计(01-17)
- 基于S3C2440处理器Linux平台的物流配送系统设计(02-05)
- 基于嵌入式的杯突试验机测控系统设计与实现(02-12)
- 基于ARM的多路同步的A/D和D/A设计(06-29)