Linux LCD驱动

一、Linux LCD驱动简介

先来回顾一下裸机的时候 LCD 驱动是怎么编写的,裸机 LCD 驱动编写流程如下:
①、初始化 I.MX6U 的 eLCDIF 控制器,重点是 LCD 屏幕宽(width)、高(height)、hspw、
hbp、hfp、vspw、vbp 和 vfp 等信息。
②、初始化 LCD 像素时钟。
③、设置 RGBLCD 显存。
④、应用程序直接通过操作显存来操作 LCD,实现在 LCD 上显示字符、图片等信息。
在 Linux 中应用程序最终也是通过操作 RGB LCD 的显存来实现在 LCD 上显示字符、图片
等信息。在裸机中我们可以随意的分配显存,但是在 Linux 系统中内存的管理很严格,显存是
需要申请的,不是你想用就能用的。而且因为虚拟内存的存在,驱动程序设置的显存和应用程
序访问的显存要是同一片物理内存。
为了解决上述问题,Framebuffer 诞生了, Framebuffer 翻译过来就是帧缓冲,简称 fb,因
此大家在以后的 Linux 学习中见到"Framebuffer"或者"fb"的话第一反应应该想到 RGBLCD
或者显示设备。fb 是一种机制,将系统中所有跟显示有关的硬件以及软件集合起来,虚拟出一
个 fb 设备,当我们编写好 LCD 驱动以后会生成一个名为/dev/fbX(X=0~n)的设备,应用程序通
过访问/dev/fbX 这个设备就可以访问 LCD。NXP 官方的 Linux 内核默认已经开启了 LCD 驱动,
因此我们是可以看到/dev/fb0 这样一个设备,如图 59.1.1.1 所示:

fb 的 file_operations 操作集定义在 drivers/video/fbdev/core/fbmem.c 文件
中,如下所示:

cpp 复制代码
1495 static const struct file_operations fb_fops = {
1496     .owner = THIS_MODULE,
1497     .read = fb_read,
1498     .write = fb_write,
1499     .unlocked_ioctl = fb_ioctl,
1500 #ifdef CONFIG_COMPAT
1501     .compat_ioctl = fb_compat_ioctl,
1502 #endif
1503     .mmap = fb_mmap,
1504     .open = fb_open,
1505     .release = fb_release,
1506 #ifdef HAVE_ARCH_FB_UNMAPPED_AREA
1507     .get_unmapped_area = get_fb_unmapped_area,
1508 #endif
1509 #ifdef CONFIG_FB_DEFERRED_IO
1510     .fsync = fb_deferred_io_fsync,
1511 #endif
1512     .llseek = default_llseek,
1513 };

二、LCD设备树驱动修改

1、IO配置

