LCD笔记(7)LCD驱动程序框架_配置时钟
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驱动程序框架_配置时钟相关推荐
- 野火学习笔记(8) —— RCC —— 使用 HSE/HSI 配置时钟
文章目录 1. RCC 主要作用--时钟部分 2. RCC 框图剖析-时钟部分 2.1 系统时钟 ① HSE 高速外部时钟信号 ② PLL 时钟源 ③ PLL 时钟 PLLCLK ④ 系统时钟 SYS ...
- Linux内核 LCD 驱动程序框架
Linux 内核 LCD 驱动程序框架 1. framebuffer 简介 1.1 什么是 framebuffer 1.2 framebuffer的作用 2. framebuffer 驱动的框架 3. ...
- TI-RTOS学习笔记(三)—— 驱动程序框架
前言:因为在网上没有找到TI-RTOS的学习视频,虽然很多地方与free-RTOS相通,但是本人仍不想为了学习TI-RTOS先去学习freeRTOS,所幸关于TI-RTOS,ti公司给了许多相关的文档 ...
- oracle11g中用asmlib配置磁盘组,ASM学习笔记_配置ASMLIB磁盘组
ASM学习笔记_配置ASMLIB磁盘组 目录 1 ASMLIB Introduction 2 虚拟机添加一个共享磁盘(块设备) 3 下载,安装ASMLIB 4 配置,使用ASMLib 磁盘组 #### ...
- TI OMAP平台BSP学习笔记之 - LCD 驱动(3)
通过前面两个系列的学习,我们已经了解DSS系统,LCD基本原理,DSS设备树的配置等基本知识.本文简单学习和梳理LCD设备驱动的代码,方便项目中快速bring up和debug. 此系列文章基于TI的 ...
- pycharm python部署_使用PyCharm配合部署Python的Django框架的配置纪实
安装软件安装 Python 2.7.PyCharm.pip(Python包管理工具).Django ( pip install Django) 部署PyCharm 新建Django工程 完成后,其目录 ...
- Java连接redshift数据库_配置 JDBC 驱动程序版本 1.0 连接 - Amazon Redshift
本文属于机器翻译版本.若本译文内容与英语原文存在差异,则一律以英文原文为准. 配置 JDBC 驱动程序版本 1.0 连接 您可以使用 JDBC 驱动程序版本 1.0 连接从许多第三方 SQL 客户端工 ...
- 【蓝桥杯嵌入式】比赛笔记(2)根据固件库快速配置各模块初始化
[蓝桥杯嵌入式]比赛笔记(2)根据固件库快速配置各模块初始化 因为蓝桥杯比赛时间很短,并且如果自己去记忆各模块初始化的话,也难免有问题,所以这里给出一个通过固件库的快速初始化模块的方法. 比赛提供固件 ...
- 驱动硬件Framebuffer驱动程序框架 skeletonfb.c 分析
新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正 Framebuffer驱动程序框架 skeletonfb.c 析分 近来想好好研究一下lcd驱动发开程过,lcd驱动发开重要就是fr ...
最新文章
- Qt浅谈之一:内存泄露(总结)
- Uart接口的详细解释
- iphone练习之手势识别(双击、捏、旋转、拖动、划动、长按)UITapGestureRecognizer...
- 【C++深度剖析教程7】C++之类中的函数重载
- python暂停和恢复游戏_pygame游戏之旅 添加游戏暂停功能
- 11个有关HTML5的事实
- 将ESXi加入到vCenter中进行管理
- 【毕业答辩】毕业设计答辩前期准备
- 创建苹果id失败_自制无添加苹果干 无糖
- Ubuntu16.04版安装VMwareTools的步骤和没法挂载目录问题的解决
- Java8 的 Stream API 的确牛X,但性能究竟如何呢?
- !!2016/02/22——当日买入——事后追悔,总结经验,忘记了买票的初衷!
- java 企业微信对接_Java对接企业微信
- 高中计算机技术教材,广西科学技术出版高中信息技术教材第一册《计算机硬件组成》...
- python xgboost建模过程_python - Dask中的XGBoost建模 - SO中文参考 - www.soinside.com
- 仓库系统用什么服务器,什么是仓库管理saas系统 仓库管理saas系统的功能有哪些...
- 在 Linux中安装中文输入法
- 任意输入一个正整数m和m个字符串,统计每行字符串中元音字母的个数。要求使用函数vowel()来判断是否为元音,其余功能在main()函数中实现。
- 2018网站优化人员不同阶段在做哪些事
- 计算机游戏设计的艺术(1)