log:
代码:
/*
- knowledge/drv/lcd_rgb_driver.c – Atari builtin chipset frame buffer device
- Copyright (C) 2022 leth
- This file is subject to the terms and conditions of the GNU General Public
- License. See the file COPYING in the main directory of this archive
- for more details.
- History:
-
- 2022/08/08: leth: add lcd driver frame
*/
- 2022/08/08: leth: add lcd driver frame
#include <linux/module.h>
#include <linux/fb.h>
#include <linux/errno.h>
#include <linux/dma-mapping.h>
static struct fb_info *stfb_info = NULL;
static struct fb_ops stfp_ops ={
.owner = THIS_MODULE,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
static int __init STD70TFT_drv_init(void)
{
int ret = 0;
dma_addr_t stphy_addr = {0};
pr_info("insmod STD70TFT driver\n");
/*申请分配fb_info*/
stfb_info = framebuffer_alloc(0, NULL);
if (!stfb_info)
{
pr_err("%s +%d:fb_info alloc err", __FILE__, __LINE__);
ret = -ENOMEM;
goto E_INFOMALLOCFAILED;
}
pr_info("%s +%d:---------\n", __FILE__, __LINE__);
/*配置fb_info*/
/*1.1 配置var 分辩率、颜色格式*/
/*xres yres 是可视区间大小,对应着LCD的显示尺寸
xres_virtual yres_virtual定义了framebuffer内存中一帧的尺寸
xres_virtual yres_virtual必须大于或等于xres yres,可以通过pan
操作来显示xres_virtual和yres_virtual定义的显示区域*/
stfb_info->var.xres = 1024;
stfb_info->var.yres = 600;
stfb_info->var.bits_per_pixel = 16;/*rgb565*/
stfb_info->var.red.length = 5;
stfb_info->var.red.offset = 11;
stfb_info->var.green.length = 6;
stfb_info->var.green.offset = 5;
stfb_info->var.blue.length = 5;
stfb_info->var.green.offset = 0;
pr_info("%s +%d:---------\n", __FILE__, __LINE__);
/*配置fix 显存相关 长度、起始地址、类型、*/
stfb_info->fix.smem_len = stfb_info->var.xres * stfb_info->var.yres * stfb_info->var.bits_per_pixel / 8;
if (stfb_info->var.bits_per_pixel == 24)
stfb_info->fix.smem_len = stfb_info->var.xres * stfb_info->var.yres * 4;
pr_info("%s +%d:---------\n", __FILE__, __LINE__);
/*fb的虚拟地址*/
stfb_info->screen_base = dma_alloc_wc(NULL, stfb_info->fix.smem_len, &stphy_addr, GFP_KERNEL);
if (!stfb_info->screen_base)
{
pr_err("%s +%d:dma_alloc_wc err", __FILE__, __LINE__);
ret = -ENOMEM;
goto E_DMA_ALLOC_WC;
}
pr_info("%s +%d:---------\n", __FILE__, __LINE__);
/*fb的物理地址*/
stfb_info->fix.smem_start = stphy_addr;
stfb_info->fix.type = FB_TYPE_PACKED_PIXELS;
stfb_info->fix.visual = FB_VISUAL_DIRECTCOLOR;
/*配置操作方法*/
stfb_info->fbops = &stfp_ops;
pr_info("%s +%d:---------\n", __FILE__, __LINE__);
ret = register_framebuffer(stfb_info);
if (!ret)
{
pr_err("%s +%d:register_framebuffer err ret = %d\n", __FILE__, __LINE__, ret);
goto E_REGISTER_INFO;
}
/*注册fb_info*/
pr_info("%s +%d:---------\n", __FILE__, __LINE__);
return ret;
E_REGISTER_INFO:
dma_free_wc(NULL, stfb_info->fix.smem_len, stfb_info->screen_base, stfb_info->fix.smem_start);
E_DMA_ALLOC_WC:
framebuffer_release(stfb_info);
E_INFOMALLOCFAILED:
return ret;
}
static void __exit STD70TFT_drv_exit(void)
{
pr_info(“rmmod STD70TFT driver\n”);
/反注册fb_info/
unregister_framebuffer(stfb_info);
/*释放内存*/
dma_free_wc(NULL, stfb_info->fix.smem_len, stfb_info->screen_base, stfb_info->fix.smem_start);
/*释放fb_info*/
framebuffer_release(stfb_info);
}
module_init(STD70TFT_drv_init);
module_exit(STD70TFT_drv_exit);
MODULE_LICENSE(“GPL”);