免费注册 查看新帖 |

Chinaunix

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

TFT屏 不显示彩色,只显示黑白色 不 知道怎么回事 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-10-09 15:29 |只看该作者 |倒序浏览
我刚写的TFT屏驱动,但是不显示彩色 ,只显示黑白色,不知道是怎么回事
那位兄弟 知道告诉我一下。


#define NR_PALETTE        256


#define LCD_WIDTH   320       
#define LCD_HEIGHT        240
#define LCDM_TIMER        25
//#define LCDM_TIMER         (HZ / 50)       

#define _CS     37
#define _RES    38
#define RegSel   36
#define _WR     40
#define _RD     39

#define DB0     24
#define DB1     25
#define DB2     26
#define DB3     27
#define DB4     28
#define DB5     29
#define DB6     30
#define DB7     31


#define FBIOSTOPTIMER        0x4680
#define FBIOSTARTTIMER        0x4681
#define FBIOREFRESH        0x4682
#define FBIOSLIGHT        0x4683
//#define DISPLAY_UPDOWN


void        gpio_init(void)
{
        __gpio_as_output(_CS);
        __gpio_as_output(_RES);
        //__gpio_as_output(RS);
        __gpio_as_output(_WR);
        __gpio_as_output(_RD);
    __gpio_set_pin(_RD);
        __gpio_as_output(RegSel);
        __gpio_as_output(DB0);
        __gpio_as_output(DB1);
        __gpio_as_output(DB2);
        __gpio_as_output(DB3);
        __gpio_as_output(DB4);
        __gpio_as_output(DB5);
        __gpio_as_output(DB6);
        __gpio_as_output(DB7);
       
}
u8  Set_F500[]={4,0x83,0x00,0xf5,0x00}; // Reg[f500]=00 (internal MCS0 cycle pulse width)
u8  Set_F504[]={4,0x83,0x04,0xf5,0x04}; // Reg[f504]=04 (internal MCS1 pulse width)
u8  Set_F505[]={4,0x83,0x05,0xf5,0x80}; // Reg[f505]=80 (internal MCS1 memory accessing setting)

u8  Set_F6C4[]={4,0x83,0xc4,0xf6,0x10}; // Reg[f505]=80 Set Memory Clock Divide

u8  Set_F080[]={4,0x83,0x80,0xf0,0xfc}; // Reg[f080]=fc (16bpp TFT)
u8  Set_F08E[]={4,0x83,0x8e,0xf0,0x32}; // Reg[f08e]=32 (set pixel clock and LCD_ON)

u8  Set_F090[]={4,0x83,0x90,0xf0,0x14}; // set the LCD charactics
u8  Set_F091[]={4,0x83,0x91,0xf0,0x25};
u8  Set_F092[]={4,0x83,0x92,0xf0,0x1e};
u8  Set_F094[]={4,0x83,0x94,0xf0,0x05};
u8  Set_F095[]={4,0x83,0x95,0xf0,0x0e};
u8  Set_F096[]={4,0x83,0x96,0xf0,0x03};
u8  Set_8F[]={7,0x8f,0x69,0x45,0x61,0x67,0x6c,0x65};

void lcdbus_init(u8 command)
{
    if(command&0x01)
        __gpio_set_pin(DB0);
    else
        __gpio_clear_pin(DB0);

    if((command>>1)&0x01)
        __gpio_set_pin(DB1);
    else
        __gpio_clear_pin(DB1);

    if((command>>2)&0x01)
        __gpio_set_pin(DB2);
    else
        __gpio_clear_pin(DB2);

    if((command>>3)&0x01)
        __gpio_set_pin(DB3);
    else
        __gpio_clear_pin(DB3);

    if((command>>4)&0x01)
        __gpio_set_pin(DB4);
    else
        __gpio_clear_pin(DB4);

    if((command>>5)&0x01)
        __gpio_set_pin(DB5);
    else
        __gpio_clear_pin(DB5);
   
    if((command>>6)&0x01)
        __gpio_set_pin(DB6);
    else
        __gpio_clear_pin(DB6);

    if((command>>7)&0x01)
        __gpio_set_pin(DB7);
    else
        __gpio_clear_pin(DB7);
}

