九鼎创展论坛中文版English
登录 | 立即注册 设为首页收藏本站 切换到宽版
查看: 3809|回复: 1
打印 上一主题 下一主题

tester_framebuffer_font ——LCD例程代码分析

[复制链接]
跳转到指定楼层
楼主
发表于 2014-10-9 19:24:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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个窗口)?
回家一个一个试验一下。




回复

使用道具 举报

沙发
 楼主| 发表于 2014-10-10 10:01:31 | 只看该作者
本帖最后由 laotang365 于 2014-10-10 17:11 编辑

void s5pv210_screen_swap(void)//调换s5pv210_fb里的前后景指针,在运行s5pv210_screen_flush之后才能生效
{
        fb_swap(&s5pv210_fb);//切换图层
}

void s5pv210_screen_flush(void)//用s5pv210_fb里的前景指针重设显存地址,相当于刷新一次画面
{
        fb_flush(&s5pv210_fb);//更新图层
}

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳市九鼎创展科技官方论坛 ( 粤ICP备11028681号-2  

GMT+8, 2024-11-22 18:45 , Processed in 0.032959 second(s), 17 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表