免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 967 | 回复: 0
打印 上一主题 下一主题

LCD驱动学习(一) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-01-01 15:21 |只看该作者 |倒序浏览
S3C2410A LCD的驱动学习
一:首先下载sdk15-S3C2410-tk-20030630.iso
        解压其中的/target/box/linux-2.4.18-rmk7-pxa1-mz4.tar.bz2即可得到kernell 文件
        以下的工作都是基于此文件。
        在/kernel/Documentation/下有许多的说明,其中/kernel/Documentation/fb/下的文件就对写frame buffer
        很有用。
(1)   从framebuffer.txt中提取的要点:
        1:frame buffer 是一个字符设备,他的之设备号是29,次设备号用来指定frame buffer 的序号,可以有多个             frame buffer (0-31)同时存在。
             frame buffer 设备也可以看作是普通的存储器,这也就是说你可以读写其内容。例如:
              cp /dev/fb0 myfile
            应用程序默认的frame buffer 是/dev/fb0,你也可以通过设置环境变量来设置他。例如:
              export FRAMEBUFFER=/dev/fb1
        2:/dev/fb*也允许 ioctls on  it 通过ioctls 可以查询和设置硬件的信息。颜色映射就是通过他来工作的。
        3 :frame buffer 分辨率的管理
               frame buffer 分辨率的管理是通过fbset来实现的,fbset 的主要作用就是来改变当前的图像模式。
               fbset 使用的是存储在配置文件里的图像模式数据库,因此你也可以添加你自己的模式。      
        其他的信息都是关于显示原理和时序的,看LCD 的手册即可。
(2)从internals.txt中提取的信息
         
1. Outside the kernel (user space)
  - struct fb_fix_screeninfo
    Device independent unchangeable information about a frame buffer device and
    a specific video mode. This can be obtained using the FBIOGET_FSCREENINFO    ioctl.
  - struct fb_var_screeninfo
    Device independent changeable information about a frame buffer device and a
    specific video mode. This can be obtained using the FBIOGET_VSCREENINFO    ioctl, and updated with the FBIOPUT_VSCREENINFO ioctl. If you want to pan
    the screen only, you can use the FBIOPAN_DISPLAY ioctl.
  - struct fb_cmap
    Device independent colormap information. You can get and set the colormap    using the FBIOGETCMAP and FBIOPUTCMAP ioctls.
