Linux-2.6.38的LCD驱动分析(二)
二、s3cfb_probe函数分析
2.1 驱动的入口点
/* GPF15 = LCD backlight control
* GPF13 => Panel power
* GPN5 = LCD nRESET signal
* PWM_TOUT1 => backlight brightness
*/
static void mini6410_lcd_power_set(struct plat_lcd_data *pd,
unsigned int power)
{
if (power) {
gpio_direction_output(S3C64XX_GPF(13), 1);
gpio_direction_output(S3C64XX_GPF(15), 1);
/* fire nRESET on power up */
gpio_direction_output(S3C64XX_GPN(5), 0);
msleep(10);
gpio_direction_output(S3C64XX_GPN(5), 1);
msleep(1);
} else {
gpio_direction_output(S3C64XX_GPF(15), 0);
gpio_direction_output(S3C64XX_GPF(13), 0);
}
}
static struct plat_lcd_data mini6410_lcd_power_data = {
.set_power = mini6410_lcd_power_set,
};
static struct platform_device mini6410_lcd_powerdev = {
.name = "platform-lcd",
.dev.parent = &s3c_device_fb.dev,
.dev.platform_data= &mini6410_lcd_power_data,
};
&s3c_device_i2c0,
&s3c_device_nand,
&s3c_device_fb,
&s3c_device_ohci,
&s3c_device_usb_hsotg,
&samsung_asoc_dma,
&mini6410_lcd_powerdev,//向内核注册lcd device
......
/* Multimedia support */
#ifdef CONFIG_VIDEO_SAMSUNG
&s3c_device_vpp,
&s3c_device_mfc,
&s3c_device_tvenc,
&s3c_device_tvscaler,
&s3c_device_rotator,
&s3c_device_jpeg,
&s3c_device_fimc0,
&s3c_device_fimc1,
&s3c_device_g2d,
&s3c_device_g3d,
#endif
};
static struct platform_driver s3cfb_driver = {
.probe = s3cfb_probe,
.remove = s3cfb_remove,
.suspend = s3cfb_suspend,
.resume = s3cfb_resume,
.driver = {
.name = "s3c-fb",
.owner = THIS_MODULE,
},
};
{
struct resource *res; //描述LCD的硬件控制寄存器的结构体.
struct fb_info *fbinfo; //fb_info为内核提供的buffer驱动的接口数据结构, 每个帧缓冲驱动都对应一个这样的结构。s3cfb_probe的最终目的填充该结构,并向内核注册.
s3cfb_info_t *info; //该结构记录了s3cfb驱动的所有信息.
char driver_name[] = "s3cfb"; //驱动名称
int index = 0, ret, size;
//framebuffer_alloc可以在include/linux/fb.h文件中找到其原型:struct fb_info *framebuffer_alloc(size_t size, struct device *dev); 它的功能是向内核申请一段大小为sizeof(struct fb_info) + size的空间,其中size的大小代表设备的私有数据空间,并用fb_info的par域指向该私有空间。
fbinfo = framebuffer_alloc(sizeof(s3cfb_info_t), &pdev->dev);
if (!fbinfo)
return -ENOMEM;
//以下开始做正经事了,填充fbinfo了。
platform_set_drvdata(pdev, fbinfo);
info = fbinfo->par;
info->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "failed to get memory registers\n");
ret = -ENXIO;
goto dealloc_fb;
}
//申请内存
size = (res->end - res->start) + 1;
info->mem = request_mem_region(res->start, size, pdev->name);
if (info->mem == NULL) {
dev_err(&pdev->dev, "failed to get memory region\n");
ret = -ENOENT;
goto dealloc_fb;
}
//映射内存
info->io = ioremap(res->start, size);
if (info->io == NULL) {
dev_err(&pdev->dev, "ioremap() of registers failed\n");
ret = -ENXIO;
goto release_mem;
}
s3cfb_pre_init();
s3cfb_set_backlight_power(1);
s3cfb_set_lcd_power(1);
s3cfb_set_backlight_level(S3CFB_DEFAULT_BACKLIGHT_LEVEL);
//该函数得到时钟源,并与硬件紧密相连
info->clk = clk_get(NULL, "lcd");
if (!info->clk || IS_ERR(info->clk)) {
printk(KERN_INFO "failed to get lcd clock source\n");
ret = -ENOENT;
goto release_io;
}
//打开时钟
clk_enable(info->clk);
printk("S3C_LCD clock got enabled :: %ld.%03ld Mhz\n", PRINT_MHZ(clk_get_rate(info->clk)));
s3cfb_fimd.vsync_info.count = 0;
init_waitqueue_head(&s3cfb_fimd.vsync_info.wait_queue);
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res == NULL) {
dev_err(&pdev->dev, "failed to get irq\n");
ret = -ENXIO;
goto release_clock;
}
//向内核注册中断
ret = request_irq(res->start, s3cfb_irq, 0, "s3c-lcd", pdev);
if (ret != 0) {
printk("Failed to install irq (%d)\n", ret);
goto release_clock;
}
msleep(5);
for (index = 0; index < S3CFB_NUM; index++) {
s3cfb_info[index].mem = info->mem;
s3cfb_info[index].io = info->io;
s3cfb_info[index].clk = info->clk;
s3cfb_init_fbinfo(&s3cfb_info[index], driver_name, index);
/* Initialize video memory */
ret = s3cfb_map_video_memory(&s3cfb_info[index]);
if (ret) {
printk("Failed to allocate video RAM: %d\n", ret);
ret = -ENOMEM;
goto release_irq;
}
ret = s3cfb_init_registers(&s3cfb_info[index]);
ret = s3cfb_check_var(&s3cfb_info[index].fb.var, &s3cfb_info[index].fb);
if (index < 2){
if (fb_alloc_cmap(&s3cfb_info[index].fb.cmap, 256, 0) < 0)
goto dealloc_fb;
} else {
if (fb_alloc_cmap(&s3cfb_info[index].fb.cmap, 16, 0) < 0)
goto dealloc_fb;
}
//神圣的时刻终于到来,向内核正式注册。
ret = register_framebuffer(&s3cfb_info[index].fb);
if (ret < 0) {
printk(KERN_ERR "Failed to register framebuffer device: %d\n", ret);
goto free_video_memory;
}
printk(KERN_INFO "fb%d: %s frame buffer device\n", s3cfb_info[index].fb.node, s3cfb_info[index].fb.fix.id);
}
/* create device files */
ret = device_create_file(&(pdev->dev), &dev_attr_backlight_power);
if (ret < 0)
printk(KERN_WARNING "s3cfb: failed to add entries\n");
ret = device_create_file(&(pdev->dev), &dev_attr_backlight_level);
if (ret < 0)
printk(KERN_WARNING "s3cfb: failed to add entries\n");
ret = device_create_file(&(pdev->dev), &dev_attr_lcd_power);
if (ret < 0)
printk(KERN_WARNING "s3cfb: failed to add entries\n");
return 0;
//错误处理返回
free_video_memory:
s3cfb_unmap_video_memory(&s3cfb_info[index]);
release_irq:
free_irq(res->start, &info);
release_clock:
clk_disable(info->clk);
clk_put(info->clk);
release_io:
iounmap(info->io);
release_mem:
release_resource(info->mem);
kfree(info->mem);
dealloc_fb:
framebuffer_release(fbinfo);
return ret;
}
Linux-2.6.38的LCD驱动分析(二)相关推荐
- 《Linux驱动:s3c2440 lcd 驱动分析》
文章目录 一,前言 二,LCD原理和硬件分析 2.1 LCD原理解析 2.2 硬件电路 2.2.1 LCD背光电路 2.2.2 LCD屏 2.2.3 S3c2440主控 三,LCD应用平台总线-设备- ...
- LCD驱动分析(一)
LCD驱动分析 转载自http://blog.chinaunix.net/uid-26021340-id-3011787.html S3C2440上LCD驱动 (FrameBuffer)实例开发讲解 ...
- Linux环境下使用 USB转串口驱动(二)
minicom是linux下串口通信的软件,它的使用完全依靠键盘的操作,虽然没有"超级终端"那么易用,但是使用习惯之后读者将会体会到它的高效与便利,下面将讲解minicom的安装和 ...
- LCD驱动分析【转】
转自:http://blog.csdn.net/hanmengaidudu/article/details/21559153 1.S3C2440上LCD驱动 (FrameBuffer)实例开发讲解 其 ...
- lcd驱动分析(读书笔记)
1.S3C2440上LCD驱动 (FrameBuffer)实例开发讲解 其中的代码也可直接参考:drivers/video/s3c2410fb.c 以下为转载文章,文章原地址:http://blog. ...
- Linux-2.6.20的LCD驱动分析(二)
.1 驱动的入口点 摆在面前的第一个问题相信应该是,这个函数是从那里开始运行的.这里就应该从long long ago 开始了,打开drivers/video/s3c2410fb.c文件,然后找到s3 ...
- linux2.6的LCD驱动分析
原文出自http://www.cnblogs.com/armlinux/archive/2010/07/28/2396954.html 一.让LCD显示可爱的小企鹅 还是先说说环境吧,处理器为S3C2 ...
- Linux-2.6.20的LCD驱动分析
一.让LCD显示可爱的小企鹅 还是先说说环境吧,处理器为S3C2410,linux的版本当然是2.6.20的.下面先说说怎样让LCD上显示出可爱的小企鹅.最直接的步骤如下(记住不要问为什么哈-_-,一 ...
- 高通 android平台LCD驱动分析
目前手机芯片厂家提供的源码里包含整个LCD驱动框架,一般厂家会定义一个xxx_fb.c的源文件,注册一个平台设备和平台驱动,在驱动的probe函数中来调用register_framebuffer(), ...
最新文章
- DARPA发布战略框架文件旨在 为美国国家安全创建突破性新技术能力
- delphi中关于时间差的实例
- Java的回调机制--学习笔记
- java opencv人脸识别_java+opencv+intellij idea实现人脸识别
- c++ (QT)笔记
- 应用程序调试技术(更新程度:完毕)送源码及PPT
- java 蓝桥杯 数字游戏
- mysql的内连接与外连接
- Android中的ANR问题
- UVA11233 POJ3366 HDU1804 Deli Deli【水题】
- python 学习day3
- JAVA偶数分解质数_优化后的寻找偶数是两个质数之和的JAVA代码
- linux php gmagick,Linux下编译安装GraphicsMagick及PHP扩展gmagick
- aws fargate_使用AWS Fargate部署PyCaret和Streamlit应用程序-无服务器基础架构
- 操作系统概念 第九版 Operating System Concepts, 9th Edition 中文译稿(不定时更新)
- c语言接收rs232串口速率,基于C语言的RS232串行接口通信实现
- linux系统中怎么复制粘贴快捷键设置,复制粘贴的快捷键是什么 复制粘贴的快捷键介绍【步骤】...
- 【工具使用】AI帮你写代码
- C#支付宝扫码支付代码完整版
- seo秘籍,seo秘籍-自学seo零基础知识入门优化教程