STM32MP157驱动开发——Linux LCD驱动(下)


相关文章:STM32MP157驱动开发——Linux LCD驱动(上)

0.前言

  在上一节内容中,对 LCD 的一些相关知识,如 LCD 的成像原理、LTDC 接口,以及 Linux 中自带的 DRM 驱动框架进行了一些了解,本节就使用这个框架开发一个 LCD 驱动。

一、驱动开发

1.原理图分析

  在 STM32MP1 开发板上,有一个 RGB LCD 接口,其原理如下所示:
在这里插入图片描述
左边对应的是 LCD 接口引脚图,右边为 STM32MP1 开发板 RGB LCD 接口的原理图。

2.设备树修改

设备树的修改需要注意四个地方:
①LCD 所使用的 IO 配置。由于 STM32MP1 的 IO 支持复用,所以实际所使用的 LCD 引脚可能不一样。因此首先要根据实际硬件设计,修改 LCD 所有使用的 IO 配置。
②LDTC 接口节点修改,修改相应的属性值,告诉内核要指定哪个输出接口,比如输出到 RGB LCD 屏、MIPI 屏等。本节内容用到是 RGB LCD 屏。
③输出接口节点的编写,比如本节用到的 RGB LCD 屏需要在根节点下添加 RGB LCD节点。
④LCD 背光节点信息修改,要根据实际所使用的背光 IO 来修改相应的设备节点信息。

1)LCD 屏幕使用的 IO 配置

  首先要检查一下设备树中 LCD 所使用的 IO 配置,其实这部分已经由 ST 官方写好了,不需要修改,不过还是要检查一下。打开 arch/arm/boot/dts/stm32mp15-pinctrl.dtsi 文件,在 pinctrl 节点中找到如下内容:
在这里插入图片描述
官方提供了两组 ltdc 接口,正点原子的板子使用的是 b 组。子节点 ltdc_pins_b,为 RGB LCD 的 24 根数据线配置项和 4 根控制线配置项。子节点 ltdc_pins_sleep_b,同样也是 RGB LCD 的 24 根数据线配置项和 4 根控制线配置项。
可以看出,这里有两个 pinmux 分别为:ltdc_pins_b 和 ltdc_pins_sleep_b,其中 ltdc_pins_b 是在默认模式下的 RGB LCD pinmux 配置, ltdc_pins_sleep_b 是在 sleep 模式下 RGB LCD 的 pinmux 配置。如果想要 LCD 屏进入睡眠模式就切换为 sleep 模式。

2)LDTC 接口节点修改

LTDC 节点在 stm32mp151.dtsi 里已经写好一部分了,只需要告诉 LTDC 节点输出到 RGB LCD 屏里就行。在 stm32mp157d-atk.dts 文件中添加如下内容(非根节点):
在这里插入图片描述
①给 LTDC 设置了两个 pinmux 模式,pinctrl-0 为 default 模式,pinctrl-1 为 sleep 模式,系统默认使用 default 模式
②设置 port 下子节点的 reg 属性的地址信息描述
③在 port 下添加了一个子节点为 ltdc_ep0_out,其中 reg 属性值为 0,remote-endpoint 属性是用来告诉 ltdc 节点输出到哪里,这里是用的 RGB LCD 屏,所以输出到 rgb_panel_in 接口。

3)输出接口的编写

还需要添加一个 LCD 设备树节点,在 stm32mp157d-atk.dts 文件的根节点/下添加如下所示内容:

panel_rgb: panel-rgb {
		compatible = "amonter,lcd-rgb";
		backlight = <&backlight>;
		status = "okay";

		port {
			rgb_panel_in: endpoint {
				remote-endpoint = <&ltdc_ep0_out>;
			};
		};
};

①设置 compatible 属性值为“amonter,lcd-rgb”,所以稍后要在 panel-simple.c 文件里的 platform_of_match 数组增加一个 of_device_id 结构体,此结构体的 compatible 成员属性值为“amonter,lcd-rgb”。
②设置 backlight 属性值为“&backlight”,此属性值为引用背光节点,稍后会讲解如何编写。
③port属性告诉 LCD 驱动,要从 LTDC 节点里获取显示数据,remote-endpoint 就是引用 ltdc。

3.在 panel-simple.c 文件里面添加屏幕参数

打开 drivers/gpu/drm/panel/panel-simple.c,在 platform_of_match 数组中添加如下内容:

.compatible = "amonter,lcd-rgb",
.data = &amonter_desc,

在这里插入图片描述
注意要留一个空白尾结点。其中amonter_desc保存的是参数,所以还需要在panel-simple.c中实现amonter_desc。添加如下代码:

1 static const struct drm_display_mode ATK7016_mode = {
2 	.clock = 51200, /* LCD 像素时钟,单位 KHz */
3 	.hdisplay = 1024, /* LCD X 轴像素个数 */
4 	.hsync_start = 1024 + 140, /* LCD X 轴+hbp 的像素个数 */
5 	.hsync_end = 1024 + 140 + 20, /* LCD X 轴+hbp+hspw 的像素个数*/
6 	.htotal = 1024 + 140 + 20 + 160,/* LCD X 轴+hbp+hspw+hfp */
7 	.vdisplay = 600, /* LCD Y 轴像素个数 */
8 	.vsync_start = 600 + 20, /* LCD Y 轴+vbp 的像素个数 */
9 	.vsync_end = 600 + 20 + 3, /* LCD Y 轴+vbp+vspw 的像素个数 */
10 	.vtotal = 600 + 20 + 3 + 12,/* LCD Y 轴+vbp+vspw+vfp */
11 	.vrefresh = 60, /* LCD 的刷新频率为 60HZ */
12 };
13
14 static const struct panel_desc amonter_desc = {
15 	.modes = &ATK7016_mode,
16 	.num_modes = 1,
17 	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
18 };

这是 ATK7016 屏的参数,并且设置为 RGB888 模式。如果使用的其他屏幕,需要按照屏幕手册对应的时序参数设置。
ATK7016_mode 结构体中是 ATK7016 屏幕时序参数,根据自己所使用的屏幕修改即可。

4.LCD 屏幕背光节点信息

1)背光 PWM 节点设置

正点原子的 LCD 接口背光控制 IO 连接到了 STM32MP1 的 PD13 引脚上,因此需要将 PD13 复用为 TIM4_CH2,然后配置 TIM4 的 CH2 输出 PWM 信号,通过此 PWM 信号来控制 LCD 屏幕背光的亮度。
在 stm32mp15-pinctrl.dtsi 中找到如下内容:
在这里插入图片描述
可以看到官方也是用的此引脚作为 LCD 背光控制引脚。如果自己使用其他引脚,那么就需要做出相应修改。

在 stm32mp157d-atk.dts 文件中添加一个 timers4 节点:


&timers4 {
	status = "okay";
	/* spare all DMA channels since they are not needed for PWM output */
	/delete-property/dmas;
	/delete-property/dma-names;
	pwm1: pwm {
		pinctrl-0 = <&pwm4_pins_a>;
		pinctrl-1 = <&pwm4_sleep_pins_a>;
		pinctrl-names = "default", "sleep";
		#pwm-cells = <2>;
		status = "okay";
	};
};

与之前的 PWM 驱动中添加的 timers1 节点类似,在此不过多赘述。

2)backlight 节点设置

PWM 和相关的 IO 已经准备好了,还需要一个节点来将 LCD 背光和 TIM4_CH2 连接起来。这个节点就是 backlight,backlight 节点描述可以参考 Documentation/devicetree/bindings/leds/backlight/pwmbacklight.txt 这个文档,主要注意以下几点:
①节点名称要为“backlight”。
②节点的 compatible 属性值要为“pwm-backlight”,因此可以通过在 Linux 内核中搜索“pwm-backlight ”来查找 PWM 背光控制驱动程序,这个驱动程序文件为drivers/video/backlight/pwm_bl.c,感兴趣的可以去看一下这个驱动程序。
③pwms 属性用于描述背光所使用的 PWM 的通道以及 PWM 频率,比如本节要使用
的 pwm4 的第二个通道,pwm 频率设置为 200Hz。
④brightness-levels 属性描述亮度级别,范围为 0~255,0 表示 PWM 占空比为 0%,也就是亮度最低,255 表示 100%占空比,也就是亮度最高。设置几级亮度根据需要自行填写此属性。
⑤default-brightness-level 属性为默认亮度级别。

所以在 stm32mp157datk.dts 文件中新建backlight节点,内容如下:

backlight: backlight {
	compatible = "pwm-backlight";
	pwms = <&pwm4 1 5000000>;
	brightness-levels = <0 4 8 16 32 64 128 255>;
	power-supply = <&v3v3>;
	default-brightness-level = <7>;
	status = "okay";
};