2. Inside the kernel
  - struct fb_info
    Generic information, API and low level information about a specific frame    buffer device instance (slot number, board address, ...).
  - struct `par'
    Device dependent information that uniquely defines the video mode for this
    particular piece of hardware.
  - struct display
    Interface between the frame buffer device and the console driver.
(3)从modedb.txt中提取的信息
     Valid mode specifiers (mode_option argument):
    x[-][@]
    [-][@]
To find a suitable video mode, you just call
int __init fb_find_mode(struct fb_var_screeninfo *var,
                        struct fb_info *info, const char *mode_option,
                        const struct fb_videomode *db, unsigned int dbsize,
                        const struct fb_videomode *default_mode,
                        unsigned int default_bpp)
To specify a video mode at bootup, use the following boot options:
    video=:x[-][@refresh]
二:frame buffer 架构
        在/kernel/driver/vedio/skeletonfb.c中给出了fb的架构
       内容如下:
/*
* linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
*
*  Created 28 Dec 1997 by Geert Uytterhoeven
*
* 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.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
    /*
     *  This is just simple sample code.
     *
     *  No warranty that it actually compiles.
     *  Even less warranty that it actually works :-)
     */
struct xxxfb_info {
    /*
     *  Choose _one_ of the two alternatives:
     *
     *    1. Use the generic frame buffer operations (fbgen_*).
     */
    struct fb_info_gen gen;
    /*
     *    2. Provide your own frame buffer operations.
     */
    struct fb_info info;
    /* Here starts the frame buffer device dependent part */
    /* You can use this to store e.g. the board number if you support */
    /* multiple boards */
};
struct xxxfb_par {
    /*
     *  The hardware specific data in this structure uniquely defines a video
     *  mode.
     *
     *  If your hardware supports only one video mode, you can leave it empty.
     */
};
    /*
     *  If your driver supports multiple boards, you should make these arrays,
     *  or allocate them dynamically (using kmalloc()).
     */
static struct xxxfb_info fb_info;
static struct xxxfb_par current_par;
static int current_par_valid = 0;
static struct display disp;
static struct fb_var_screeninfo default_var;
static int currcon = 0;
static int inverse = 0;
int xxxfb_init(void);
int xxxfb_setup(char*);
/* ------------------- chipset specific functions -------------------------- */
static void xxx_detect(void)
{
    /*
     *  This function should detect the current video mode settings and store
     *  it as the default video mode
     */
    struct xxxfb_par par;
    /* ... */
    xxx_get_par(&par);
    xxx_encode_var(&default_var, &par);
}
static int xxx_encode_fix(struct fb_fix_screeninfo *fix, struct xxxfb_par *par,
              const struct fb_info *info)
{
    /*
     *  This function should fill in the 'fix' structure based on the values
     *  in the `par' structure.
     */
    /* ... */
    return 0;
}
static int xxx_decode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par,
              const struct fb_info *info)
{
    /*
     *  Get the video params out of 'var'. If a value doesn't fit, round it up,
     *  if it's too big, return -EINVAL.
     *
     *  Suggestion: Round up in the following order: bits_per_pixel, xres,
     *  yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
     *  bitfields, horizontal timing, vertical timing.
     */
    /* ... */
    /* pixclock in picos, htotal in pixels, vtotal in scanlines */
    if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
        return -EINVAL;
    return 0;
}
static int xxx_encode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par,
              const struct fb_info *info)
{
    /*
     *  Fill the 'var' structure based on the values in 'par' and maybe other
     *  values read out of the hardware.
     */
    /* ... */
    return 0;
}
static void xxx_get_par(struct xxxfb_par *par, const struct fb_info *info)
{
    /*
     *  Fill the hardware's 'par' structure.
     */
    if (current_par_valid)
    *par = current_par;
    else {
    /* ... */
    }
}
static void xxx_set_par(struct xxxfb_par *par, const struct fb_info *info)
{
    /*
     *  Set the hardware according to 'par'.
     */
    current_par = *par;
    current_par_valid = 1;
    /* ... */
}
static int xxx_getcolreg(unsigned regno, unsigned *red, unsigned *green,
             unsigned *blue, unsigned *transp,
             const struct fb_info *info)
{
    /*
     *  Read a single color register and split it into colors/transparent.
     *  The return values must have a 16 bit magnitude.
     *  Return != 0 for invalid regno.
     */
    /* ... */
    return 0;
}
static int xxx_setcolreg(unsigned regno, unsigned red, unsigned green,
             unsigned blue, unsigned transp,
             const struct fb_info *info)
{
    /*
     *  Set a single color register. The values supplied have a 16 bit
     *  magnitude.
     *  Return != 0 for invalid regno.
     */
    if (regno > 1) |
                     ((green & 0xf800) >> 6) |
                     ((blue & 0xf800) >> 11);
    if (is_cfb16)        /* RGB 565 */
        ...fbcon_cmap.cfb16[regno] = (red & 0xf800) |
                     ((green & 0xfc00) >> 5) |
                     ((blue & 0xf800) >> 11);
    if (is_cfb24)        /* RGB 888 */
        ...fbcon_cmap.cfb24[regno] = ((red & 0xff00) > 8);
    if (is_cfb32)        /* RGBA 8888 */
        ...fbcon_cmap.cfb32[regno] = ((red & 0xff00) > 8);
    }
    /* ... */
    return 0;
}
static int xxx_pan_display(struct fb_var_screeninfo *var,
               struct xxxfb_par *par, const struct fb_info *info)
{
    /*
     *  Pan (or wrap, depending on the `vmode' field) the display using the
     *  `xoffset' and `yoffset' fields of the `var' structure.
     *  If the values don't fit, return -EINVAL.
     */
    /* ... */
    return 0;
}
static int xxx_blank(int blank_mode, const struct fb_info *info)
{
    /*
     *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
     *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
     *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
     *  to e.g. a video mode which doesn't support it. Implements VESA suspend
     *  and powerdown modes on hardware that supports disabling hsync/vsync:
     *    blank_mode == 2: suspend vsync
     *    blank_mode == 3: suspend hsync
     *    blank_mode == 4: powerdown
     */
    /* ... */
    return 0;
}
static void xxx_set_disp(const void *par, struct display *disp,
             struct fb_info_gen *info)
{
    /*
     *  Fill in a pointer with the virtual address of the mapped frame buffer.
     *  Fill in a pointer to appropriate low level text console operations (and
     *  optionally a pointer to help data) for the video mode `par' of your
     *  video hardware. These can be generic software routines, or hardware
     *  accelerated routines specifically tailored for your hardware.
     *  If you don't have any appropriate operations, you must fill in a
     *  pointer to dummy operations, and there will be no text output.
     */
    disp->screen_base = virtual_frame_buffer_address;
#ifdef FBCON_HAS_CFB8
    if (is_cfb8) {
    disp->dispsw = fbcon_cfb8;
    } else
#endif
#ifdef FBCON_HAS_CFB16
    if (is_cfb16) {
    disp->dispsw = fbcon_cfb16;
    disp->dispsw_data = ...fbcon_cmap.cfb16;    /* console palette */
    } else
#endif
#ifdef FBCON_HAS_CFB24
    if (is_cfb24) {
    disp->dispsw = fbcon_cfb24;
    disp->dispsw_data = ...fbcon_cmap.cfb24;    /* console palette */
    } else
#endif
#ifdef FBCON_HAS_CFB32
    if (is_cfb32) {
    disp->dispsw = fbcon_cfb32;
    disp->dispsw_data = ...fbcon_cmap.cfb32;    /* console palette */
    } else
#endif
    disp->dispsw = &fbcon_dummy;
}
/* ------------ Interfaces to hardware functions ------------ */
struct fbgen_hwswitch xxx_switch = {
    xxx_detect, xxx_encode_fix, xxx_decode_var, xxx_encode_var, xxx_get_par,
    xxx_set_par, xxx_getcolreg, xxx_setcolreg, xxx_pan_display, xxx_blank,
    xxx_set_disp
};
/* ------------ Hardware Independent Functions ------------ */
    /*
     *  Initialization
     */
