|
本帖最后由 laotang365 于 2014-10-10 10:01 编辑
fb的代码有点大,结构体跳来跳去,只好一行行分析了。
一、先看s5pv210_fb_initial():
void s5pv210_fb_initial(void)
{
struct s5pv210fb_lcd * lcd = &ek070tn93_lcd;//定义一个(s5pv210fb_lcd类型)临时结构体变量lcd,用来初始化s5pv210_fb
if(! clk_get_rate("dsys-hclk", 0))
return;//如果dsys-hclk没有正确配置则退出
if( (lcd->bits_per_pixel != 16) && (lcd->bits_per_pixel != 24) && (lcd->bits_per_pixel != 32) )
return;
s5pv210_fb.lcd = lcd;
……
……
……
memset(&s5pv210_fb.surface.maps, 0, sizeof(struct surface_maps));//map清零,即重置接口函数的映射
surface_set_maps(&s5pv210_fb.surface.maps);//设置图形操作函数的映射
fb_init(&s5pv210_fb);
if(lcd->backlight)
lcd->backlight(255);
}
这里开始给s5pv210_fb.lcd = lcd赋值,s5pv210_fb是什么呢?s5pv210_fb是fb_t类型,它是整个LCD控制的核心,所有LCD操作、控制器配置都要通过s5pv210_fb进行。
struct fb_t
{
/* the framebuffer's surface */
struct surface_t surface;//LCD接口结构体,主要用来操作LCD
/* framebuffer's lcd data */
struct s5pv210fb_lcd * lcd;//LCD配置信息结构体,用来设置相关寄存器、LCD信息。
};
二、看LCD接口结构体surface_t 的定义:
struct surface_t { //LCD接口结构体
/* surface pixel information */
struct pixel_info info;//指定像素的格式
/* surface's width and height */
u32_t w, h;//LCD接口的尺寸
/* pitch of one scan line */
u32_t pitch;//行长,就是LCD宽度啦,对于与800*480的LCD,就是800
/* surface pixels flag */
enum surface_pixels flag;//是否needfree?
/* pointer to pixel data */
void * pixels;//像素指针
/* clipping information */
struct rect_t clip;//修正区域,类型是一个指明左上角位置的矩形
/* surface map functions */
struct surface_maps maps;
/* private data */
void * priv;//之前的数据,还不懂用来干什么
};
三、再看看s5pv210fb_lcd结构体:
struct s5pv210fb_lcd
{
/* horizontal resolution */
s32_t width;
/* vertical resolution */
s32_t height;
/* bits per pixel */
s32_t bits_per_pixel;
/* bytes per pixel */
s32_t bytes_per_pixel;
/* vframe frequency */
s32_t freq;
/* output path */
enum s5pv210fb_output output;
/* rgb mode */
enum s5pv210fb_rgb_mode rgb_mode;
/* bpp mode */
enum s5pv210_bpp_mode bpp_mode;
/* swap flag */
u32_t swap;
struct {
/* red color */
s32_t r_mask;
s32_t r_field;
/* green color */
s32_t g_mask;
s32_t g_field;
/* blue color */
s32_t b_mask;
s32_t b_field;
/* alpha color */
s32_t a_mask;
s32_t a_field;
} rgba;
struct {
/* horizontal front porch */
s32_t h_fp;
/* horizontal back porch */
s32_t h_bp;
/* horizontal sync width */
s32_t h_sw;
/* vertical front porch */
s32_t v_fp;
/* vertical front porch for even field */
s32_t v_fpe;
/* vertical back porch */
s32_t v_bp;
/* vertical back porch for even field */
s32_t v_bpe;
/* vertical sync width */
s32_t v_sw;
} timing;
struct {
/* if 1, video data is fetched at rising edge */
s32_t rise_vclk;
/* if HSYNC polarity is inversed */
s32_t inv_hsync;
/* if VSYNC polarity is inversed */
s32_t inv_vsync;
/* if VDEN polarity is inversed */
s32_t inv_vden;
} polarity;
/* video ram front buffer */
void * vram_front;//不懂干啥的,求解释,看到static u8_t vram[2][800 * 480 * 32 / 8] __attribute__((aligned(4)));vram_front应该是前景显存指针
/* video ram back buffer */
void * vram_back;//不懂干啥的,求解释,后景显存
/* lcd init */
void (*init)(void);//成员函数:初始化背光IO
/* lcd backlight */
void (*backlight)(u8_t brightness);//打开背光成员函数,函数static void lcd_backlight(u8_t brightness)通过IO控制背光电路,brightness为非零值就打开
};
四、surface_maps 结构体
回到第一节,有一个surface_set_maps(&s5pv210_fb.surface.maps);//设置图形操作函数的映射surface_maps 结构体,该结构体封装了LCD的GUI操作函数,画点画线、填充、位块传送、清屏、旋转都在这里了。相关函数在graphic/maps/software.h中声明。
struct surface_maps {
bool_t (*point)(struct surface_t * surface, s32_t x, s32_t y, u32_t c, enum blend_mode mode);//画点函数,blend即混合模式
bool_t (*hline)(struct surface_t * surface, s32_t x0, s32_t y0, u32_t x1, u32_t c, enum blend_mode mode);//画横线
bool_t (*vline)(struct surface_t * surface, s32_t x0, s32_t y0, u32_t y1, u32_t c, enum blend_mode mode);//画竖线
bool_t (*fill)(struct surface_t * surface, struct rect_t * rect, u32_t c, enum blend_mode mode);//填充区域
bool_t (*blit)(struct surface_t * dst, struct rect_t * dst_rect, struct surface_t * src, struct rect_t * src_rect, enum blend_mode mode);//位块传输?求解释
struct surface_t * (*scale)(struct surface_t * surface, struct rect_t * rect, u32_t w, u32_t h);//扫描?求解释
struct surface_t * (*rotate)(struct surface_t * surface, struct rect_t * rect, enum rotate_type type);//旋转,具体实现还没看
};
五、fb_init()函数
回到第一节fb_init(&s5pv210_fb);
传递s5pv210_fb指针,则以下代码的fb都是指s5pv210_fb。
static void fb_init(struct fb_t * fb)
{
struct s5pv210fb_lcd * lcd = (struct s5pv210fb_lcd *)(fb->lcd);//从s5pv210_fb.lcd取出lcd信息
/*
* initial lcd port
* 从帧缓冲结构体s5pv210_fb.lcd获取设置信息,放到临时结构体s5pv210fb_lcd ,用来配置相关寄存器
*/
writel(S5PV210_GPF0CON, 0x22222222);
writel(S5PV210_GPF0DRV, 0xffffffff);
writel(S5PV210_GPF0PUD, 0x0);
writel(S5PV210_GPF1CON, 0x22222222);
writel(S5PV210_GPF1DRV, 0xffffffff);
writel(S5PV210_GPF1PUD, 0x0);
writel(S5PV210_GPF2CON, 0x22222222);
writel(S5PV210_GPF2DRV, 0xffffffff);
writel(S5PV210_GPF2PUD, 0x0);
writel(S5PV210_GPF3CON, (readl(S5PV210_GPF3CON) & ~(0xffff<<0)) | (0x2222<<0));
writel(S5PV210_GPF3DRV, (readl(S5PV210_GPF3DRV) & ~(0xff<<0)) | (0xff<<0));
writel(S5PV210_GPF3PUD, (readl(S5PV210_GPF3PUD) & ~(0xff<<0)) | (0x00<<0));
/*
* lcd init function
*/
if(lcd->init)
lcd->init();//指向lcd_init()函数,函数功能只是将背光IO设置上拉、下拉
/*
* display path selection
*/
writel(S5PV210_DISPLAY_CONTROL, (readl(S5PV210_DISPLAY_CONTROL) & ~(0x3<<0)) | (0x2<<0));
/*
* turn all windows off
*/
writel(S5PV210_WINCON0, (readl(S5PV210_WINCON0) & ~0x1));
……
/*
* turn all windows color map off
*/
writel(S5PV210_WIN0MAP, (readl(S5PV210_WIN0MAP) & ~(1<<24)));
……
/*
* turn all windows color key off
*/
writel(S5PV210_W1KEYCON0, (readl(S5PV210_W1KEYCON0) & ~(3<<25)));
……
/*
* initial lcd controller
*/
s5pv210fb_set_output(lcd);
s5pv210fb_set_display_mode(lcd);
s5pv210fb_display_off(lcd);
s5pv210fb_set_polarity(lcd);
s5pv210fb_set_timing(lcd);
s5pv210fb_set_lcd_size(lcd);
s5pv210fb_set_clock(lcd);
/*
* set lcd video buffer
*/
s5pv210fb_set_buffer_address(lcd, 2);
s5pv210fb_set_buffer_size(lcd, 2);
s5pv210fb_set_window_position(lcd, 2);
s5pv210fb_set_window_size(lcd, 2);
/*
* enable window 2 for main display area
*/
s5pv210fb_window2_enable(lcd);
/*
* display on
*/
s5pv210fb_display_on(lcd);
/*
* wait a moment
*/
mdelay(100);
}
六、其他函数
struct surface_t * s5pv210_screen_surface(void)
{
return &s5pv210_fb.surface;//获取surface指针
}
void s5pv210_screen_swap(void)
{
fb_swap(&s5pv210_fb);/前后景切换
}
void s5pv210_screen_flush(void)
{
fb_flush(&s5pv210_fb);//调用s5pv210fb_set_buffer_address(lcd, 2),求解释
}
void s5pv210_screen_backlight(u8_t brightness)
{
fb_backlight(&s5pv210_fb, brightness);//打开背光
}
static bool_t s5pv210fb_set_output(struct s5pv210fb_lcd * lcd)//配置S5PV210_VIDCON0和S5PV210_VIDCON2寄存器。
{
……………………
}
static bool_t s5pv210fb_set_buffer_address(struct s5pv210fb_lcd * lcd, s32_t id)//好像是将前景显存起止地址装入窗口(id为窗口号,总共5个窗口)?
回家一个一个试验一下。
|
|