void SdCmd(u8 Command)      //send command
{
   __gpio_clear_pin(RegSel);        //A1 = 0;                   // init all control signal
   lcdbus_init(Command);
    __gpio_clear_pin(_CS);       //_CS = 0;                  // enable the access
    __gpio_clear_pin(_WR);      //_WR = 0;
    __gpio_set_pin(_WR);     //_WR = 1;
    __gpio_set_pin(_CS);     //_CS = 1;                  // disable the access
}
void CmdEnd()               //send command
{
  __gpio_set_pin(RegSel);     //A1 = 1;                   // init all control signal
  lcdbus_init(0x01);       // = 1;
  __gpio_clear_pin(_CS);      //_CS = 0;                // enable the access
  __gpio_clear_pin(_WR);      //_WR = 0;
  __gpio_set_pin(_WR);       //_WR = 1;
  __gpio_set_pin(_CS);        //_CS = 1;                // disable the access
}
void WritePKG(u8 *pkg) // send a command package
{
  u8 i;
for(i=*pkg;i;i--)
         SdCmd(*(++pkg));
     CmdEnd();
    mdelay(2);      //(unsigned long usec)//delayms(2);
}

void lcdm_chip_reset(void)
{
      gpio_init();
      lcdbus_init(0xff);    // init all the port
    __gpio_set_pin(_CS);               
    __gpio_set_pin(_RES);
    __gpio_clear_pin(RegSel);//A=0       
    __gpio_set_pin(_WR);               

    __gpio_clear_pin(_RES);         udelay(100000);        //_RES=1; mdelay(10);
    __gpio_set_pin(_RES);        udelay(500000);            //_RES=1; mdelay(10);
   
     WritePKG(Set_F500);
     WritePKG(Set_F504); WritePKG(Set_F505);
     WritePKG(Set_F6C4);
     WritePKG(Set_F080); WritePKG(Set_F08E);
     WritePKG(Set_F090); WritePKG(Set_F091);
     WritePKG(Set_F092); WritePKG(Set_F094);
     WritePKG(Set_F095); WritePKG(Set_F096);
     WritePKG(Set_8F);
   
}

static void write_data(u8 data)   //send command
{
    __gpio_set_pin(RegSel);                //RS = 1;     init all control signal
    lcdbus_init(data);
    __gpio_clear_pin(_CS);         //_CS = 0;        enable the access
    __gpio_clear_pin(_WR);        //_WR = 0;
    __gpio_set_pin(_WR);                //_WR = 1;
    __gpio_set_pin(_CS);                //_CS = 1;        disable the access
}


static int write_screen(u16 *displaydata)        // displaydata should be (240x160)/8 = 4800byte
{   

int x,y;
u16  temp=*displaydata;
printk("temp=%x\n",temp);
unsigned  char  a,b;
       //    a=*buffer-*bufer>>7;
                        //        b=*bufer>>7;
                          a=temp>>8;
                          //b=temp&0xff00;
                          b=temp&0x00ff;
                          printk("### tmp %x, a %x, b %x\n", temp, a, b);
                          write_data(b);
                        write_data(a);
                          // CmdEnd();
//        }
  //  }
               



        return 0;
}

struct lcd_cfb_info {
        struct fb_info                fb;
//        struct display_switch        *dispsw;
        signed int                currcon;
        int                        func_use_count;

        struct {
                u16 red, green, blue;
        } palette[NR_PALETTE];
#ifdef CONFIG_PM
        struct pm_dev                *pm;
#endif
};

static volatile unsigned char *shadow_buf;
static volatile unsigned char *backup_buf;
static struct timer_list lcdm_timer;

static void update_lcd(unsigned long dummy)
{
        int i;
        int dirty = 0;
        unsigned int *tmp = (unsigned int *)shadow_buf;
//        unsigned int *ptr = (unsigned int *)backup_buf;
#if 0
        for(i=0;i<(LCD_WIDTH * LCD_HEIGHT)/32;i++)
        {                if(*(tmp+i) != *(ptr+i))
                        *(ptr+i) = *(tmp+i);
                        dirty = 1;
                }

        if(dirty)
    write_screen((unsigned char *)backup_buf);
#endif
    write_screen((unsigned char   *)shadow_buf);
        init_timer(&lcdm_timer);
        lcdm_timer.expires = jiffies + LCDM_TIMER;
        lcdm_timer.data = 0;
        lcdm_timer.function = update_lcd;
        add_timer(&lcdm_timer);
}