int __init xxxfb_init(void)
{
    fb_info.gen.fbhw = &xxx_switch;
    fb_info.gen.fbhw->detect();
    strcpy(fb_info.gen.info.modename, "XXX");
    fb_info.gen.info.changevar = NULL;
    fb_info.gen.info.node = -1;
    fb_info.gen.info.fbops = &xxxfb_ops;
    fb_info.gen.info.disp = &disp;
    fb_info.gen.info.switch_con = &xxxfb_switch;
    fb_info.gen.info.updatevar = &xxxfb_update_var;
    fb_info.gen.info.blank = &xxxfb_blank;
    fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
    /* This should give a reasonable default video mode */
    fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
    fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
    fbgen_set_disp(-1, &fb_info.gen);
    fbgen_install_cmap(0, &fb_info.gen);
    if (register_framebuffer(&fb_info.gen.info) fb_open */
static int xxxfb_open(const struct fb_info *info, int user)
{
    return 0;
}
/* If all you need is that - just don't define ->fb_release */
static int xxxfb_release(const struct fb_info *info, int user)
{
    return 0;
}
    /*
     *  In most cases the `generic' routines (fbgen_*) should be satisfactory.
     *  However, you're free to fill in your own replacements.
     */
static struct fb_ops xxxfb_ops = {
    owner:        THIS_MODULE,
    fb_open:    xxxfb_open,    /* only if you need it to do something */
    fb_release:    xxxfb_release, /* only if you need it to do something */
    fb_get_fix:    fbgen_get_fix,
    fb_get_var:    fbgen_get_var,
    fb_set_var:    fbgen_set_var,
    fb_get_cmap:    fbgen_get_cmap,
    fb_set_cmap:    fbgen_set_cmap,
    fb_pan_display:    fbgen_pan_display,
    fb_ioctl:    xxxfb_ioctl,   /* optional */
};
/* ------------------------------------------------------------------------- */
    /*
     *  Modularization
     */
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
    return xxxfb_init();
}
void cleanup_module(void)
{
    xxxfb_cleanup(void);
}
#endif /* MODULE */
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/56796/showart_454311.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP