// HSPW: 一个HSYNC信号的时间宽度
fbinfo->var.left_margin = S3C2410_LCDCON3_GET_HFPD(mregs->lcdcon3) + 1;
fbinfo->var.right_margin = S3C2410_LCDCON3_GET_HBPD(mregs->lcdcon3) + 1;
fbinfo->var.hsync_len = S3C2410_LCDCON4_GET_HSPW(mregs->lcdcon4) + 1;
4.2.3 其他参数设置
fbinfo->fbops = &s3c2410fb_ops;
fbinfo->flags = FBINFO_FLAG_DEFAULT;
// 设置调色板
fbinfo->pseudo_palette = &info->pseudo_pal;
s3c2410fb_ops:
static struct fb_ops s3c2410fb_ops = {
.owner = THIS_MODULE,
.fb_check_var = s3c2410fb_check_var,
.fb_set_par = s3c2410fb_set_par,
.fb_blank = s3c2410fb_blank,
.fb_setcolreg = s3c2410fb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
4.2.4 硬件相关设置(相关寄存器和引脚)
/* Stop the video and unset ENVID if set */
// 设置LCD控制器的lcdcon1寄存器,第0位为0,先失能lcd等设置完其他参数后,需要开启LCD,再使能该位
info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID;
lcdcon1 = readl(S3C2410_LCDCON1);
writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
// 设置GPB0 低电平,即关闭LCD背光,后面需要开启背光
// add by thisway.diy@163.com, for eBlocks
s3c2410_gpio_setpin(S3C2410_GPB0, 0); // back light control
// 设置调色板数据
for (i = 0; i < 256; i++)
info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
if (!request_mem_region((unsigned long)S3C24XX_VA_LCD, SZ_1M, 's3c2410-lcd')) {
ret = -EBUSY;
goto dealloc_fb;
}
dprintk('got LCD regionn');
// 设置LCD中断
ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info);
if (ret) {
dev_err(&pdev->dev, 'cannot get irq %d - err %dn', irq, ret);
ret = -EBUSY;
goto release_mem;
}
// 使能LCD clk
info->clk = clk_get(NULL, 'lcd');
if (!info->clk || IS_ERR(info->clk)) {
printk(KERN_ERR 'failed to get lcd clock sourcen');
ret = -ENOENT;
goto release_irq;
}
clk_enable(info->clk);
dprintk('got and enabled clockn');
msleep(1);
/* Initialize video memory */
// 申请frame buff内存并初始化
ret = s3c2410fb_map_video_memory(info);
if (ret) {
printk( KERN_ERR 'Failed to allocate video RAM: %dn', ret);
ret = -ENOMEM;
goto release_clock;
}
dprintk('got video memoryn');
// 根据s3c2440芯片手册和使用的屏的规格书设置相关寄存器和引脚
ret = s3c2410fb_init_registers(info);
ret = s3c2410fb_check_var(&fbinfo->var, fbinfo);
static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
{
unsigned long flags;
/* Initialise LCD with values from haret */
local_irq_save(flags);
/* modify the gpio(s) with interrupts set (bjd) */
// 根据s3c2440芯片手册设置
// 设置GPC引脚上拉使能 mach_info->gpcup 0xffffffff
modify_gpio(S3C2410_GPCUP, mach_info->gpcup, mach_info->gpcup_mask);
// 设置GPC引脚为LCD功能 mach_info->gpccon 0xaaaaaaaa -> 1010 1010 1010 1010 1010 1010 1010 1010
modify_gpio(S3C2410_GPCCON, mach_info->gpccon, mach_info->gpccon_mask);
// 设置GPD引脚上拉使能 mach_info->gpdup 0xffffffff
modify_gpio(S3C2410_GPDUP, mach_info->gpdup, mach_info->gpdup_mask);
// 设置GPD引脚为LCD功能 mach_info->gpdcon 0xaaaaaaaa
modify_gpio(S3C2410_GPDCON, mach_info->gpdcon, mach_info->gpdcon_mask);
local_irq_restore(flags);
// 根据s3c2440芯片手册设置
// lcdcon1: S3C2410_LCDCON1_TFT16BPP | S3C2410_LCDCON1_TFT | S3C2410_LCDCON1_CLKVAL(0x04),
writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
// lcdcon2: S3C2410_LCDCON2_VBPD(1) | S3C2410_LCDCON2_LINEVAL(271) | S3C2410_LCDCON2_VFPD(1) | S3C2410_LCDCON2_VSPW(9)
writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);
// lcdcon3: S3C2410_LCDCON3_HBPD(1) | S3C2410_LCDCON3_HOZVAL(479) | S3C2410_LCDCON3_HFPD(1)
writel(fbi->regs.lcdcon3, S3C2410_LCDCON3);
// lcdcon4: S3C2410_LCDCON4_HSPW(40)
writel(fbi->regs.lcdcon4, S3C2410_LCDCON4);
// lcdcon5: S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_INVVLINE | S3C2410_LCDCON5_INVVFRAME | S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP,
writel(fbi->regs.lcdcon5, S3C2410_LCDCON5);
// 根据s3c2440芯片手册设置
// 设置地址相关寄存器 LCDSADDR1、LCDSADDR2、LCDSADDR3
s3c2410fb_set_lcdaddr(fbi);
dprintk('LPCSEL = 0x%08lxn', mach_info->lpcsel);
writel(mach_info->lpcsel, S3C2410_LPCSEL);
dprintk('replacing TPAL %08xn', readl(S3C2410_TPAL));
// 不使用调色板
/* ensure temporary palette disabled */
writel(0x00, S3C2410_TPAL);
#if 0
/* ghcstop modified */
s3c2410_gpio_cfgpin(S3C2410_GPC5, S3C2410_GPC5_OUTP); // lcd display enable/disable
s3c2410_gpio_cfgpin(S3C2410_GPB1, S3C2410_GPB1_OUTP); // back light control
s3c2410_gpio_cfgpin(S3C2410_GPH6, S3C2410_GPH6_OUTP);
s3c2410_gpio_pullup(S3C2410_GPC5, 0);
s3c2410_gpio_pullup(S3C2410_GPB1, 0);
s3c2410_gpio_pullup(S3C2410_GPH6, 0);
s3c2410_gpio_setpin(S3C2410_GPC5, 1);
s3c2410_gpio_setpin(S3C2410_GPH6, 1);
s3c2410_gpio_setpin(S3C2410_GPB1, 1);
#else
/* thisway.diy@163.com modify again, for eBlocks */
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP); // back light control
s3c2410_gpio_pullup(S3C2410_GPB0, 0);
s3c2410_gpio_setpin(S3C2410_GPB0, 1); // back light control, enable
#endif
/* probably not required */
msleep(10);
// 使能lcd
/* Enable video by setting the ENVID bit to 1 */
fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID;
writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
// add by thisway.diy@163.com, for eBlocks
// 开启背光
s3c2410_gpio_setpin(S3C2410_GPB0, 1); // back light control
return 0;
}
五,fbmem字符设备驱动
5.1 驱动加载并初始化
编译进内核,加载
linux-2.6.22.6/drivers/video/Makefile
fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o
modedb.o fbcvt.o
fb-objs := $(fb-y)
linux-2.6.22.6/drivers/video/fbmem.c
subsys_initcall(fbmem_init);
static int __init
fbmem_init(void)
{
create_proc_read_entry('fb', 0, NULL, fbmem_read_proc, NULL);
// 注册字符设备
if (register_chrdev(FB_MAJOR,'fb',&fb_fops))
printk('unable to get major %d for fb devsn', FB_MAJOR);
// 创建设备类 /sys/class/graphics
fb_class = class_create(THIS_MODULE, 'graphics');
if (IS_ERR(fb_class)) {
printk(KERN_WARNING 'Unable to create fb class; errno = %ldn', PTR_ERR(fb_class));
fb_class = NULL;
}
return 0;
}
5.2 register_framebuffer
int
register_framebuffer(struct fb_info *fb_info)
{
int i;
struct fb_event event;
struct fb_videomode mode;
// 最多支持32个fb设备
if (num_registered_fb == FB_MAX)
return -ENXIO;
num_registered_fb++;
// 从registered_fb中找到一项空的位置,存放本次fb。下标作为次设备号,创建设备节点,以供应用程序使用
for (i = 0 ; i < FB_MAX; i++)
if (!registered_fb[i])
break;
fb_info->node = i;
// 创建设备 节点。/dev/fb%d
fb_info->dev = device_create(fb_class, fb_info->device,
MKDEV(FB_MAJOR, i), 'fb%d', i);
if (IS_ERR(fb_info->dev)) {
/* Not fatal */
printk(KERN_WARNING 'Unable to create device for framebuffer %d; errno = %ldn', i, PTR_ERR(fb_info->dev));
fb_info->dev = NULL;
} else
fb_init_device(fb_info);
if (fb_info->pixmap.addr == NULL) {
fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
if (fb_info->pixmap.addr) {
fb_info->pixmap.size = FBPIXMAPSIZE;
fb_info->pixmap.buf_align = 1;
fb_info->pixmap.scan_align = 1;
fb_info->pixmap.access_align = 32;
fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
}
}
fb_info->pixmap.offset = 0;
if (!fb_info->pixmap.blit_x)
fb_info->pixmap.blit_x = ~(u32)0;
if (!fb_info->pixmap.blit_y)
fb_info->pixmap.blit_y = ~(u32)0;
if (!fb_info->modelist.prev || !fb_info->modelist.next)
INIT_LIST_HEAD(&fb_info->modelist);
fb_var_to_videomode(&mode, &fb_info->var);
fb_add_videomode(&mode, &fb_info->modelist);
registered_fb[i] = fb_info;
event.info = fb_info;
上一篇:s3c2440裸机-时钟编程-1-2440时钟体系介绍
下一篇:《Linux驱动:s3c2440 lcd 驱动分析》
- 热门资源推荐
- 热门放大器推荐
- LTC2263-12 演示板,12 位,25Msps,1.8V 双路串行 ADC,5MHz
- 用PIC单片机设计电子密码锁
- AM1G-2424DH30Z ±24V 1 瓦 DC-DC 转换器的典型应用
- 无线充电电动牙刷设计
- OP497FSZ平方放大器典型应用电路
- 基于LTC3453的LED闪光灯驱动器设计
- PAM2808 5W 大功率高亮度 LED 驱动器的典型应用
- 使用 Analog Devices 的 LTC1258CS8-5 的参考设计
- 基于ARM处理器的EtherCAT 通信开发平台 -原理图
- 适用于 ADP1741 2A 低 VIN、低压差线性稳压器的具有可调输出电压、0.75V 至 3.3V 的典型应用电路



非常经典的关于LLC的杨波博士论文
LM139AJ/883C

XC6406PP60DL






京公网安备 11010802033920号