static int lcdm_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                              u_int transp, struct fb_info *info)
{
        struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info;
        unsigned short ctmp;

        if (regno >= NR_PALETTE)
                return 1;
/*
        cfb->palette[regno].red                = red ;
        cfb->palette[regno].green        = green;
        cfb->palette[regno].blue        = blue;
*/
//        if(cfb->fb.var.bits_per_pixel <=16) //
//{
   u32 v;
   if(regno >=16)
           return 1;
   

   v = (red << cfb->fb.var.red.offset) |
           (green << cfb->fb.var.green.offset) |
       (blue << cfb->fb.var.blue.offset) |
       (transp << cfb->fb.var.transp.offset);
  switch (cfb->fb.var.bits_per_pixel)
       {
                 case 8:
                             break;
                    case 16:
                          ((u32 *) (cfb->fb.pseudo_palette))[regno] = v;
                             break;
                        case 24:
                        case 32:
                             ((u32 *) (cfb->fb.pseudo_palette))[regno] = v;
                         break;
         }
        /*red        >>= 8;
        green        >>= 8;
        blue        >>= 8;
       
        red        &= 0xff;
        green        &= 0xff;
        blue        &= 0xff;
//}
        ctmp = (77L * red + 150L * green + 29L * blue) >> 8;
        ctmp = ((ctmp >> 3) << 11) | ((ctmp >> 2) << 5) | (ctmp >> 3);
        */
        return 0;
}

static int lcdm_ioctl (struct inode *inode, struct file *file,
                       unsigned int cmd, unsigned long arg, int con,
                       struct fb_info *info)
{
        switch (cmd) {
        case FBIOSTOPTIMER:
                del_timer(&lcdm_timer);
                break;
        case FBIOSTARTTIMER:
                init_timer(&lcdm_timer);
                lcdm_timer.expires = jiffies + LCDM_TIMER;
                lcdm_timer.data = 0;
                lcdm_timer.function = update_lcd;
                add_timer(&lcdm_timer);
                break;
        case FBIOREFRESH:
                write_screen(shadow_buf);
                break;
        case FBIOSLIGHT:
                if (arg)
                        __lcd_light_on();
                else
                        __lcd_light_off();
                break;
        }
        return 0;
}

/*
*    Set the User Defined Part of the Display
*/
static int lcdm_set_var(struct fb_var_screeninfo *var, int con,
                            struct fb_info *info)
{
        struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info;
//        struct display *display;
        int chgvar = 0;

        var->height                    = LCD_HEIGHT;
        var->width                    = LCD_WIDTH;
        var->bits_per_pixel            = 16;

        var->vmode                  = FB_VMODE_NONINTERLACED;
        var->activate               = cfb->fb.var.activate;
        var->xres                   = var->width;
        var->yres                   = var->height;
        var->xres_virtual           = var->width;
        var->yres_virtual           = var->height;

    var->red.offset=11;
        var->green.offset=5;
        var->blue.offset=0;
        var->red.length=5;
    var->green.length=6;
        var->blue.length=5;
        var->transp.length=0;





        var->xoffset                = 0;
        var->yoffset                = 0;
        var->pixclock               = 0;
        var->left_margin            = 0;
        var->right_margin           = 0;
        var->upper_margin           = 0;
        var->lower_margin           = 0;
        var->hsync_len              = 0;
        var->vsync_len              = 0;
        var->sync                   = 0;
        var->activate              &= ~FB_ACTIVATE_TEST;
   
        /*
         * CONUPDATE and SMOOTH_XPAN are equal.  However,
         * SMOOTH_XPAN is only used internally by fbcon.
         */
        if (var->vmode & FB_VMODE_CONUPDATE) {
                var->vmode |= FB_VMODE_YWRAP;
                var->xoffset = cfb->fb.var.xoffset;
                var->yoffset = cfb->fb.var.yoffset;
        }

        if (var->activate & FB_ACTIVATE_TEST)
                return 0;

        if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
                return -EINVAL;

        if (cfb->fb.var.xres != var->xres)
                chgvar = 1;
        if (cfb->fb.var.yres != var->yres)
                chgvar = 1;
        if (cfb->fb.var.xres_virtual != var->xres_virtual)
                chgvar = 1;
        if (cfb->fb.var.yres_virtual != var->yres_virtual)
                chgvar = 1;
        if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
                chgvar = 1;


        var->red.msb_right        = 0;
        var->green.msb_right        = 0;
        var->blue.msb_right        = 0;

        //cfb->fb.fix.visual        = FB_VISUAL_MONO01;
          cfb->fb.fix.visual    = FB_VISUAL_TRUECOLOR;
        cfb->fb.fix.line_length = (var->xres * var->bits_per_pixel) /  8;

        cfb->fb.var = *var;
        cfb->fb.var.activate &= ~FB_ACTIVATE_ALL;


