我是靠谱客的博主 优秀导师,最近开发中收集的这篇文章主要介绍7.framebuffer驱动详解1.framebuffer介绍3.framebuffer应用编程实践24.framebuffer应用编程实践35.framebuffer驱动框架总览6.framebuffer驱动框架分析17.framebuffer驱动框架分析28.framebuffer驱动框架分析39.framebuffer驱动分析110.framebuffer驱动分析111.framebuffer驱动分析2使用资源:动态分配虚拟内存12.framebuffer驱动分析313.framebuf,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.framebuffer介绍

1.1、什么是framebuffer
(1)裸机中如何操作LCD
(2)OS下操作LCD的难点
(3)framebuffer帧缓冲(简称fb)是linux内核中虚拟出的一个设备
(4)framebuffer向应用层提供一个统一标准接口的显示设备
(5)从驱动来看,fb是一个典型的字符设备,而且创建了一个类/sys/class/graphics
1.2、framebuffer的使用
(1)设备文件 /dev/fb0
(2)获取设备信息 #include <linux/fb.h>
(3)mmap做映射
(4)填充framebuffer

FrameBuffer的显示缓冲区位于Linux的内核态地址空间中。

而在Linux中,每个应用程序都有自己的虚拟地址空间,在应用程序中是不能直接访问物理,缓冲区地址的。

为此, Linux在文件操作file operations结构中提供了mmap()函数,可将文件的内容映射到用户空间。

对于帧缓冲设备,则可通过映射操作,将屏幕缓冲区(FrameBuffer)的物理地址映射到用户空间的一段虚拟地址中,之后用户就可以通过读写这段虚拟地址访问屏幕缓冲区,在屏幕上绘图。

FrameBuffer与应用程序的交互如图15.1所示。


2.framebuffer应用编程实践1

2.1、打开设备
2.2、获取设备信息
(1)不可变信息FSCREENINFO,使用ioctl的FBIOGET_FSCREENINFO名
(2)可变信息VSCREENINFO,使用ioctl的FBIOGET_VSCREENINFO名


3.framebuffer应用编程实践2

3.1、mmap做映射
做完了mmap后fb在当前进程中就已经就绪了,随时可以去读写LCD显示器了。
3.2、fb显示之刷背景


4.framebuffer应用编程实践3

4.1、设置分辨率
(1)实验失败,实验结果是只能修改虚拟分辨率,不能修改可视分辨率。原因要去驱动里找。
(2)正确的做法是在驱动中去修改参数,然后重新编译运行,才能解决。
4.2、写字、画线、图片显示等


5.framebuffer驱动框架总览

5.1、驱动框架部分
(1)drivers/video/fbmem.c。主要任务:1、创建graphics类、注册FB的字符设备驱动、提供register_framebuffer接口给具体framebuffer驱动编写着来注册fb设备的。本文件相对于fb来说,地位和作用和misc.c文件相对于杂散类设备来说一样的,结构和分析方法也是类似的。
(2)drivers/video/fbsys.c。这个文件是处理fb在/sys目录下的一些属性文件的。
(3)drivers/video/modedb.c。这个文件是管理显示模式(譬如VGA、720P等就是显示模式)的
(4)drivers/video/fb_notify.c
5.2、驱动部分
(1)drivers/video/samsung/s3cfb.c,驱动主体
(2)drivers/video/samsung/s3cfb_fimd6x.c,里面有很多LCD硬件操作的函数
(2)arch/arm/mach-s5pv210/mach-x210.c,负责提供platform_device的
(3)arch/arm/plat-s5p/devs.c,为platform_device提供一些硬件描述信息的
5.3、如何分析
(1)经验
(2)分析menuconfig、Makefile、Kconfig等
(3)内核编译后检查编译结果中的.o文件


6.framebuffer驱动框架分析1

重要结构体:----------------------------------

1. fb_fops

用来实现帧缓冲设备的操作


 

 

 

2. fb_info:

包含了驱动实现的底层函数和设备状态的数据

 

 

3. fb_cmap

结构体记录了一个颜色板信息,也可以叫调色板信息。

用户空间程序可以使明ioctl()函数的FBIOGETCMAP和FBIOPUTCMAP命令读取和设置颜色表的值。struct fb cmap结构体的定义如下:

struct fb_cmap {
__u32 start;
/* 颜色板的第一个元素的入口地址	*/
__u32 len;
/* 元素的个数 */
__u16 *red;
/* 表示红色分量的值	*/
__u16 *green;
__u16 *blue;
__u16 *transp;
/* 透明度分量的值, can be NULL */
};

 

 

4. fb_var_screeninfo

