s5pv210,lcd驱动,x210,驱动



#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>

#include <plat/gpio-cfg.h>

#include <mach/regs-gpio.h>
#include <mach/regs-irq.h>
#include <mach/regs-clock.h>
#include <linux/gpio.h>

#include <asm/io.h>
#include <asm/div64.h>

#include <asm/mach/map.h>
#include <mach/regs-gpio.h>

static struct fb_info *x210_fb_info;
static u32 pseudo_pal[16];

static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
{
 chan &= 0xffff;
 chan >>= 16 - bf->length;
 return chan << bf->offset;
}

static int x210_lcdfb_setcolreg(unsigned int regno, unsigned int red,
        unsigned int green, unsigned int blue,
        unsigned int transp, struct fb_info *info)
{
 unsigned int val;
 
 if (regno > 16)
  return 1;

 /* 用red,green,blue三原色构造出val */
 val  = chan_to_field(red, &info->var.red);
 val |= chan_to_field(green, &info->var.green);
 val |= chan_to_field(blue, &info->var.blue);
 
 //((u32 *)(info->pseudo_palette))[regno] = val;
 pseudo_pal[regno] = val;
 return 0;
}


struct fb_ops s3cfb_ops = {
 .owner = THIS_MODULE,
       .fb_setcolreg = x210_lcdfb_setcolreg,
       .fb_fillrect = cfb_fillrect,
 .fb_copyarea = cfb_copyarea, 
 .fb_imageblit = cfb_imageblit,
};

void lcd_gpio_init(void)
{
 int i;
        /*RGB引脚*/
 for (i = 0; i < 8; i++) {
  s3c_gpio_cfgpin(S5PV210_GPF0(i), S3C_GPIO_SFN(2));
  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);

      /*设置背光灯*/
       s3c_gpio_cfgpin(S5PV210_GPD0(0), S3C_GPIO_OUTPUT);
 s3c_gpio_setpull(S5PV210_GPD0(0), S3C_GPIO_PULL_UP);
 gpio_set_value(S5PV210_GPD0(0), 0);

      /* backlight enable pin */
 s3c_gpio_cfgpin(S5PV210_GPF3(5), S3C_GPIO_OUTPUT);
 s3c_gpio_setpull(S5PV210_GPF3(5), S3C_GPIO_PULL_UP);
 gpio_set_value(S5PV210_GPF3(5), 1);

       /* LCD_5V */
 s3c_gpio_cfgpin(S5PV210_GPH0(5), S3C_GPIO_OUTPUT);
 s3c_gpio_setpull(S5PV210_GPH0(5), S3C_GPIO_PULL_UP);
 gpio_set_value(S5PV210_GPH0(5), 1);

 /* LCD_33 */
 s3c_gpio_cfgpin(S5PV210_GPH2(0), S3C_GPIO_OUTPUT);
 s3c_gpio_setpull(S5PV210_GPH2(0), S3C_GPIO_PULL_DOWN);
 gpio_set_value(S5PV210_GPH2(0), 0);

 /* wait a moment */
 mdelay(200);

   
}


typedef  struct s5pv_lcd_reg{
     volatile unsigned int VIDCON0;
     volatile unsigned int VIDCON1;
     volatile unsigned int VIDCON2;
     volatile unsigned int VIDCON3;
     volatile unsigned int VIDTCON0;
     volatile unsigned int VIDTCON1;
     volatile unsigned int VIDTCON2;
     volatile unsigned int VIDTCON3;
 }*PT_s5pv_lcd_reg;


static PT_s5pv_lcd_reg pt_s5pv_lcd_reg;
static unsigned int lcd_mem_size;
static unsigned int lcd_mem;
static unsigned char *lcd_var_mem;
//0xF800_0034
static volatile unsigned int *SHADOWCON;
//0xF800_0028
static volatile unsigned int *WINCON2;
//0xF800_0060
static volatile unsigned int *VIDOSD2A;
//0xF800_0064
static volatile unsigned int *VIDOSD2B;
//0xF800_0068
static volatile unsigned int *VIDOSD2C;
//0xF800_00B0
static volatile unsigned int *VIDW02ADD0B0;
//0xF800_00E0
static volatile unsigned int *VIDW02ADD1B0;
//0xF800_0108
static volatile unsigned int *VIDW02ADD2;

