当前位置:网站首页>LCD notes (7) LCD driver framework_ Configure clock
LCD notes (7) LCD driver framework_ Configure clock
2022-07-26 12:42:00 【Cui Guo broke her mouth】
1. Hardware related operations
LCD The core of the driver is :
Distribute fb_info
Set up fb_info
register fb_info
Hardware related settings
Hardware related settings can be divided into 3 part :
Pin settings
The clock is set
LCD Controller settings
In this section, we use the clock subsystem to configure the clock in the device tree
2. Analyze the driver of the kernel
2.1 Chip manual

2.2 Device tree
We add these codes to the device tree
lcdif: [email protected] {
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>; // This is just for compatibility
clock-names = "pix", "axi", "disp_axi";
status = "disabled";
};Defined 3 A clock :
pix:Pixel clock, be used for LCD Interface , Set to LCD Parameters in the manual
axi:AXI clock, For data transfer 、 Read and write registers , Enable it
disp_axi: A virtual clock , No need to set
2.3 Code ( Built in kernel LCD drive )
Get clock
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;
}Set the frequency : Just set up pixel clock The frequency of
ret = clk_set_rate(host->clk_pix,
PICOS2KHZ(fb_info->var.pixclock) * 1000U);Can make the clock
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);The following is my own code
#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 Distribute fb_info */
myfb_info = framebuffer_alloc(0, NULL);
/* 1.2 Set up fb_info */
/* a. var : LCD The resolution of the 、 Color format */
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 The virtual address of */
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 The physical address of */
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 register fb_info */
register_framebuffer(myfb_info);
/* 1.4 Hardware operation */
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)
{
/* Reverse operation */
/* 2.1 Anti registration fb_info */
unregister_framebuffer(myfb_info);
/* 2.2 Release 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. exit */
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");
边栏推荐
- Jsj-3/ac220v time relay
- Emerging security providers to learn about in 2022
- 笔记。。。。
- Can the Windows version of Oracle be used in Linux?
- Kuzaobao: summary of Web3 encryption industry news on July 25
- Interviewer: how to deal with high concurrency?
- Data query where
- Ue5 official case Lyra full feature explanation 7. resource management
- If there is a declaration "int x=5, y=1;", Then the expression x < y? The result of x++: y++ is:
- Shell变量和引用
猜你喜欢

The.Net webapi uses groupname to group controllers to render the swagger UI

编程式导航路由跳转到当前路由(参数不变), 多次执行会抛出NavigationDuplicated的警告错误?

Backtracking - 46. Full arrangement

Redis主从复制原理

2、 Container_

Redis master-slave replication principle

.NET WebAPI 使用 GroupName 对 Controller 分组呈现 Swagger UI

Detailed explanation of Legendre transformation and conjugate function

Vs code set the method of ctrl+s saving and automatic formatting
![[wechat applet] read the article, data request](/img/9a/3b9aef6c5f5735b886252ec830798c.png)
[wechat applet] read the article, data request
随机推荐
14.2 byte stream learning
VS code 设置Ctrl+S保存,自动格式化的方法
虚拟偶像代言产品出问题谁负责?且听律师分析
全国职业院校技能大赛网络安全B模块wirshark数据包分析 wireshark0051.pcap
Understand test.py in gaitset
【Map】万能的Map使用方法 & 模糊查询的两种方式
食品安全 | 无菌蛋真的完全无菌吗?
Backtracking - 491. Incremental subsequence
How much do you know about the two infrastructures of the badminton stadium?
Food safety | are sterile eggs really completely sterile?
Azure Synapse Analytics 性能优化指南(2)——使用具体化视图优化性能(上)
Data query where
Oracle AWR report script: SQL ordered by elapsed time
什么是回调函数,对于“回”字的理解
回溯——131. 分割回文串
Problems and solutions in the learning process of file class
面试京东T5,被按在地上摩擦,鬼知道我经历了什么?
C语言文件知识点
Data query of MySQL (aggregate function)
.eslintrc.js configuration description