TFT屏 不显示彩色,只显示黑白色 不 知道怎么回事
我刚写的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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论