1. 硬件相关的操作

LCD驱动程序的核心就是:

  • 分配fb_info

  • 设置fb_info

  • 注册fb_info

  • 硬件相关的设置

硬件相关的设置又可以分为3部分:

  • 引脚设置

  • 时钟设置

  • LCD控制器设置

本节我们使用时钟子系统再设备树中配置好时钟

2. 分析内核自带的驱动程序

2.1 芯片手册

2.2 设备树

我们再设备树中添加这些代码

            lcdif: lcdif@021c8000 {compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";reg = <0x021c8000 0x4000>;interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clks IMX6UL_CLK_LCDIF_PIX>,<&clks IMX6UL_CLK_LCDIF_APB>,<&clks IMX6UL_CLK_DUMMY>;   //这个只是为了兼容性clock-names = "pix", "axi", "disp_axi";status = "disabled";};

定义了3个时钟:

  • pix:Pixel clock,用于LCD接口,设置为LCD手册上的参数

  • axi:AXI clock,用于传输数据、读写寄存器,使能即可

  • disp_axi:一个虚拟的时钟,可以不用设置

2.3 代码(内核自带的LCD驱动)

  • 获得时钟

 host->clk_pix = devm_clk_get(&host->pdev->dev, "pix");if (IS_ERR(host->clk_pix)) {host->clk_pix = NULL;ret = PTR_ERR(host->clk_pix);goto fb_release;}host->clk_axi = devm_clk_get(&host->pdev->dev, "axi");if (IS_ERR(host->clk_axi)) {host->clk_axi = NULL;ret = PTR_ERR(host->clk_axi);dev_err(&pdev->dev, "Failed to get axi clock: %d\n", ret);goto fb_release;}host->clk_disp_axi = devm_clk_get(&host->pdev->dev, "disp_axi");if (IS_ERR(host->clk_disp_axi)) {host->clk_disp_axi = NULL;ret = PTR_ERR(host->clk_disp_axi);dev_err(&pdev->dev, "Failed to get disp_axi clock: %d\n", ret);goto fb_release;}

设置频率:只需要设置pixel clock的频率

 ret = clk_set_rate(host->clk_pix,PICOS2KHZ(fb_info->var.pixclock) * 1000U);

使能时钟

     clk_enable_pix(host);clk_prepare_enable(host->clk_pix);clk_enable_axi(host);clk_prepare_enable(host->clk_axi);clk_enable_disp_axi(host);clk_prepare_enable(host->clk_disp_axi);

以下是自己的代码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/io.h>#include <asm/div64.h>#include <asm/mach/map.h>struct lcd_regs {volatile unsigned int fb_base_phys;volatile unsigned int fb_xres;volatile unsigned int fb_yres;volatile unsigned int fb_bpp;
};static struct lcd_regs *mylcd_regs;static struct fb_info *myfb_info;static unsigned int pseudo_palette[16];static struct gpio_desc *bl_gpio;
static struct clk* clk_pix;
static struct clk* clk_axi;/* from pxafb.c */
static inline unsigned int chan_to_field(unsigned int chan,struct fb_bitfield *bf)
{chan &= 0xffff;chan >>= 16 - bf->length;return chan << bf->offset;
}static int mylcd_setcolreg(unsigned regno,unsigned red, unsigned green, unsigned blue,unsigned transp, struct fb_info *info)
{unsigned int val;/* dprintk("setcol: regno=%d, rgb=%d,%d,%d\n",regno, red, green, blue); */switch (info->fix.visual) {case FB_VISUAL_TRUECOLOR:/* true-colour, use pseudo-palette */if (regno < 16) {u32 *pal = info->pseudo_palette;val  = chan_to_field(red,   &info->var.red);val |= chan_to_field(green, &info->var.green);val |= chan_to_field(blue,  &info->var.blue);pal[regno] = val;}break;default:return 1;   /* unknown type */}return 0;
}static struct fb_ops myfb_ops = {.owner       = THIS_MODULE,.fb_setcolreg    = mylcd_setcolreg,.fb_fillrect = cfb_fillrect,.fb_copyarea    = cfb_copyarea,.fb_imageblit   = cfb_imageblit,
};static int mylcd_probe(struct platform_device *pdev)
{dma_addr_t phy_addr;/* get gpio from device tree */bl_gpio = gpiod_get(&pdev->dev, "backlight", 0);/* config bl_gpio as output */gpiod_direction_output(bl_gpio, 1);/* set val: gpiod_set_value(bl_gpio, status); *//* get clk from device tree */clk_pix = devm_clk_get(&pdev->dev, "pix");clk_axi = devm_clk_get(&pdev->dev, "axi");/* set clk rate */clk_set_rate(clk_pix, 50000000);/* enable clk */clk_prepare_enable(clk_pix);clk_prepare_enable(clk_axi);/* 1.1 分配fb_info */myfb_info = framebuffer_alloc(0, NULL);/* 1.2 设置fb_info *//* a. var : LCD分辨率、颜色格式 */myfb_info->var.xres_virtual = myfb_info->var.xres = 500;myfb_info->var.yres_virtual = myfb_info->var.yres = 300;myfb_info->var.bits_per_pixel = 16;  /* rgb565 */myfb_info->var.red.offset = 11;myfb_info->var.red.length = 5;myfb_info->var.green.offset = 5;myfb_info->var.green.length = 6;myfb_info->var.blue.offset = 0;myfb_info->var.blue.length = 5;/* b. fix */strcpy(myfb_info->fix.id, "100ask_lcd");myfb_info->fix.smem_len = myfb_info->var.xres * myfb_info->var.yres * myfb_info->var.bits_per_pixel / 8;if (myfb_info->var.bits_per_pixel == 24)myfb_info->fix.smem_len = myfb_info->var.xres * myfb_info->var.yres * 4;/* fb的虚拟地址 */myfb_info->screen_base = dma_alloc_wc(NULL, myfb_info->fix.smem_len, &phy_addr,GFP_KERNEL);myfb_info->fix.smem_start = phy_addr;  /* fb的物理地址 */myfb_info->fix.type = FB_TYPE_PACKED_PIXELS;myfb_info->fix.visual = FB_VISUAL_TRUECOLOR;myfb_info->fix.line_length = myfb_info->var.xres * myfb_info->var.bits_per_pixel / 8;if (myfb_info->var.bits_per_pixel == 24)myfb_info->fix.line_length = myfb_info->var.xres * 4;/* c. fbops */myfb_info->fbops = &myfb_ops;myfb_info->pseudo_palette = pseudo_palette;/* 1.3 注册fb_info */register_framebuffer(myfb_info);/* 1.4 硬件操作 */mylcd_regs = ioremap(0x021C8000, sizeof(struct lcd_regs));mylcd_regs->fb_base_phys = phy_addr;mylcd_regs->fb_xres = 500;mylcd_regs->fb_yres = 300;mylcd_regs->fb_bpp  = 16;return 0;
}static int mylcd_remove(struct platform_device *pdev)
{/* 反过来操作 *//* 2.1 反注册fb_info */unregister_framebuffer(myfb_info);/* 2.2 释放fb_info */framebuffer_release(myfb_info);iounmap(mylcd_regs);return 0;
}static const struct of_device_id mylcd_of_match[] = {{ .compatible = "100ask,lcd_drv", },{ },
};
MODULE_DEVICE_TABLE(of, simplefb_of_match);static struct platform_driver mylcd_driver = {.driver = {.name = "mylcd",.of_match_table = mylcd_of_match,},.probe = mylcd_probe,.remove = mylcd_remove,
};static int __init lcd_drv_init(void)
{int ret;struct device_node *np;ret = platform_driver_register(&mylcd_driver);if (ret)return ret;return 0;
}/* 2. 出口 */
static void __exit lcd_drv_exit(void)
{platform_driver_unregister(&mylcd_driver);
}module_init(lcd_drv_init);
module_exit(lcd_drv_exit);MODULE_AUTHOR("www.100ask.net");
MODULE_DESCRIPTION("Framebuffer driver for the linux");
MODULE_LICENSE("GPL");

