概述
这一篇博文承接上一篇博文“系统lcd驱动(-)”(https://blog.csdn.net/Ian22l/article/details/105927936),这篇博文讲的是mtk的lcd驱动一部分。
上一篇讲到在移植或者调试的时候需要填充fb_info对象信息并且进行register_framebuffer进行注册。那么mtk的lcd驱动便是实现这一部分的逻辑。首先从mtkfb_probe进行底层硬件lcd驱动的加载。如下:
代码路径:
drivers/misc/mediatek/video/xxx/videox/mtkfb.c(其中xxx代表某个具体平台,例如mt3561)
static int mtkfb_probe(struct platform_device *pdev)
{
struct mtkfb_device *fbdev = NULL;
struct fb_info *fbi;
......
......
/*申请一块fb_info类型的内存*/
fbi = framebuffer_alloc(sizeof(struct mtkfb_device), &(pdev->dev));
if (!fbi) {
DISPERR("unable to allocate memory for device infon");
r = -ENOMEM;
goto cleanup;
}
mtkfb_fbi = fbi;
fbdev = (struct mtkfb_device *)fbi->par;
fbdev->fb_info = fbi;
fbdev->dev = &(pdev->dev);
dev_set_drvdata(&(pdev->dev), fbdev);
......
......
/*lcd控制器以及lcm模组的初始化*/
primary_display_init(mtkfb_find_lcm_driver(), lcd_fps, is_lcm_inited);
......
......
/*初始化fb_info*/
r = mtkfb_fbinfo_init(fbi);
if (r) {
DISPERR("mtkfb_fbinfo_init fail, r = %dn", r);
goto cleanup;
}
......
......
/*注册fb_info结构体fbi*/
r = register_framebuffer(fbi);
if (r != 0) {
DISPERR("register_framebuffer failedn");
goto cleanup;
}
DISPMSG("register_framebuffer donen");
......
return r;
}
mtk的驱动其实可以分为两条线,一个是初始化fb_info结构体,另外一个是lcm模组的一些初始化。这里我们先说fb_info的初始化,后续会说lcm模组的初始化。
一:fb_info结构体的初始化以及注册
从上面的代码看出,fb_info结构体的初始化主要是通过mtkfb_fbinfo_init进行fb_info对象的填充,然后再通过r = register_framebuffer(fbi);进行注册。这正是我们上一篇博文的结尾所提到的内容。这里我们看下fb_info的初始化主要初始化的内容是什么。
mtkfb_fbinfo_init代码主要内容:
static int mtkfb_fbinfo_init(struct fb_info *info)
{
struct mtkfb_device *fbdev = (struct mtkfb_device *)info->par;
struct fb_var_screeninfo var;
int r = 0;
DISPFUNC();
ASSERT(fbdev->fb_va_base);
/*初始化操作集合*/
info->fbops = &mtkfb_ops;
info->flags = FBINFO_FLAG_DEFAULT;
info->screen_base = (char *)fbdev->fb_va_base;
info->screen_size = fbdev->fb_size_in_byte;
info->pseudo_palette = fbdev->pseudo_palette;
r = fb_alloc_cmap(&info->cmap, 32, 0);
if (r != 0)
DISPERR("unable to allocate color map memoryn");
/* setup the initial video mode (RGB565) */
memset(&var, 0, sizeof(var));
/*初始化可变参数fb_var_screeninfo,例如分辨率*/
var.xres = MTK_FB_XRES;
var.yres = MTK_FB_YRES;
var.xres_virtual = MTK_FB_XRESV;
var.yres_virtual = MTK_FB_YRESV;
DISPMSG(
"mtkfb_fbinfo_init var.xres=%d,var.yres=%d,var.xres_virtual=%d,var.yres_virtual=%dn",
var.xres, var.yres, var.xres_virtual, var.yres_virtual);
/* use 32 bit framebuffer as default */
var.bits_per_pixel = 32;
var.transp.offset = 24;
var.red.length = 8;
/*初始化颜色位域*/
#if 0
var.red.offset = 16;
var.red.length = 8;
var.green.offset = 8;
var.green.length = 8;
var.blue.offset = 0;
var.blue.length = 8;
#else
var.red.offset = 0;
var.red.length = 8;
var.green.offset = 8;
var.green.length = 8;
var.blue.offset = 16;
var.blue.length = 8;
#endif
var.width = DISP_GetActiveWidth();
var.height = DISP_GetActiveHeight();
var.activate = FB_ACTIVATE_NOW;
r = mtkfb_check_var(&var, info);
if (r != 0)
DISPERR("failed to mtkfb_check_varn");
/*将已经初始化好的fb_var_screeninfo对象赋值给info中的var*/
info->var = var;
/*初始化fb_fix_screeninfo*/
r = mtkfb_set_par(info);
if (r != 0)
DISPERR("failed to mtkfb_set_parn");
MSG_FUNC_LEAVE();
return r;
}
fb_info的初始化内核主要是对fb_var_screeninfo以及fb_fix_screeninfo,info->fbops的初始化。
(1)其中fb_var_screeninfo的初始化主要进行分辨率,颜色位域等初始化。
(2)nfo->fbops的初始化:
static struct fb_ops mtkfb_ops = {
.owner = THIS_MODULE,
.fb_open = mtkfb_open,
.fb_release = mtkfb_release,
.fb_setcolreg = mtkfb_setcolreg,
.fb_pan_display = mtkfb_pan_display_proxy,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_cursor = mtkfb_soft_cursor,
.fb_check_var = mtkfb_check_var,
.fb_set_par = mtkfb_set_par,
.fb_ioctl = mtkfb_ioctl,
#ifdef CONFIG_COMPAT
.fb_compat_ioctl = mtkfb_compat_ioctl,
#endif
#if defined(CONFIG_PM_AUTOSLEEP)
.fb_blank = mtkfb_blank,
#endif
};
(3)fb_fix_screeninfo初始化:
/* Switch to a new mode. The parameters for it has been check already by
* mtkfb_check_var.
*/
static int mtkfb_set_par(struct fb_info *fbi)
{
struct fb_var_screeninfo *var = &fbi->var;
struct mtkfb_device *fbdev = (struct mtkfb_device *)fbi->par;
struct fb_overlay_layer fb_layer;
u32 bpp = var->bits_per_pixel;
struct disp_session_input_config *session_input;
struct disp_input_config *input;
/* DISPFUNC(); */
memset(&fb_layer, 0, sizeof(struct fb_overlay_layer));
switch (bpp) {
case 16:
fb_layer.src_fmt = MTK_FB_FORMAT_RGB565;
fb_layer.src_use_color_key = 1;
fb_layer.src_color_key = 0xFF000000;
break;
case 24:
fb_layer.src_use_color_key = 1;
fb_layer.src_fmt = (var->blue.offset == 0) ?
MTK_FB_FORMAT_RGB888 : MTK_FB_FORMAT_BGR888;
fb_layer.src_color_key = 0xFF000000;
break;
case 32:
fb_layer.src_use_color_key = 0;
DISPDBG("set_par,var->blue.offset=%dn", var->blue.offset);
fb_layer.src_fmt = (var->blue.offset == 0) ?
MTK_FB_FORMAT_ARGB8888 : MTK_FB_FORMAT_BGRA8888;
fb_layer.src_color_key = 0;
break;
default:
fb_layer.src_fmt = MTK_FB_FORMAT_UNKNOWN;
DISPWARN("[%s]unsupported bpp: %d", __func__, bpp);
return -1;
}
//初始化fb_fix_screeninfo
set_fb_fix(fbdev);
}
static void set_fb_fix(struct mtkfb_device *fbdev)
{
struct fb_info *fbi = fbdev->fb_info;
struct fb_fix_screeninfo *fix = &fbi->fix;
struct fb_var_screeninfo *var = &fbi->var;
struct fb_ops *fbops = fbi->fbops;
strncpy(fix->id, MTKFB_DRIVER, sizeof(fix->id));
fix->type = FB_TYPE_PACKED_PIXELS;
switch (var->bits_per_pixel) {
case 16:
case 24:
case 32:
fix->visual = FB_VISUAL_TRUECOLOR;
break;
case 1:
case 2:
case 4:
case 8:
fix->visual = FB_VISUAL_PSEUDOCOLOR;
break;
default:
DISPERR("set fb fix fail,bits per pixel=%dn",
var->bits_per_pixel);
return;
}
fix->accel = FB_ACCEL_NONE;
fix->line_length = ALIGN_TO(var->xres_virtual, MTK_FB_ALIGNMENT) *
var->bits_per_pixel / 8;
fix->smem_len = fbdev->fb_size_in_byte;
fix->smem_start = fbdev->fb_pa_base;
fix->xpanstep = 0;
fix->ypanstep = 1;
fbops->fb_fillrect = cfb_fillrect;
fbops->fb_copyarea = cfb_copyarea;
fbops->fb_imageblit = cfb_imageblit;
}
最后
以上就是开心抽屉为你收集整理的linux系统LCD驱动(二):mtk lcd驱动fb_info初始化的全部内容,希望文章能够帮你解决linux系统LCD驱动(二):mtk lcd驱动fb_info初始化所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复