分析内核自带的LCD驱动程序_基于IMX6ULL

分析内核自带的LCD驱动程序_基于IMX6ULL




参考资料:

  • 内核自带的IMX6ULL LCD驱动程序
    • 驱动源码:Linux-4.9.88\drivers\video\fbdev\mxsfb.c
    • 设备树:
      • arch/arm/boot/dts/imx6ull.dtsi
      • arch/arm/boot/dts/100ask_imx6ull-14x14.dts

一、驱动程序框架

Linux驱动程序 = 驱动程序框架 + 硬件编程。
在前面已经基于QEMU编写了LCD驱动程序,对LCD驱动程序的框架已经分析清楚。
核心就是:

  • 分配fb_info
  • 设置fb_info
  • 注册fb_info
  • 硬件相关的设置

1.1 入口函数注册platform_driver

在这里插入图片描述

1.2 设备树有对应节点

在这里插入图片描述

1.3 probe函数分析

二、 编写硬件相关的代码

我们只需要针对IMX6ULL的编写硬件相关的代码,涉及3部分:

  • GPIO设置
    • LCD引脚
    • 背光引脚
  • 时钟设置
    • 确定LCD控制器的时钟
    • 根据LCD的DCLK计算相关时钟
  • LCD控制器本身的设置
    • 比如设置Framebuffer的地址
    • 设置Framebuffer中数据格式、LCD数据格式
    • 设置时序

2.1 GPIO设置

有两种方法:

  • 直接读写相关寄存器
  • 使用设备树,在设备树中设置pinctrl
    • 本课程专注于LCD,所以使用pinctrl简化程序

设备树arch/arm/boot/dts/100ask_imx6ull-14x14.dts中:
在这里插入图片描述

2.2 时钟设置

IMX6ULL的LCD控制器涉及2个时钟:

在这里插入图片描述
代码里直接使用时钟子系统的代码。

  • 在设备树里指定频率:

    • 文件:arch/arm/boot/dts/100ask_imx6ull-14x14.dts

    • 代码:clock-frequency

             display-timings {
                  native-mode = <&timing0>;
      
                   timing0: timing0_1024x768 {
                   clock-frequency = <50000000>;
      
  • 从设备树获得dot clock,存入display_timing

    • 文件:drivers\video\of_display_timing.c

    • 代码:

      ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
      
  • 使用display_timing来设置videomode

    • 文件:drivers\video\videomode.c

    • 代码:

      void videomode_from_timing(const struct display_timing *dt,
      			  struct videomode *vm)
      {
      	vm->pixelclock = dt->pixelclock.typ;
      	vm->hactive = dt->hactive.typ;
      	vm->hfront_porch = dt->hfront_porch.typ;
      	vm->hback_porch = dt->hback_porch.typ;
      	vm->hsync_len = dt->hsync_len.typ;
      
      	vm->vactive = dt->vactive.typ;
      	vm->vfront_porch = dt->vfront_porch.typ;
      	vm->vback_porch = dt->vback_porch.typ;
      	vm->vsync_len = dt->vsync_len.typ;
      
      	vm->flags = dt->flags;
      }
      
      
  • 根据videomode的值,使用时钟子系统的函数设置时钟:

    • 文件:drivers\video\fbdev\mxc\ldb.c
    • 代码:

在这里插入图片描述

2.3 LCD控制器的配置

以设置分辨率为例。

  • 在设备树里指定频率:

    • 文件:arch/arm/boot/dts/100ask_imx6ull-14x14.dts

    • 代码:clock-frequency

             display-timings {
                  native-mode = <&timing0>;
      
                   timing0: timing0_1024x768 {
      				hactive = <1024>;
      	            vactive = <600>;
      
      
  • 从设备树获得分辨率,存入display_timing

    • 文件:drivers\video\of_display_timing.c

    • 代码:

      	ret |= parse_timing_property(np, "hactive", &dt->hactive);
      	ret |= parse_timing_property(np, "vactive", &dt->vactive);
      
  • 使用display_timing来设置videomode

    • 文件:drivers\video\videomode.c

    • 代码:

      void videomode_from_timing(const struct display_timing *dt,
      			  struct videomode *vm)
      {
      	vm->hactive = dt->hactive.typ;
      
          vm->vactive = dt->vactive.typ;
      
  • 根据videomode的值,设置fb_videomode

    • 文件:drivers\video\fbdev\core\fbmon.c

    • 代码:

      int fb_videomode_from_videomode(const struct videomode *vm,
      				struct fb_videomode *fbmode)
      {
      	unsigned int htotal, vtotal;
      
      	fbmode->xres = vm->hactive;
      
          fbmode->yres = vm->vactive;
      
      
  • 根据fb_videomode的值,设置fb_info中的var:

    • 文件:drivers\video\fbdev\core\modedb.c

    • 代码:

      void fb_videomode_to_var(struct fb_var_screeninfo *var,
      			 const struct fb_videomode *mode)
      {
      	var->xres = mode->xres;
      	var->yres = mode->yres;
      
      
  • 根据var的分辨率,设置寄存器

    • 文件:drivers\video\fbdev\mxsfb.c

    • 代码:

      	writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |
      			TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),
      			host->base + host->devdata->transfer_count);
      
      
      
    • 文件:drivers\video\fbdev\mxsfb.c

    • 代码:

      	writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |
      			TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),
      			host->base + host->devdata->transfer_count);
      
      


致谢

以上笔记源自韦东山老师的视频课程,感谢韦老师,韦老师是嵌入式培训界一股清流,为嵌入式linux开发点起的星星之火,也愿韦老师桃李满园。聚是一团火,散是满天星!

在这样一个速食的时代,坚持做自己,慢下来,潜心琢磨,心怀敬畏,领悟知识,才能向下扎到根,向上捅破天,背着世界往前行!
仅此向嵌入行业里的每一个认真做技术的从业者致敬!



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值