fb_var_screeninfo结构体中存储了用户可以修改的显示控制器参数,例如屏幕分辨率、每个像素的比特数、透明度等。

  1. 该结构体中有几个重要成员需要注意。
  2. xres表示屏幕一行有多少个像素点。
  3. yres表示屏幕一列有多少个像素点。
  4. bits_per_pixel表示每个像素点占用多少个字节。

fb_var_screeninfo结构体的定义如下:

 

5.fb_fix_screeninfo

fb_fix_screeninfo结构体中,记录了用户不能修改的固定显示控制器参数。这些固定参数如缓冲区的物理地址、缓冲区的长度、显示色彩模式、内存映射的开始位置等。

  1. 需要注意的是,
  2. 第07行的visual表示屏幕使用的色彩模式,在Linux下,支持多种色彩模式。
  3. 第11行,表示显存中一行占用的内存字节数,具体占用多少字节由显示模式来决定。
  4. 第15行,保留了6个字节为以后扩充使用。

这个结构体的成员都需要在驱动程序初始化时设置,该结构体的定义代码如下:

 

 

 

参考:

https://blog.csdn.net/jmq_0000/article/details/7104824

 

 

 

 

 

 

 

 

 


7.framebuffer驱动框架分析2

7.1、register_framebuffer
(1)fb驱动框架开放给驱动编写着的注册接口
(2)fb_check_foreignness
(3)remove_conflicting_framebuffers
(4)device_create
(5)fb_init_device
7.2、fb在sysfs中的接口
(1)device_attrs
(2)dev_set_drvdata和dev_get_drvdata


8.framebuffer驱动框架分析3

8.1、fb的mode
(1)什么是mode
(2)fb_var_to_videomode
(3)fb_add_videomode
8.2、注册登记该fb设备
(1)registered_fb[i] = fb_info;
(2)结合fb_read等函数中对fb_info的使用
(3)关键点:数据如何封装、数据由谁准备由谁消费、数据如何传递
8.3、fb_notifier_call_chain


9.framebuffer驱动分析1

9.1、s3cfb.c
(1)注意目录结构的组织
(2)s3cfb_driver
9.2、s3c_device_fb
(1)mach-x210.c中,被使用
(2)devs.c中
(3)resource的定义和作用


10.framebuffer驱动分析1

10.1、probe函数分析

(1)struct s3c_platform_fb    这个结构体是fb的platform_data结构体,这个结构体变量就是platform设备的私有数据,这个数据在platform_device.device.platform_data中存储。在mach文件中去准备并填充这些数据,在probe函数中通过传参的platform_device指针取出来。

struct s3c_platform_fb {
int
hw_ver;
char
clk_name[16];
int
nr_wins;
int
nr_buffers[5];
int
default_win;
int
swap;
phys_addr_t	pmem_start; /* starting physical address of memory region */
size_t
pmem_size; /* size of memory region */
void
*lcd;
void
(*cfg_gpio)(struct platform_device *dev);
int
(*backlight_on)(struct platform_device *dev);
int
(*backlight_onoff)(struct platform_device *dev, int onoff);
int
(*reset_lcd)(struct platform_device *dev);
int
(*clk_on)(struct platform_device *pdev, struct clk **s3cfb_clk);
int
(*clk_off)(struct platform_device *pdev, struct clk **clk);
};

 

 

(2)struct s3cfb_global        这个结构体主要作用是在驱动部分的2个文件(s3cfb.c和s3cfb_fimd6x.c)的函数中做数据传递用的。

struct s3cfb_global {
/* general */
void __iomem
*regs;
struct mutex
lock;
struct device
*dev;
struct clk
*clock;
struct regulator	*regulator;
int
irq;
struct fb_info
**fb;
struct completion	fb_complete;
/* fimd */
int
enabled;
int
dsi;
int
interlace;
enum s3cfb_output_t	output;
enum s3cfb_rgb_mode_t	rgb_mode;
struct s3cfb_lcd	*lcd;
#ifdef CONFIG_HAS_WAKELOCK
struct early_suspend	early_suspend;
struct wake_lock	idle_lock;
#endif
#ifdef CONFIG_CPU_FREQ
struct notifier_block	freq_transition;
struct notifier_block	freq_policy;
#endif
};

(3)struct resource

struct resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
struct resource *parent, *sibling, *child;
};


(4)regulator  电源监控


10.2、重要的platform_data

platform_data的传递过程
(1)to_fb_plat

static int __devinit s3cfb_probe(struct platform_device *pdev)
{
struct s3c_platform_fb *pdata;
struct s3cfb_global *fbdev;
struct resource *res;
int i, j, ret = 0;
pdata = to_fb_plat(&pdev->dev);//取出挂接再device上的私有变量void
*platform_data;
if (!pdata) {
dev_err(fbdev->dev, "failed to get platform datan");
ret = -EINVAL;
goto err_pdata;
}
}


(2)s3cfb_set_platdata     archarmplat-s5pdevs.c

void __init s3cfb_set_platdata(struct s3c_platform_fb *pd)
{
struct s3c_platform_fb *npd;
int i;
if (!pd)
pd = &default_fb_data;
npd = kmemdup(pd, sizeof(struct s3c_platform_fb), GFP_KERNEL);
if (!npd)
printk(KERN_ERR "%s: no memory for platform datan", __func__);
else {
for (i = 0; i < npd->nr_wins; i++)
npd->nr_buffers[i] = 1;
npd->nr_buffers[npd->default_win] = CONFIG_FB_S3C_NR_BUFFERS;
s3cfb_get_clk_name(npd->clk_name);
npd->clk_on = s3cfb_clk_on;
npd->clk_off = s3cfb_clk_off;
/* starting physical address of memory region */
npd->pmem_start = s5p_get_media_memory_bank(S5P_MDEV_FIMD, 1);
/* size of memory region */
npd->pmem_size = s5p_get_media_memsize_bank(S5P_MDEV_FIMD, 1);
s3c_device_fb.dev.platform_data = npd;
//设置了platform_data
}
}


(3)smdkc110_machine_init      archarmmach-s5pv210mach-x210.c

static void __init smdkc110_machine_init(void)
{
/*************
部分省略
**************/
#ifdef CONFIG_FB_S3C_LTE480WV
s3cfb_set_platdata(&lte480wv_fb_data);
#endif
#ifdef CONFIG_FB_S3C_EK070TN93
//我们使用的是这款lcd
smdkv210_backlight_off();
s3cfb_set_platdata(&ek070tn93_fb_data);//调用函数
#endif
}

(4)真正的Platform_data    archarmmach-s5pv210mach-x210.c

static struct s3c_platform_fb ek070tn93_fb_data __initdata = {
.hw_ver	= 0x62,
.nr_wins = 5,
.default_win = CONFIG_FB_S3C_DEFAULT_WINDOW,
.swap = FB_SWAP_WORD | FB_SWAP_HWORD,
.lcd = &ek070tn93,
.cfg_gpio	= ek070tn93_cfg_gpio,
.backlight_on	= ek070tn93_backlight_on,
.backlight_onoff
= ek070tn93_backlight_off,
.reset_lcd	= ek070tn93_reset_lcd,
};
#endif


11.framebuffer驱动分析2

11.1、struct s3cfb_lcd

fbdev->lcd = (struct s3cfb_lcd *)pdata->lcd;
static struct s3c_platform_fb ek070tn93_fb_data __initdata = {
.hw_ver	= 0x62,
.nr_wins = 5,
.default_win = CONFIG_FB_S3C_DEFAULT_WINDOW,
.swap = FB_SWAP_WORD | FB_SWAP_HWORD,
.lcd = &ek070tn93,
.cfg_gpio	= ek070tn93_cfg_gpio,
.backlight_on	= ek070tn93_backlight_on,
.backlight_onoff
= ek070tn93_backlight_off,
.reset_lcd	= ek070tn93_reset_lcd,
};
#endif
static struct s3cfb_lcd ek070tn93 = {
.width = S5PV210_LCD_WIDTH,
//1024
.height = S5PV210_LCD_HEIGHT, //600
.bpp = 32,
.freq = 60,
.timing = {
.h_fp	= 160,
.h_bp	= 140,
.h_sw	= 20,
.v_fp	= 12,
.v_fpe	= 1,
.v_bp	= 20,
.v_bpe	= 1,
.v_sw	= 3,
},
.polarity = {
.rise_vclk = 0,
.inv_hsync = 1,
.inv_vsync = 1,
.inv_vden = 0,
},
};

 

11.2、pdata->cfg_gpio

if (pdata->cfg_gpio)
pdata->cfg_gpio(pdev);
static void ek070tn93_cfg_gpio(struct platform_device *pdev)
{
int i;
for (i = 0; i < 8; i++) {
s3c_gpio_cfgpin(S5PV210_GPF0(i), S3C_GPIO_SFN(2));
//设置CON为0x2
s3c_gpio_setpull(S5PV210_GPF0(i), S3C_GPIO_PULL_NONE);
//设置上升
}
for (i = 0; i < 8; i++) {
s3c_gpio_cfgpin(S5PV210_GPF1(i), S3C_GPIO_SFN(2));
s3c_gpio_setpull(S5PV210_GPF1(i), S3C_GPIO_PULL_NONE);
}
for (i = 0; i < 8; i++) {
s3c_gpio_cfgpin(S5PV210_GPF2(i), S3C_GPIO_SFN(2));
s3c_gpio_setpull(S5PV210_GPF2(i), S3C_GPIO_PULL_NONE);
}
for (i = 0; i < 4; i++) {
s3c_gpio_cfgpin(S5PV210_GPF3(i), S3C_GPIO_SFN(2));
s3c_gpio_setpull(S5PV210_GPF3(i), S3C_GPIO_PULL_NONE);
}
/* mDNIe SEL: why we shall write 0x2 ? */
writel(0x2, S5P_MDNIE_SEL);
/* drive strength to max */
writel(0xffffffff, S5PV210_GPF0_BASE + 0xc);
//将强度提升至最大
writel(0xffffffff, S5PV210_GPF1_BASE + 0xc);
writel(0xffffffff, S5PV210_GPF2_BASE + 0xc);
writel(0x000000ff, S5PV210_GPF3_BASE + 0xc);
}


