关键词:
Linux内核中换屏技术
21.5.1 u-boot中的参数bootargs实现换屏
在uboot中有一个 bootargs环境变量,这个参数就是传递数据给内核的。
对tiny4412提供的内核,可以通过修改 bootargs 实现驱动不同的LCD屏。
21.5.2 分析bootargs中的lcd参数
再启动uboot的时候会有如下的环境参数:
bootargs=noinitrd root=/dev/nfs nfsroot=192.168.10.106:/home/xyd/rootfs/ ip=192.168.10.123:192.168.10.106:192.168.10.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0 coherent_pool=2M lcd=S702 |
每个参数之间都是空格分开。
可以看到上面传递了2,启动内核之后就可以驱动S702屏。
在内核启动阶段,内核会根据lcd=S720这个信息,在注册平台设备/驱动前把LCD平台数据修改了。
21.5.3 分析在注册平台设备/驱动前修改lcd平台数据过程
首先从板级文件Mach-tiny4412.c中开始看。在这个文件中我们会看到一个机器初始化函数。
(1) 机器初始化函数中多平台设备注册代码段
代码段如下,在02299行可以看到:
static void __init smdk4x12_machine_init(void) …… //注册多平台设备 platform_add_devices(smdk4x12_devices, //包含LCD平台设备结构指针 ARRAY_SIZE(smdk4x12_devices));//数组元素个数,即平台设备个数 …… |
注册平台设备函数原型:
int platform_add_devices(struct platform_device **devs, int num) |
LCD平台设备层结构指针就是存放在 smdk4x12_devices的,以上函数注册包含LCD平台设备。所以,我们可以推出修改平台数据的地方应该在 platform_add_devices 函数前。
问题:在哪里修改lcd平台数据?
在platform_add_devices之前,有和lcd相关代码,下面的调用是在有触摸屏的时候才调用。我们只是把它作为例子来找到能识别s702屏的地方。
后边会讲到真正调用识别S702屏的地方。
代码如下:
static void __init smdk4x12_machine_init(void) …… #ifdef CONFIG_TOUCHSCREEN_FT5X0X//配置FT5X0X触摸屏的宏 struct s3cfb_lcd *lcd = tiny4412_get_lcd(); ft5x0x_pdata.screen_max_x = lcd->width; ft5x0x_pdata.screen_max_y = lcd->height; #endif …… platform_add_devices(smdk4x12_devices, ARRAY_SIZE(smdk4x12_devices)); …… |
其实真正的获得lcd参数结构是在tiny4412_fb_init_pdata函数里边调用,后面会有分析。
问题:现在我们分析如何通过bootargc传参获得lcd平台数据?
(2) 机器初始化函数中调用一个和lcd相关的tiny4412_get_lcd函数
SI里边调转,此函数在Tiny4412-lcds.c (linux-3.5\\arch\\arm\\mach-exynos)文件下。
代码如下:
struct s3cfb_lcd *tiny4412_get_lcd(void) return tiny4412_lcd_config[lcd_idx].lcd; |
这个函数只返回一个数组元素,此数组定义和初始化如下:
在文件Tiny4412-lcds.c (linux-3.5\\arch\\arm\\mach-exynos) 中。
代码如下:是一个结构体数组。
static struct char *name; struct s3cfb_lcd *lcd; int ctp; tiny4412_lcd_config[] = "HD700",&wxga_hd700, 1 , "S70",&wvga_s70, 1 , "S702",&wvga_s70, 3 , "W50",&wvga_w50, 0 , "W101",&wsvga_w101, 1 , "A97",&xga_a97, 0 , "LQ150",&xga_lq150, 1 , "L80",&vga_l80, 1 , "HD101",&wxga_hd101, 1 , "BP101",&wxga_bp101, 1 , "HDM",&hdmi_def, 0 ,/* Pls keep it at last */ ; |
所以我们就要关注lcd_idx值,在哪里设置这个值。
SI跳转得到如下:
static int lcd_idx = 0; //在本文件中定义为静态变量 |
(3) 在哪里得到lcd_idx的值
我们采用搜索的方式查找lcd_idx,可以找到以下:
Tiny4412-lcds.c (arch\\arm\\mach-exynos):lcd_idx = i; |
进入查看搜索语句所在代码:
static int __inittiny4412_setup_lcd(char *str) int i; …… /* 这里想通过名字查找对应的lcd配置参数,返回下标号lcd_idx */ for (i = 0; i < ARRAY_SIZE(tiny4412_lcd_config); i++) if (!strcascmp(tiny4412_lcd_config[i].name, str)) lcd_idx = i; break; __ret: printk("TINY4412: %s selected\\n", tiny4412_lcd_config[lcd_idx].name); return 0; |
这个是static静态函数,在本文件中有效。
这里我们可以知道tiny4412_lcd_config是一个数组,它就是存放所有支持的LCD屏信息。 通过比较数组成员name和tiny4412_setup_lcd参数str决定lcd_idx的值。
到这里就有疑问了:tiny4412_setup_lcd在哪里被调用?
(4) 补充知识:字符串比较函数。
int strcasecmp(const char *s1, const char *s2) int c1, c2; do c1 = tolower(*s1++); //转换小写 c2 = tolower(*s2++); //转换小写 while (c1 == c2 && c1 != 0); return c1 - c2; 这个函数是不区分大小写比较 |
21.5.4 几个重要结构
(1) 结构定义即初始化
这个结构体是当前板子所支持的lcd屏列表。
/* 定义lcd屏支持列表 */ static struct char *name; struct s3cfb_lcd *lcd; int ctp; tiny4412_lcd_config[] = "HD700",&wxga_hd700, 1 , "S70",&wvga_s70, 1 ,//我们当前板子上所使用的屏 "W50",&wvga_w50, 0 , "W101",&wsvga_w101, 1 , "A97",&xga_a97, 0 , "HDM",&hdmi_def, 0 ,/* Pls keep it at last */ ; |
里边struct s3cfb_lcd *lcd;结构成员是存放lcd屏的工作时序参数。
(2)结构体定义
如下:这个结构已经包含LCD驱动所需要的平台数据信息。
/* * @width:horizontal resolution---水平分辨率 * @height:vertical resolution---垂直分辨率 * @p_width:width of lcd in mm---屏物理尺寸(宽,mm单位) * @p_height:height of lcd in mm---屏物理尺寸(高,mm单位) * @bpp:bits per pixel * @freq:vframe frequency---刷屏频率 * @timing:timing values--时序参数 * @polarity:polarity settings---极性参数 */ struct s3cfb_lcd intwidth; intheight; intp_width; intp_height; intbpp; intfreq; structs3cfb_lcd_timing timing; structs3cfb_lcd_polarity polarity; ; |
(3) s3cfb_lcd_timing屏的时序参数结构
/* * @h_fp:horizontal front porch * @h_bp:horizontal back porch * @h_sw:horizontal sync width * @v_fp:vertical front porch * @v_fpe:vertical front porch for even field * @v_bp:vertical back porch * @v_bpe:vertical back porch for even field */ struct s3cfb_lcd_timing inth_fp; inth_bp; inth_sw; intv_fp; intv_fpe; intv_bp; intv_bpe; intv_sw; ; |
(4) 屏的时序极性配置
/* * @rise_vclk:if 1, video data is fetched at rising edge * @inv_hsync:if HSYNC polarity is inversed * @inv_vsync:if VSYNC polarity is inversed * @inv_vden:if VDEN polarity is inversed */ struct s3cfb_lcd_polarity intrise_vclk; intinv_hsync; intinv_vsync; intinv_vden; ; |
21.5.5 以bootargc传入lcd=S70为例子填充s3cfb_lcd结构
定义struct s3cfb_lcd结构变量wvga_s70 ,并初始化屏参数;
在文件Tiny4412-lcds.c (arch\\arm\\Mach-exynos)下实现。
//以下信息是根据LCD屏的手册得到的 static struct s3cfb_lcdwvga_s70= .width = 800, .height = 480, .p_width = 155, .p_height = 93, .bpp = 24, .freq = 63,
1、驱动源码分析大致思路(1)分析LCD驱动首先需要分析内核的帧缓冲子系统,因为LCD驱动就是按照帧缓冲子系统提供的注册接口来注册的;(2)内核帧缓冲子系统参考博客:《Linux帧缓冲子系统详解:LCD介绍、framebuffe... 查看详情 分析内核自带的lcd驱动程序\_基于imx6ull(代码片段)分析内核自带的LCD驱动程序_基于IMX6ULL参考资料,GIT仓库里:IMX6ULL\\开发板配套资料\\datasheet\\Core_board\\CPU\\IMX6ULLRM.pdf《Chapter34EnhancedLCDInterface(eLCDIF)》IMX6ULL的LCD裸机程序IMX6ULL\\source\\03_LCD\\05_参考的裸机源码\\ 查看详情 10.lcd驱动程序——框架分析(代码片段)...把内容写到帧缓冲区中即可。 在帧缓冲区层,主要把内核空间的一块内存虚拟为一个字符设备,并实现文件接口操作函数(open/read/write) 然后把帧缓冲注册为一个字符设备,这样在应用层就可以像访问普通字符设... 查看详情 linuxlcd驱动实验(代码片段)目录Linux下LCD驱动简析1Framebuffer设备LCD驱动简析硬件原理图分析LCD驱动程序编写运行测试LCD屏幕基本测试设置LCD作为终端控制台LCD背光调节从LCD自动关闭解决方法LCD是很常用的一个外设,在裸机篇中我们讲解了如何编写LCD裸... 查看详情 linux设备树-lcd触摸屏设备驱动(代码片段)...---------------------------------------------------------------------------内核版本:linux5.2.8根文件系统:busybox1.25.0u-boot:2016.05----------------------------------------------------------------------------------------------------------------------------在上一节我们已经移... 查看详情 lcd驱动分析字符设备驱动框架分析LCD驱动也是字符设备驱动,也遵循字符设备驱动的流程:a.分配主设备号b.构建file_operations结构体中的open,write,read...等函数c.调用register_chrdev()函数注册字符设备d.调用class_register()注册类e.调用device_create()创建设备,linux会在sysfs目... 查看详情 lcd液晶屏驱动详解开发环境:开发板:JZ2440V3CPU:samsunS3C2440内核:Linux3.4.2编译工具:arm-linux-gcc4.3.2LCD:4.3存液晶屏AT043TN24参考文献:LCD驱动程序详细讲解(一)_weixin_33935505的博客-LCD驱动详解-Lilto-博客园(cnblogs.com)主题:s3c2440移... 查看详情 linux驱动开发lcd(代码片段)...驱动代码相同,只需要修改好对应的屏幕参数。Linux内核将所有frameb 查看详情 linux驱动开发:framebuffe(lcd)驱动开发(代码片段)...缓冲设备,英文frameBuffer设备。frameBuffer是出现在2.2.xx内核当中的一种驱动程序接口。帧缓冲(framebuffer)是Linux系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异 查看详情 lcd驱动分析时序分析参考:S3C2440LCD驱动(FrameBuffer)实例开发<一> S3C2440LCD驱动(FrameBuffer)实例开发<二> 查看详情 实验四...键盘设备驱动程序编写步骤设备驱动简介设备驱动程序是内核的一部分。OS通过各种驱动程序来操作硬件设备,设备驱动程序是内核的一部分,硬件驱动程序是OS最基本的组成部分。Linux将最基本的核心代码编译在内核当中,其他... 查看详情 面向对象地分析linux内核设备驱动——用面向对象思想分析vfbframebuffer设备驱动(代码片段)用面向对象思想分析vfbFramebuffer设备驱动- 内核版本LinuxKernel2.6.34,与Robert.Love的《LinuxKernelDevelopment》(第三版)所讲述的内核版本一样- 源代码下载路径:https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.34.tar.bz 查看详情 #导入word文档图片#linux下framebuffe(lcd)驱动编写...缓冲设备,英文frameBuffer设备。frameBuffer是出现在2.2.xx内核当中的一种驱动程序接口。帧缓冲(framebuffer)是Linux系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模... 查看详情 面向对象地分析linux内核设备驱动——linux内核设备模型与总线(代码片段)Linux内核设备模型与总线- 内核版本LinuxKernel2.6.34,与Robert.Love的《LinuxKernelDevelopment》(第三版)所讲述的内核版本一样- 源代码下载路径:https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.34.tar.bz2 1. Linu... 查看详情 面向对象地分析linux内核设备驱动——linux内核设备模型与总线(代码片段)Linux内核设备模型与总线- 内核版本LinuxKernel2.6.34,与Robert.Love的《LinuxKernelDevelopment》(第三版)所讲述的内核版本一样- 源代码下载路径:https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.34.tar.bz2 1. Linu... 查看详情 lcd驱动分析转自:http://blog.csdn.net/hanmengaidudu/article/details/215591531.S3C2440上LCD驱动(FrameBuffer)实例开发讲解其中的代码也可直接参考:drivers/video/s3c2410fb.c以下为转载文章,文章原地址:http://blog.csdn.net/jianyun123/archive/2010/04/24/55 查看详情 linux驱动加载流程分析(代码片段)linux驱动加载流程分析内核是如何加载驱动的,有些是编译到内核里面,有些事编译成ko,让系统自动加载。总的说来,在Linux下可以通过两种方式加载驱动程序:静态加载和动态加载。静态加载就是把驱动程... 查看详情 linux驱动加载流程分析(代码片段)linux驱动加载流程分析内核是如何加载驱动的,有些是编译到内核里面,有些事编译成ko,让系统自动加载。总的说来,在Linux下可以通过两种方式加载驱动程序:静态加载和动态加载。静态加载就是把驱动程... 查看详情 |