天嵌 ARM开发社区

 找回密码
 注册
查看: 3486|回复: 2

很郁闷呀 LCD的背光灯亮啦,但是屏幕就是不亮呀 怎么回事

[复制链接]
wang12zhedi 发表于 2012-11-12 17:06:41 | 显示全部楼层 |阅读模式
#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/workqueue.h>
#include <linux/wait.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/div64.h>
#include <asm/mach/map.h>
#include <mach/regs-lcd.h>
#include <mach/regs-gpio.h>
#include <mach/fb.h>


#define DBGprintk  printk
//#define DBGprintk(...)

//LCDCON1定义
#define CLKVAL 4
#define MMODE  0
#define PNRMODE 3
#define BPPMODE 12
#define ENVIDOFF 0
#define ENVIDON 1

//LCDCON2定义
#define VBPD 2
#define LINEVAL (272-1)
#define VFPD 4  //原值4
#define VSPW 8  //原值8
//LCDCON3定义
#define HBPD 10
#define HOZVAL (480-1)
#define HFPD 19
//LCDCON4定义
#define MVAL 13
#define HSPW 30
//LCDCON5定义

#define BPP24BL      0
#define FRM565      1
#define INVVCLK     0
#define INVVLINE    1
#define INVVFRAME   1
#define INVVD       0
#define INVVDEN     0
#define INVPWREN    0
#define INVLEND     0
#define PWRENOFF    0
#define PWRENON     1
#define ENLEND      0
#define BSWP        0
#define HWSWP       1  //2440手册
//LCDSADD3定义
#define OFFSIZE 0  //因为虚拟屏幕和物理屏幕大小一样->0
#define LCDSADDR3 480//因为虚拟屏幕和物理屏幕大小一样->480

//这个结构体中寄存器名字使用大写的话会出现莫明奇妙的错误  需要再试试
struct s3c2440_reg
{
        unsigned long        lcdcon1;
        unsigned long        lcdcon2;
        unsigned long        lcdcon3;
        unsigned long        lcdcon4;
        unsigned long        lcdcon5;
    unsigned long        lcdsaddr1;
    unsigned long        lcdsaddr2;
    unsigned long        lcdsaddr3;
    unsigned long        redlut;
    unsigned long        greenlut;
    unsigned long        bluelut;//BLUELUT地址0X4D000028
    unsigned long        reserved[9];//地址0X4D00004C,二者相差9个字节  为什么不是bluelut【9】
    unsigned long        dithmode;
    unsigned long        tpal;
    unsigned long        lcdintpnd;
    unsigned long        lcdsrcpnd;
    unsigned long        lcdintmsk;
    unsigned long        tconsel;
        };

//有些需要定义成指针,因为 对应的函数是返回指针的函数
struct s3c2440_reg *s3c2440_regs;
static struct fb_info *mylcd_info;
//static volatile unsigned long *GPBCON;
//static volatile unsigned long *GPBDAT;
static volatile unsigned long *GPCCON;
static volatile unsigned long *GPDCON;
static volatile unsigned long *GPGCON;
static u32 pseudo_palette[16];//


/* from pxafb.c */
static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
{
   
        chan &= 0xffff;  //取出低16位  
        chan >>= 16 - bf->length;//chan保存相应颜色的取值
        return chan << bf->offset; //
        DBGprintk(" chan_to_field\n");
}

//设置调色板
static int s3c_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_palette[regno] = val;
       
        DBGprintk(" val= %d\n",val);
        DBGprintk(" s3c_lcdfb_setcolreg\n");
        return 0;
}


static struct fb_ops s3c_lcdfb_ops = {
        .owner                = THIS_MODULE,
        .fb_setcolreg        = s3c_lcdfb_setcolreg,
        .fb_fillrect        = cfb_fillrect,
        .fb_copyarea        = cfb_copyarea,
        .fb_imageblit        = cfb_imageblit,
};