11.3、pdata->clk_on

    if (pdata->clk_on)  //为空
        pdata->clk_on(pdev, &fbdev->clock);

11.4、resource的处理


(1)platform_device中提供resource结构体数组
(2)probe中platform_get_resource取出resource并且按FLAG分头处理

取出资源:

	fbdev->regulator = regulator_get(&pdev->dev, "pd");
if (!fbdev->regulator) {
dev_err(fbdev->dev, "failed to get regulatorn");
ret = -EINVAL;
goto err_regulator;
}
struct platform_device s3c_device_fb = {
.name
= "s3cfb",
.id
= -1,
.num_resources
= ARRAY_SIZE(s3cfb_resource),
.resource
= s3cfb_resource,
.dev
= {
.dma_mask
= &fb_dma_mask,
.coherent_dma_mask	= 0xffffffffUL
}
};
static struct resource s3cfb_resource[] = {
[0] = {
.start = S5P_PA_LCD,
//0xf800 0000
.end
= S5P_PA_LCD + S5P_SZ_LCD - 1,
//0xf800 0000 - SZ_1M -1
.flags = IORESOURCE_MEM,
//0000 0020
},
[1] = {
.start = IRQ_LCD1,
.end
= IRQ_LCD1,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = IRQ_LCD0,
.end
= IRQ_LCD0,
.flags = IORESOURCE_IRQ,
},
};

使用资源:动态分配虚拟内存

res = request_mem_region(res->start,
res->end - res->start + 1, pdev->name); //注册地址
if (!res) {
dev_err(fbdev->dev, "failed to request io memory regionn");
ret = -EINVAL;
goto err_io;
}
fbdev->regs = ioremap(res->start, res->end - res->start + 1);
//得到虚拟地址
if (!fbdev->regs) {
dev_err(fbdev->dev, "failed to remap io regionn");
ret = -EINVAL;
goto err_mem;
}


12.framebuffer驱动分析3

12.1、一些硬件操作
(1)s3cfb_set_vsync_interrupt
(2)s3cfb_set_global_interrupt
12.2、s3cfb_init_global
12.3、向框架注册该fb设备
(1)s3cfb_alloc_framebuffer
(2)s3cfb_register_framebuffer


13.framebuffer驱动分析4

13.1、一些硬件操作
(1)s3cfb_set_clock
(2)s3cfb_set_window
(3)s3cfb_display_on
13.2、驱动中处理中断
(1)platform_get_irq
(2)request_irq
13.3、logo显示
13.4、backlight点亮


14.应用层为何不能设置分辨率

14.1、问题描述
(1)第4节时试图在应用层设置分辨率失败了,原因何在?
(2)定位问题:肯定是驱动的事儿
(3)进一步驱动中定位:ioctl部分的事儿
14.2、fb的ioctl部分
(1)fb是典型的字符设备驱动
(2)ioctl分为2部分,在驱动框架部分和驱动部分各有一半
(3)一路追踪找问题


15.折腾内核的启动logo

15.1、让logo显示在屏幕中央
15.2、自定义内核启动logo

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

最后

以上就是优秀导师为你收集整理的7.framebuffer驱动详解1.framebuffer介绍3.framebuffer应用编程实践24.framebuffer应用编程实践35.framebuffer驱动框架总览6.framebuffer驱动框架分析17.framebuffer驱动框架分析28.framebuffer驱动框架分析39.framebuffer驱动分析110.framebuffer驱动分析111.framebuffer驱动分析2使用资源:动态分配虚拟内存12.framebuffer驱动分析313.framebuf的全部内容,希望文章能够帮你解决7.framebuffer驱动详解1.framebuffer介绍3.framebuffer应用编程实践24.framebuffer应用编程实践35.framebuffer驱动框架总览6.framebuffer驱动框架分析17.framebuffer驱动框架分析28.framebuffer驱动框架分析39.framebuffer驱动分析110.framebuffer驱动分析111.framebuffer驱动分析2使用资源:动态分配虚拟内存12.framebuffer驱动分析313.framebuf所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(58)

评论列表共有 0 条评论

立即
投稿
返回
顶部