①设置背光使用 pwm4 的第二个通道,PWM 频率为 200Hz。
②设置背 8 级背光(0~7),分别为 0、4、8、16、32、64、128、255,对应占空比
为 0%、1.57%、3.13%、6.27%、12.55%、25.1%、50.19%、100%,可以根据需要自行添加其他背光等级值。
③设置默认背光等级为 7,也就是 100%的亮度
注:背光的驱动代码有点 bug,如果设置 0 级屏不会灭屏,打开 pwm_bl.c 文件,找到 123 行,将 > 改为 >=:
在这里插入图片描述

二、运行测试

1.编译出新的内核和设备树

make uImage dtbs LOADADDR=0xC2000040 -j16

2.内核配置说明

  官方的内核已经使能了 DRM 驱动, 如果自己想要使用,在 menuconfig 中的Device Drivers --> Graphics support目录下,选中Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)DRM Support for STMicroelectronics SoC Series,同时在该级目录的Display Panels子目录选中support for simple panelsBacklight & LCD device support子目录选中Generic PWM based Backlight Driver
用新的 uImage 镜像和 stm32mp157d-atk.dtb 设备树用来启动内核,如果设置正确那么在文件统/sys/class/drm/路径下,存在以下内容:
在这里插入图片描述

3.文件系统使能 libdrm 库

  没有 libdrm 库是不能调用 drm 驱动的,所以我们要在文件系统使能 libdrm 库。正点原子使用的根文件系统是通过 buildroot 配置的,这是一种对 busybox 的封装和扩展,除了支持 busybox 的功能外,还支持手动添加第三方库,用起来更加方便。可以查阅原子哥的手册进行了解。在 buildroot 的 menuconfig 中选中以下选项,来使能 libdrm 库:
在这里插入图片描述
然后编译出新的根文件系统,并解压到挂载的nfs中。

4.测试

使用modetest --help命令可以查看 modetest 帮助信息。使用modetest -M stm可以查看设备信息。然后使用modetest -M stm -s 32@35:1024x600测试DRM驱动,32 表示 connectors 的 ID,35 表示 CRTC 的 ID,1024x600 表示显示的模式。
这里笔者手头没有 LCD 屏,就先不附上图片了,直接跟着教程走,下一节学习将 LCD 转换为 HDMI 输出进行验证。

5.LCD 屏幕的 FB 基本测试

  KMS 包含了 FB 框架。DRM 驱动默认为 CRTC 用来控制,CRTC 是可以模仿 FB 框架,实现使用 FB 接口。需在 Linux 内核图形化配置界面里配置以下选项:
在这里插入图片描述
使能 PL110 :
在这里插入图片描述
使能 Linux logo显示:
在这里插入图片描述

6.设置 LCD 为终端控制台

修改启动参数

setenv bootargs 'console=tty1 console=ttySTM0,115200 root=/dev/nfs nfsroot=192.168.1.21:/home/liangwencong/linux/nfs/rootfs,proto=tcp rw ip=192.168.1.246:192.168.1.21:192.168.1.1:255.255.255.0::eth0:off

第一次设置 console=tty1,也就是设置 LCD 屏幕为控制台,第二遍设置 console=ttymxc0,115200,也就是设置串口也作为控制台。但目前还无法使用LCD。

修改/etc/inittab 文件:
在开发板的 /etc/inittab 文件中添加以下代码:

tty1::askfirst:-/bin/sh

修改完成以后保存/etc/inittab 并退出,然后重启开发板,重启以后开发板 LCD 屏幕最后一行会显示下面一行语句:Please press Enter to activate this console.上述提示语句说的是:按下回车键使能当前终端。至此,我们就拥有了两套终端,一个是基于串口的 MobaXterm,一个就是我们开发板的 LCD 屏幕,可以通过下面这一行命令向 LCD 屏幕输出“hello linux!”:

echo hello linux! > /dev/tty1

7.背光调节

LCD 驱动开启了 TIM4_CH2,之前 PWM 实验开启了 TIM1_CH3,因此会在/sys/class/pwm 目录下存在两个 pwmchipX 目录:
在这里插入图片描述
注意:本节中进入 pwmchip0 目录发现 pwmchip0 才是 TIM4,而 pwmchip4 是 TIM1,所以在以后需要操作 PWM 时一定要注意操作对象是否正确。

进入 /sys/devices/platform/backlight/backlight/backlight 目录:
在这里插入图片描述
max_brightness 为预设的最大亮度等级,brightness 表示当前亮度等级,输入以下命令就可以改变亮度:

echo 6 > brightness
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值