LCD笔记(7)LCD驱动程序框架_配置时钟相关推荐

  1. 野火学习笔记(8) —— RCC —— 使用 HSE/HSI 配置时钟

    文章目录 1. RCC 主要作用--时钟部分 2. RCC 框图剖析-时钟部分 2.1 系统时钟 ① HSE 高速外部时钟信号 ② PLL 时钟源 ③ PLL 时钟 PLLCLK ④ 系统时钟 SYS ...

  2. Linux内核 LCD 驱动程序框架

    Linux 内核 LCD 驱动程序框架 1. framebuffer 简介 1.1 什么是 framebuffer 1.2 framebuffer的作用 2. framebuffer 驱动的框架 3. ...

  3. TI-RTOS学习笔记(三)—— 驱动程序框架

    前言:因为在网上没有找到TI-RTOS的学习视频,虽然很多地方与free-RTOS相通,但是本人仍不想为了学习TI-RTOS先去学习freeRTOS,所幸关于TI-RTOS,ti公司给了许多相关的文档 ...

  4. oracle11g中用asmlib配置磁盘组,ASM学习笔记_配置ASMLIB磁盘组

    ASM学习笔记_配置ASMLIB磁盘组 目录 1 ASMLIB Introduction 2 虚拟机添加一个共享磁盘(块设备) 3 下载,安装ASMLIB 4 配置,使用ASMLib 磁盘组 #### ...

  5. TI OMAP平台BSP学习笔记之 - LCD 驱动(3)

    通过前面两个系列的学习,我们已经了解DSS系统,LCD基本原理,DSS设备树的配置等基本知识.本文简单学习和梳理LCD设备驱动的代码,方便项目中快速bring up和debug. 此系列文章基于TI的 ...

  6. pycharm python部署_使用PyCharm配合部署Python的Django框架的配置纪实

    安装软件安装 Python 2.7.PyCharm.pip(Python包管理工具).Django ( pip install Django) 部署PyCharm 新建Django工程 完成后,其目录 ...

  7. Java连接redshift数据库_配置 JDBC 驱动程序版本 1.0 连接 - Amazon Redshift

    本文属于机器翻译版本.若本译文内容与英语原文存在差异,则一律以英文原文为准. 配置 JDBC 驱动程序版本 1.0 连接 您可以使用 JDBC 驱动程序版本 1.0 连接从许多第三方 SQL 客户端工 ...

  8. 【蓝桥杯嵌入式】比赛笔记(2)根据固件库快速配置各模块初始化

    [蓝桥杯嵌入式]比赛笔记(2)根据固件库快速配置各模块初始化 因为蓝桥杯比赛时间很短,并且如果自己去记忆各模块初始化的话,也难免有问题,所以这里给出一个通过固件库的快速初始化模块的方法. 比赛提供固件 ...

  9. 驱动硬件Framebuffer驱动程序框架 skeletonfb.c 分析

    新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正 Framebuffer驱动程序框架 skeletonfb.c 析分 近来想好好研究一下lcd驱动发开程过,lcd驱动发开重要就是fr ...

最新文章

  1. Qt浅谈之一:内存泄露(总结)
  2. Uart接口的详细解释
  3. iphone练习之手势识别(双击、捏、旋转、拖动、划动、长按)UITapGestureRecognizer...
  4. 【C++深度剖析教程7】C++之类中的函数重载
  5. python暂停和恢复游戏_pygame游戏之旅 添加游戏暂停功能
  6. 11个有关HTML5的事实
  7. 将ESXi加入到vCenter中进行管理
  8. 【毕业答辩】毕业设计答辩前期准备
  9. 创建苹果id失败_自制无添加苹果干 无糖
  10. Ubuntu16.04版安装VMwareTools的步骤和没法挂载目录问题的解决
  11. Java8 的 Stream API 的确牛X,但性能究竟如何呢?
  12. !!2016/02/22——当日买入——事后追悔,总结经验,忘记了买票的初衷!
  13. java 企业微信对接_Java对接企业微信
  14. 高中计算机技术教材,广西科学技术出版高中信息技术教材第一册《计算机硬件组成》...
  15. python xgboost建模过程_python - Dask中的XGBoost建模 - SO中文参考 - www.soinside.com
  16. 仓库系统用什么服务器,什么是仓库管理saas系统 仓库管理saas系统的功能有哪些...
  17. 在 Linux中安装中文输入法
  18. 任意输入一个正整数m和m个字符串,统计每行字符串中元音字母的个数。要求使用函数vowel()来判断是否为元音,其余功能在main()函数中实现。
  19. 2018网站优化人员不同阶段在做哪些事
  20. 计算机游戏设计的艺术(1)

热门文章

  1. 赔97.6万元!腾讯一程序员违反竞业协议,三年白干了!
  2. 实现苹果和虫子(c语言)
  3. 2.郝斌C语言课程大纲
  4. Mac 锦囊 —— 误删除admin组之后
  5. 服务器的丢包率一般与什么有关
  6. 英语 译林 2019 单词表
  7. 获取指定区域内的坐标点位,在线查看经纬坐标
  8. android studio 雷电模拟器
  9. 【数据库】HIVE SQL实现本月一号、月底的提取
  10. OLED显示字符的大小与PCtoLCD2002生成字模