static int lcd_init(void)
{/*  分配一个fb_info */
mylcd_info = framebuffer_alloc(0,NULL);
if(mylcd_info ==NULL)//检查分配是否成功
        DBGprintk(" framebuffer_alloc fail \n");
/*  设置固定的参数 */
strcpy(mylcd_info->fix.id, "mylcd");
mylcd_info->fix.smem_len = 480*272*16/8;//  R  G  B  565  =16
mylcd_info->fix.type     = FB_TYPE_PACKED_PIXELS;/* Packed Pixels  塞满 像素        */
mylcd_info->fix.visual   = FB_VISUAL_TRUECOLOR; /* TFT  真彩色*/
mylcd_info->fix.line_length = 480*16/8;//一行480个像素 一个像素16位

/*  设置可变的参数 */
//硬件确定的分辨率
mylcd_info->var.xres           = 480;
mylcd_info->var.yres           = 272;
//虚拟分辨率;可以通过软件更该 类似电脑分辨率
mylcd_info->var.xres_virtual   = 480;
mylcd_info->var.yres_virtual   = 272;
mylcd_info->var.bits_per_pixel = 16;

/* RGB:565   ->红色偏移值11  绿色偏移值5 蓝色偏移值0*/
mylcd_info->var.red.offset     = 11;
mylcd_info->var.red.length     = 5;

mylcd_info->var.green.offset   = 5;
mylcd_info->var.green.length   = 6;

mylcd_info->var.blue.offset    = 0;
mylcd_info->var.blue.length    = 5;

mylcd_info->var.activate       = FB_ACTIVATE_NOW;//看不懂就用默认值 默认值支持大多数

/*  设置操作函数 */
mylcd_info->fbops              = &s3c_lcdfb_ops;

/*  其他的设置 */
mylcd_info->pseudo_palette = pseudo_palette; /* 伪16色颜色表  可能是兼容以前的程序,需要设置假的调色板*/
mylcd_info->screen_size   = 480*272*16/8;

/* 3.1 配置GPIO用于LCD */
//GPBCON = ioremap(0x56000010, 8);//ioremap是一个返回指针的函数
//GPBDAT = GPBCON+1;
GPCCON = ioremap(0x56000020, 4);
GPDCON = ioremap(0x56000030, 4);
GPGCON = ioremap(0x56000060, 4);
//向GPCCVON写入值,特别注意GPCCON是指针
*GPCCON  =0xaaaa02a9;   /* GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND */
*GPDCON  = 0xaaaaaaaa;   /* GPIO管脚用于VD[23:8] */
*GPGCON |= (3<<8); /* GPG4用作LCD_PWREN */

s3c2440_regs = ioremap(0X4D000000, sizeof(struct s3c2440_reg));
s3c2440_regs->lcdcon1= (CLKVAL <<8)|(MMODE<<7)|(PNRMODE<<5)|(BPPMODE<<1)|(ENVIDOFF<<0);
s3c2440_regs->lcdcon2= (VBPD<<24)|(LINEVAL<<14)|(VFPD<<6)|(VSPW<<0);
s3c2440_regs->lcdcon3= (HBPD<<19)|(HOZVAL<<8)|(HFPD<<0);
s3c2440_regs->lcdcon4 =(MVAL<<8)|(HSPW<<0);
s3c2440_regs->lcdcon5 =(FRM565<<11)|(INVVCLK<<10)|(INVVLINE<<9)|(INVVFRAME<<8)|(1<<3)|(1<<2)|(HWSWP<<0);

// 分配显存(framebuffer),  专用函数dma_alloc_writecombine分配 */
mylcd_info->screen_base = dma_alloc_writecombine(NULL, mylcd_info->fix.smem_len, &mylcd_info->fix.smem_start, GFP_KERNEL);
//并把地址告诉LCD控制器
s3c2440_regs->lcdsaddr1 = (mylcd_info->fix.smem_start >> 1) & ~(3<<30);//最高两位不需要 ->& ~(3<<30)
s3c2440_regs->lcdsaddr2 = ((mylcd_info->fix.smem_start + mylcd_info->fix.smem_len) >> 1) & 0x1fffff;//只关心21位-> & 0x1fffff
//                                 起始地址     +             大小  =结束地址            
s3c2440_regs->lcdsaddr3 = (480*16/16);  /* 一行的长度(单位: 2字节) */       

/* 启动LCD */

s3c2440_regs->lcdcon5|= (0<<5)|(PWRENON<<3); /* 使能LCD本身 */
s3c2440_regs->lcdcon1|= (ENVIDON<<0); /* 使能LCD控制器 */


DBGprintk(" lcd_init\n");
/* 4. 注册 */
register_framebuffer(mylcd_info);

return 0;
}


static void lcd_exit(void)
{
        unregister_framebuffer(mylcd_info);
        s3c2440_regs->lcdcon1 &= ~(1<<0); /* 关闭LCD本身 */
       
        dma_free_writecombine(NULL, mylcd_info->fix.smem_len, mylcd_info->screen_base, mylcd_info->fix.smem_start);
        iounmap(s3c2440_regs);
       
        iounmap(GPCCON);
        iounmap(GPDCON);
        iounmap(GPGCON);
        framebuffer_release(mylcd_info);
        DBGprintk(" lcd_exit\n");
}


module_init(lcd_init);
module_exit(lcd_exit);
MODULE_LICENSE("GPL");
embedsky_lhh 发表于 2012-11-13 09:45:39 | 显示全部楼层
LCD的时序对了么,在系统里边LCD驱动你加到video中好些,有专门的fb管理,应用操作方便
回复

使用道具 举报

 楼主| wang12zhedi 发表于 2012-11-13 12:58:28 | 显示全部楼层
终于找到问题啦,加载自己的驱动时需要把原来的驱动LCD去掉,我在配置内核的时候去掉的多啦
回复

使用道具 举报

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

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号-2 )

GMT+8, 2025-8-5 23:22 , Processed in 2.034254 second(s), 20 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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