cpp 复制代码
1 pinctrl_lcdif_dat: lcdifdatgrp {
2     fsl,pins = <
3         MX6UL_PAD_LCD_DATA00__LCDIF_DATA00 0x79
4         MX6UL_PAD_LCD_DATA01__LCDIF_DATA01 0x79
5         MX6UL_PAD_LCD_DATA02__LCDIF_DATA02 0x79
6         MX6UL_PAD_LCD_DATA03__LCDIF_DATA03 0x79
7         MX6UL_PAD_LCD_DATA04__LCDIF_DATA04 0x79
8         MX6UL_PAD_LCD_DATA05__LCDIF_DATA05 0x79
9         MX6UL_PAD_LCD_DATA06__LCDIF_DATA06 0x79
10         MX6UL_PAD_LCD_DATA07__LCDIF_DATA07 0x79
11         MX6UL_PAD_LCD_DATA08__LCDIF_DATA08 0x79
12         MX6UL_PAD_LCD_DATA09__LCDIF_DATA09 0x79
13         MX6UL_PAD_LCD_DATA10__LCDIF_DATA10 0x79
14         MX6UL_PAD_LCD_DATA11__LCDIF_DATA11 0x79
15         MX6UL_PAD_LCD_DATA12__LCDIF_DATA12 0x79
16         MX6UL_PAD_LCD_DATA13__LCDIF_DATA13 0x79
17         MX6UL_PAD_LCD_DATA14__LCDIF_DATA14 0x79
18         MX6UL_PAD_LCD_DATA15__LCDIF_DATA15 0x79
19         MX6UL_PAD_LCD_DATA16__LCDIF_DATA16 0x79
20         MX6UL_PAD_LCD_DATA17__LCDIF_DATA17 0x79
21         MX6UL_PAD_LCD_DATA18__LCDIF_DATA18 0x79
22         MX6UL_PAD_LCD_DATA19__LCDIF_DATA19 0x79
23         MX6UL_PAD_LCD_DATA20__LCDIF_DATA20 0x79
24         MX6UL_PAD_LCD_DATA21__LCDIF_DATA21 0x79
25         MX6UL_PAD_LCD_DATA22__LCDIF_DATA22 0x79
26         MX6UL_PAD_LCD_DATA23__LCDIF_DATA23 0x79
27     >;
28 };
29
30 pinctrl_lcdif_ctrl: lcdifctrlgrp {
31     fsl,pins = <
32         MX6UL_PAD_LCD_CLK__LCDIF_CLK 0x79
33         MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE 0x79
34         MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC 0x79
35         MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC 0x79
36     >;
37     pinctrl_pwm1: pwm1grp {
38     fsl,pins = <
39         MX6UL_PAD_GPIO1_IO08__PWM1_OUT 0x110b0
40     >;
41 };

2**、LCD屏幕参数节点信息修改**

cpp 复制代码
1 &lcdif {
2     pinctrl-names = "default";
3     pinctrl-0 = <&pinctrl_lcdif_dat /* 使用到的 IO */
4     &pinctrl_lcdif_ctrl>;
5     display = <&display0>;
6     status = "okay";
7 
8     display0: display { /* LCD 属性信息 */
9          bits-per-pixel = <24>; /* 一个像素占用 24bit */
10         bus-width = <24>; /* 总线宽度 */
11
12         display-timings {
13             native-mode = <&timing0>; /* 时序信息 */
14             timing0: timing0 { 
15                 clock-frequency = <51200000>;/* LCD 像素时钟,单位 Hz */
16                 hactive = <1024>; /* LCD X 轴像素个数 */
17                 vactive = <600>; /* LCD Y 轴像素个数 */
18                 hfront-porch = <160>; /* LCD hfp 参数 */
19                 hback-porch = <140>; /* LCD hbp 参数 */
20                 hsync-len = <20>; /* LCD hspw 参数 */
21                 vback-porch = <20>; /* LCD vbp 参数 */
22                 vfront-porch = <12>; /* LCD vfp 参数 */
23                 vsync-len = <3>; /* LCD vspw 参数 */
24
25                 hsync-active = <0>; /* hsync 数据线极性 */
26                 vsync-active = <0>; /* vsync 数据线极性 */
27                 de-active = <1>; /* de 数据线极性 */
28                 pixelclk-active = <0>; /* clk 数据线先极性 */
29             };
30         };
31     };
32 };

3**、LCD屏幕背光节点信息**

cpp 复制代码
1 pinctrl_pwm1: pwm1grp {
2     fsl,pins = <
3         MX6UL_PAD_GPIO1_IO08__PWM1_OUT 0x110b0
4     >;
5 };

三、编译验证LCD

设备树编译

make dtbs

将编译生成的设备树文件拷贝到~/linux/tftboot

使能linux logo显示

使用新编译的linux内核文件重启开发板

四、使能LCD作为控制台

1**、设置uboot中的****bootargs**

cpp 复制代码
setenv bootargs 'console=tty1 console=ttymxc0,115200 root=/dev/nfs rw nfsroot=192.168.1.3:
/home/zipeng/linux/nfs/rootfs ip=192.168.1.2:192.168.1.3:192.168.1.1:255.255.255.0::eth0:
off'

这里我们设置了两遍 console,第一次设置 console=tty1,
也就是设置 LCD 屏幕为控制台,第二遍又设置 console=ttymxc0,115200,也就是设置串口也作
为控制台。相当于我们打开了两个 console。

2**、修改****/etc/inittab****文件**

打开开发板根文件系统里面的/etc/inittab文件,在里面添加这一句:
tty1::askfirst:-/bin/sh

3、重启Limux开发板

可以看到这会linux内核启动的时候会在LCD屏打印信息


执行echo hello linux > /dev/tty1 可以看到LCD屏幕上打印对应信息

相关推荐
思麟呀1 小时前
C++11并发编程:call_once一次性执行+atomic原子类型+CAS无锁编程+自旋锁
linux·开发语言·jvm·c++·windows
浮生若城1 小时前
Linux库制作与原理(2):理解链接与加载
linux·运维·服务器
Cat_Rocky1 小时前
Gitlab安装与配置
linux·运维·gitlab
志栋智能1 小时前
超自动化巡检:降低运维总成本(TCO)的有效路径
大数据·运维·网络·人工智能·自动化
爱讲故事的2 小时前
操作系统第一讲复习:为什么学习操作系统,以及操作系统到底在做什么?
linux·开发语言·windows·学习·ubuntu·c#
荒--2 小时前
kali安装与下载、设置(2026)
linux·服务器
Yang96112 小时前
一站式网络检测 鼎讯信通网络综合测试仪科普
运维·服务器·网络·能源
越强越不秃2 小时前
大模型驱动的PoC脚本自动化生成:从挑战到实践
运维·自动化·安全工程师
sulikey2 小时前
个人Linux操作系统学习笔记4 - makefile
linux·makefile·make·构建