        /*
         * Update the old var.  The fbcon drivers still use this.
         * Once they are using cfb->fb.var, this can be dropped.
         *                                        --rmk
         */
//        display->var = cfb->fb.var;
        /*
         * If we are setting all the virtual consoles, also set the
         * defaults used to create new consoles.
         */
        fb_set_cmap(&cfb->fb.cmap,&cfb->fb);
       

        return 0;
}

static void lcdm_blank(int blank, struct fb_info *info)
{
        return 0;
}

static int lcdm_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
         return 0;
}

static int lcdm_set_par(struct fb_info *info)
{
         return 0;
}



static int lcdm_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
        struct lcd_cfb_info *cfb = (struct lcd_cfb_info *)info;
        unsigned long start;
        unsigned long off;
        u32 len;

        off = vma->vm_pgoff << PAGE_SHIFT;
        //fb->fb_get_fix(&fix, PROC_CONSOLE(info), info);

        /* frame buffer memory */
        start = cfb->fb.fix.smem_start;
        len = PAGE_ALIGN((start & ~PAGE_MASK) + cfb->fb.fix.smem_len);
        start &= PAGE_MASK;

        if ((vma->vm_end - vma->vm_start + off) > len)
                return -EINVAL;
        off += start;

        vma->vm_pgoff = off >> PAGE_SHIFT;
        vma->vm_flags |= VM_IO;

#if defined(CONFIG_MIPS32)
        pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
        pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
//        pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT;
#endif
        printk("lcdm_mmap(): 1...\n");
        if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
                               vma->vm_end - vma->vm_start,
                               vma->vm_page_prot)) {
                printk("err, lcdm_mmap(): 2...\n");
                return -EAGAIN;
        }
        printk("lcdm_mmap(): 3...\n");
        return 0;
}

static struct fb_ops lcdm_ops = {
        .owner                        = THIS_MODULE,
        .fb_setcolreg                = lcdm_setcolreg,
        .fb_check_var                 = lcdm_check_var,
        .fb_set_par                 = lcdm_set_par,
        .fb_blank                = lcdm_blank,
//        .fb_pan_display                = lcdm_pan_display,
        .fb_fillrect                = cfb_fillrect,
        .fb_copyarea                = cfb_copyarea,
        .fb_imageblit                = cfb_imageblit,
        .fb_ioctl                = lcdm_ioctl,
        .fb_mmap                = lcdm_mmap,
};


static struct lcd_cfb_info * __devinit lcdm_alloc_fb_info(void)
{
        struct lcd_cfb_info *cfb;

        //cfb = kmalloc(sizeof(struct lcd_cfb_info) + sizeof(struct display) +
        //              sizeof(u32) * 16, GFP_KERNEL);

        cfb = kmalloc(sizeof(struct lcd_cfb_info) + sizeof(u32) * 16, GFP_KERNEL);
        if (!cfb)
                return NULL;

        memset(cfb, 0, sizeof(struct lcd_cfb_info));

        cfb->currcon                = -1;

        strcpy(cfb->fb.fix.id,"st7529-lcd");

        cfb->fb.fix.type        = FB_TYPE_PACKED_PIXELS;
        cfb->fb.fix.type_aux        = 0;
        cfb->fb.fix.xpanstep        = 0;
//        cfb->fb.fix.xpanstep        = 1;
        cfb->fb.fix.ypanstep        = 1;
        cfb->fb.fix.ywrapstep        = 0;

//        cfb->fb.fix.accel        = FB_ACCEL_NONE;

        cfb->fb.var.nonstd        = 0;
        cfb->fb.var.activate        = FB_ACTIVATE_NOW;
        cfb->fb.var.height        = -1;
        cfb->fb.var.width        = -1;
        cfb->fb.var.accel_flags        = FB_ACCELF_TEXT;

        //strcpy(cfb->fb.fontname, "lcd240160");

        cfb->fb.fbops                = &lcdm_ops;
//        cfb->fb.changevar        = NULL;
//        cfb->fb.switch_con        = lcdm_switch;
//        cfb->fb.updatevar        = lcdm_updatevar;
//        cfb->fb.blank                = lcdm_blank;
        cfb->fb.flags                = FBINFO_FLAG_DEFAULT;
//        cfb->fb.disp                = (struct display *)(cfb + 1);
//        cfb->fb.pseudo_palette        = (void *)(cfb->fb.disp + 1);
        cfb->fb.pseudo_palette        = (void *)(cfb + 1);

        fb_alloc_cmap(&cfb->fb.cmap, 256, 0);

        return cfb;
}