static volatile unsigned int *DISPLAY_PATH_SEL ;

static struct clk *clk;

void reg_ioremap(void)
{
    SHADOWCON       = ioremap(0xF8000034,4);
    WINCON2            = ioremap(0xF8000028,4);
    VIDOSD2A           = ioremap(0xF8000060,4);
    VIDOSD2B           = ioremap(0xF8000064,4);
    VIDOSD2C           = ioremap(0xF8000068,4);
    VIDW02ADD0B0   = ioremap(0xF80000B0,4);
    VIDW02ADD1B0  =  ioremap(0xF80000E0,4);
    VIDW02ADD2      =  ioremap(0xF8000108,4);
    DISPLAY_PATH_SEL =ioremap(0xE0107008,4);
}
static int x210_lcd_init(void)
{
    
       /*分配fb_info*/
      
      x210_fb_info=framebuffer_alloc(0, NULL);
      
      strcpy(x210_fb_info->fix.id, "mylcd");

      x210_fb_info->fbops = &s3cfb_ops;
     
       /*分配固定参数*/
      x210_fb_info->fix.smem_len    = 1024*600*32/8;
      x210_fb_info->fix.type            = FB_TYPE_PACKED_PIXELS;
      x210_fb_info->fix.visual          =FB_VISUAL_TRUECOLOR;
      x210_fb_info->fix.line_length   =1024*4;
        /*设置可变参数*/
      x210_fb_info->var.xres               = 1024;
      x210_fb_info->var.yres               = 600;
      x210_fb_info->var.xres_virtual     = 1024;
      x210_fb_info->var.yres_virtual     = 600;
      x210_fb_info->var.bits_per_pixel  =32;
     
       /*设置RGB偏移值参数*/
     x210_fb_info->var.red.offset= 16;
     x210_fb_info->var.red.length       = 8;
     x210_fb_info->var.green.offset    = 8;
     x210_fb_info->var.green.length   = 8;
     x210_fb_info->var.blue.offset      = 0;
     x210_fb_info->var.blue.length     = 8;

     x210_fb_info->var.activate        = FB_ACTIVATE_NOW;

     /*设置其他参数*/
     x210_fb_info->pseudo_palette  = &pseudo_pal;

     x210_fb_info->screen_size   = 1024*600*32/8;
 
     /*初始化GPIO*/
     lcd_gpio_init();
    
     reg_ioremap();

     /*使能lcd控制器时钟*/
     clk = clk_get(NULL,"lcd");
     if (IS_ERR(clk)) {
  printk("can't get clock \n");
  return PTR_ERR(clk);
 }
     clk_enable(clk);

        //11: RGB=FIMD I80=FIMD ITU=FIMD
       *DISPLAY_PATH_SEL = (2<<0);
    
       /* C2_EN_F  [2] 1
     *
     */
     *SHADOWCON = (1<<2);
     /*  OSD_LeftTopX_F  [21:11]
    *  OSD_LeftTopY_F  [10:0]
    */
     *VIDOSD2A     = 0x00000000;  
     /* OSD_RightBotX_F  [21:11]
    * OSD_RightBotY_F  [10:0]
    */
     *VIDOSD2B     = (1023<<11)  |(599<<0) ;

    
     *VIDOSD2C     =(1024-1)*(600-1);


     /*设置lcd控制器参数*/
 
      /*分配显存*/
     lcd_mem_size =1024*600*32/8;
     lcd_var_mem=dma_alloc_writecombine(NULL,lcd_mem_size,(dma_addr_t *) &x210_fb_info->fix.smem_start, GFP_KERNEL);
     if(lcd_var_mem == NULL){
            printk("can't alloc lcd mem !\n");
        }

     printk("lcd mem phy address 0x%x \n",x210_fb_info->fix.smem_start);
    
     x210_fb_info->screen_base =    lcd_var_mem;
    
     lcd_mem                    =  x210_fb_info->fix.smem_start;
     /*把显存的地址告诉控制器*/
     /*start address*/
     *VIDW02ADD0B0   =  lcd_mem;
     /*end address*/
     *VIDW02ADD1B0   =  lcd_mem+lcd_mem_size;
     /*mem size
    *OFFSIZE_F    [25:13]
    *PAGEWIDTH_F  [12:0]
    */
     //*VIDW02ADD2

     pt_s5pv_lcd_reg =(PT_s5pv_lcd_reg)ioremap(0xF8000000, 4*8);
     if(pt_s5pv_lcd_reg == NULL){
            printk("lcd ioremap error \n");
        }

       /*IVCLK   7  0  Video data is fetched at VCLK falling edge
     *IHSYNC  6  1  1 = Inverted
     *IVSYNC  5  1  1 = Inverted
     *IVDEN   4
     */
      pt_s5pv_lcd_reg->VIDCON1 = (1<<6) | (1<<5);

      /* RGB_SKIP_EN 0  0 = Disables
     *这个暂时不设置
    */
      //pt_s5pv_lcd_reg->VIDCON2 =
      /*
     *CG_ON 18  Enables Control Color Gain.
     */

      //by quan

     
     // pt_s5pv_lcd_reg->VIDCON3 = (1<<18);
      /* timing
     *VBPD  [23:16]  18-1 = 21
     *VFPD  [15:8]   22-1 = 17
     *VSPW  [7:0]    1-1  =0
     */
      pt_s5pv_lcd_reg->VIDTCON0 = (21<<16) |(17<<8);

      /* timing
     *HBPD  [23:16]  45-1 = 44
     *HFPD  [15:8]   100-1 = 99
     *HFPD  [7:0]    1-1  =0
     */
       pt_s5pv_lcd_reg->VIDTCON1 = (44<<16) | (99<<8);
      /*  LINEVAL [21:11] 600 -1 599
     *  HOZVAL  [10:0] 1024 -1 1023
     */
      pt_s5pv_lcd_reg->VIDTCON2  = (599<<11) |(1023<<0);
     /* [31] 1 = Enables   Enables VSYNC Signal Output.
    *
    */
    pt_s5pv_lcd_reg->VIDTCON3  = (1<<31);
  
     /*
    * VIDOUT  [28:26] 000  RGB interface
    * RGSPSEL [18]      0  RGB parallel format
    * CLKVAL_F[13:6]  3    设置为4分频
    * CLKDIR  [4]     1    1 = Divided by CLKVAL_F
    *CLKSEL_F         0    0 = HCLK
    *ENVID    使能位  1
    *ENVID_F  使能位  1
    */
     pt_s5pv_lcd_reg->VIDCON0 = (3<<6) | (1<<4) |(1<<1) |(1<<0);


     //by quan

    
       /*WSWP_F    [15]     1 = Swap Enable
    *BPPMODE_F  [5:2]    1011
    *ENWIN_F    [0]      1 = Enables the video output and video control signal.
    */
     *WINCON2      =  (1<<15) |(11<<2) |(1<<0);

      register_framebuffer(x210_fb_info);
        
}

static void x210_lcd_exit(void)
{
    iounmap(SHADOWCON);
    iounmap(WINCON2);
    iounmap(VIDOSD2A);
    iounmap(VIDOSD2B);
    iounmap(VIDOSD2C);
    iounmap(VIDW02ADD0B0);
    iounmap(VIDW02ADD1B0);
    iounmap(VIDW02ADD2);
    iounmap(DISPLAY_PATH_SEL);
    iounmap(pt_s5pv_lcd_reg);
   
    framebuffer_release(x210_fb_info);
    dma_free_writecombine(NULL,lcd_mem_size,&lcd_mem,GFP_KERNEL);
    unregister_framebuffer(x210_fb_info);
   
    clk_put(clk);
}


module_init(x210_lcd_init);
module_exit(x210_lcd_exit);

MODULE_LICENSE("GPL");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值