/*
* Map screen memory
*/
//static int __devinit lcdm_map_smem(struct lcd_cfb_info *cfb)
static int lcdm_map_smem(struct lcd_cfb_info *cfb)
{

        struct page * map = NULL;

        shadow_buf = (unsigned char *)__get_free_pages(GFP_KERNEL, 6);
//        backup_buf = (unsigned char *)__get_free_pages(GFP_KERNEL, 2);
        memset(shadow_buf, 0, 64 * PAGE_SIZE);
//        memset(backup_buf, 0, 4 * PAGE_SIZE);
        cfb->fb.screen_base = shadow_buf;
        printk("cfb->fb.screen_base %08x\n",cfb->fb.screen_base);
        map = virt_to_page(shadow_buf);
        set_bit(PG_reserved, &map->flags);

        /* Map the Screen memmory */
        cfb->fb.fix.smem_start = virt_to_phys(cfb->fb.screen_base);       

//        cfb->fb.fix.smem_start = virt_to_phys((void*)shadow_buf);       

        cfb->fb.fix.smem_len = LCD_WIDTH * LCD_HEIGHT*2;
       
#if 0
        cfb->fb.screen_base =
                    (unsigned char *)(((unsigned int)shadow_buf & 0x1fffffff) | 0xa0000000);

        printk("cfb->fb.screen_base %08x\n",cfb->fb.screen_base);
#endif
        if(!cfb->fb.screen_base){
                printk("%s,unable to map screen memory\n",cfb->fb.fix.id);
                return -ENOMEM;
        }

        return 0;

}

//static void __devinit lcdm_free_fb_info(struct lcd_cfb_info *cfb)
static void lcdm_free_fb_info(struct lcd_cfb_info *cfb)
{
        if (cfb) {
                fb_alloc_cmap(&cfb->fb.cmap, 0, 0);
                kfree(cfb);
        }
}

//static void __devinit lcdm_unmap_smem(struct lcd_cfb_info *cfb)
static void lcdm_unmap_smem(struct lcd_cfb_info *cfb)
{
        struct page * map = NULL;

        if (cfb && cfb->fb.screen_base) {
                iounmap(cfb->fb.screen_base);
                cfb->fb.screen_base = NULL;
                release_mem_region(cfb->fb.fix.smem_start,
                                   cfb->fb.fix.smem_len);
        }

        map = virt_to_page(shadow_buf);
        clear_bit(PG_reserved, &map->flags);
        free_pages((int)shadow_buf, 0);
}


#ifdef CONFIG_PM

/*
* Suspend the LCDC.
*/
//static int lcdm_suspend(struct lcd_cfb_info *cfb, int state)
static int lcdm_suspend(struct lcd_cfb_info *cfb, pm_message_t state)
{
        return 0;
}

/*
* Resume the LCDC.
*/
//static int lcdm_resume(struct lcd_cfb_info *cfb)
static int lcdm_resume(struct device *dev)
{
        return 0;
}

/*
* Power management hook.  Note that we won't be called from IRQ context,
* unlike the blank functions above, so we may sleep.
*/
static int lcdm_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
{
        int ret;
        struct lcd_cfb_info *cfb = pm_dev->data;

        return ret;
}
#endif /* CONFIG_PM */




#ifdef CONFIG_CLX_PWF
void lcdm_pwf_handler(int k)
{
        switch (k) {
        case 1:        /* check the power OK. */
                lcdm_chip_reset();
                break;
        default:
                break;
        }
}

static int lcdm_pwf_index;
#endif

static int __init st7529fb_init(void)
{
        struct lcd_cfb_info *cfb;
        int err = 0;
//        __lcdc_init();

        cfb = lcdm_alloc_fb_info();
        if (!cfb)
                goto failed;

        err = lcdm_map_smem(cfb);
        if (err)
                goto failed;

        lcdm_set_var(&cfb->fb.var, -1, &cfb->fb);

        lcdm_chip_reset();

        err = register_framebuffer(&cfb->fb);
        if (err < 0)
                goto failed;

#ifdef CONFIG_PM
        /*
         * Note that the console registers this as well, but we want to
         * power down the display prior to sleeping.
         */
        cfb->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, lcdm_pm_callback);
        if (cfb->pm)
                cfb->pm->data = cfb;
#endif

#ifdef CONFIG_CLX_PWF
        lcdm_pwf_index = register_powerfail_function(lcdm_pwf_handler);
        if (lcdm_pwf_index < 0)
                printk("WARN: register pwf function fail, slot busy\n");
#endif
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP