56、编写lcd控制器设置、参数的设置程序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18077275/article/details/89416688

1、代码结构

2、s3c2440_lcd_controller.c   //lcd控制器相关的代码,需要向lcd_controller.c管理者注册,管理者下发p_lcd_params屏的参数


#include "lcd.h"
#include "lcd_controller.h"
#include "../s3c2440_soc.h"

#define HCLK 100

void jz2440_lcd_pin_init(void)
{
    /* 初始化引脚 : 背光引脚 */
    GPBCON &= ~0x3;
    GPBCON |= 0x01;

    /* LCD专用引脚 */
    GPCCON = 0xaaaaaaaa;
    GPDCON = 0xaaaaaaaa;

    /* PWREN */
    GPGCON |= (3<<8);
}


/* 根据传入的LCD参数设置LCD控制器 */
void s3c2440_lcd_controller_init(p_lcd_params plcdparams)
{
    int pixelplace;
    unsigned int addr;

    jz2440_lcd_pin_init();
    
    /* [17:8]: clkval, vclk = HCLK / [(CLKVAL+1) x 2]
     *                   9   = 100M /[(CLKVAL+1) x 2], clkval = 4.5 = 5
     *                 CLKVAL = 100/vclk/2-1
     * [6:5]: 0b11, tft lcd
     * [4:1]: bpp mode
     * [0]  : LCD video output and the logic enable/disable
     */
    int clkval = (float)HCLK/plcdparams->time_seq.vclk/2-1+0.5;
    //int clkval = 5;
    int bppmode = plcdparams->bpp == 8  ? 0xb :\
                  plcdparams->bpp == 16 ? 0xc :\
                  0xd;  /* 0xd: 24,32bpp */
    LCDCON1 = (clkval<<8) | (3<<5) | (bppmode<<1) ;

    /* [31:24] : VBPD    = tvb - 1
     * [23:14] : LINEVAL = line - 1
     * [13:6]  : VFPD    = tvf - 1
     * [5:0]   : VSPW    = tvp - 1
     */
    LCDCON2 =     ((plcdparams->time_seq.tvb - 1)<<24) | \
                ((plcdparams->yres - 1)<<14)         | \
                ((plcdparams->time_seq.tvf - 1)<<6)  | \
                ((plcdparams->time_seq.tvp - 1)<<0);

    /* [25:19] : HBPD     = thb - 1
     * [18:8]  : HOZVAL  = 列 - 1
     * [7:0]   : HFPD     = thf - 1
     */
    LCDCON3 =    ((plcdparams->time_seq.thb - 1)<<19) | \
                ((plcdparams->xres - 1)<<8)              | \
                ((plcdparams->time_seq.thf - 1)<<0);

    /* 
     * [7:0]   : HSPW     = thp - 1
     */
    LCDCON4 =    ((plcdparams->time_seq.thp - 1)<<0);

    /* 用来设置引脚极性, 设置16bpp, 设置内存中象素存放的格式
     * [12] : BPP24BL
     * [11] : FRM565, 1-565
     * [10] : INVVCLK, 0 = The video data is fetched at VCLK falling edge
     * [9]  : HSYNC是否反转
     * [8]  : VSYNC是否反转
     * [7]  : INVVD, rgb是否反转
     * [6]  : INVVDEN
     * [5]  : INVPWREN
     * [4]  : INVLEND
     * [3]  : PWREN, LCD_PWREN output signal enable/disable
     * [2]  : ENLEND
     * [1]  : BSWP
     * [0]  : HWSWP
     */

    pixelplace = plcdparams->bpp == 32 ? (0) : \
                 plcdparams->bpp == 16 ? (1) : \
                 (1<<1);  /* 8bpp */
    
    LCDCON5 = (plcdparams->pins_pol.vclk<<10) |\
              (plcdparams->pins_pol.rgb<<7)   |\
              (plcdparams->pins_pol.hsync<<9) |\
              (plcdparams->pins_pol.vsync<<8) |\
               (plcdparams->pins_pol.de<<6)    |\
              (plcdparams->pins_pol.pwren<<5) |\
              (1<<11) | pixelplace;

    /* framebuffer地址 */
    /*
     * [29:21] : LCDBANK, A[30:22] of fb
     * [20:0]  : LCDBASEU, A[21:1] of fb
     */
    addr = plcdparams->fb_base & ~(1<<31);
    LCDSADDR1 = (addr >> 1);

    /* 
     * [20:0] : LCDBASEL, A[21:1] of end addr
     */
    addr = plcdparams->fb_base + plcdparams->xres*plcdparams->yres*plcdparams->bpp/8;
    addr >>=1;
    addr &= 0x1fffff;
    LCDSADDR2 = addr;//    
}

void s3c2440_lcd_controller_enalbe(void)
{
    /* 背光引脚 : GPB0 */
    GPBDAT |= (1<<0);
    
    /* pwren    : 给LCD提供AVDD  */
    LCDCON5 |= (1<<3);
    
    /* LCDCON1'BIT 0 : 设置LCD控制器是否输出信号 */
    LCDCON1 |= (1<<0);
}

void s3c2440_lcd_controller_disable(void)
{
    /* 背光引脚 : GPB0 */
    GPBDAT &= ~(1<<0);

    /* pwren    : 给LCD提供AVDD  */
    LCDCON5 &= ~(1<<3);

    /* LCDCON1'BIT 0 : 设置LCD控制器是否输出信号 */
    LCDCON1 &= ~(1<<0);
}


/* 设置调色板之前, 先关闭lcd_controller */
void s3c2440_lcd_controller_init_palette(void)
{
    volatile unsigned int *palette_base =  (volatile unsigned int *)0x4D000400;
    int i;

    int bit = LCDCON1 & (1<<0);

    /* LCDCON1'BIT 0 : 设置LCD控制器是否输出信号 */
    if (bit)
        LCDCON1 &= ~(1<<0);

    for (i = 0; i < 256; i++)
    {
        /* 低16位 : rgb565 */    
        *palette_base++ = i;
    }

    if (bit)
        LCDCON1 |= (1<<0);
}

struct lcd_controller s3c2440_lcd_controller = {
    .name    = "s3c2440",
    .init    = s3c2440_lcd_controller_init,
    .enable  = s3c2440_lcd_controller_enalbe,
    .disable = s3c2440_lcd_controller_disable,
    .init_palette = s3c2440_lcd_controller_init_palette,
};


void s3c2440_lcd_contoller_add(void)
{
    register_lcd_controller(&s3c2440_lcd_controller);
}

3、lcd_controller.c 控制器管理者,提供下面控制器注册接口,封装控制器这一层,向lcd.c来提供一些接口使用它


#include "lcd_controller.h"

#define LCD_CONTROLLER_NUM 10

static p_lcd_controller p_array_lcd_controller[LCD_CONTROLLER_NUM];
static p_lcd_controller g_p_lcd_controller_selected;

int register_lcd_controller(p_lcd_controller plcdcon)
{
    int i;
    for (i = 0; i < LCD_CONTROLLER_NUM; i++)
    {
        if (!p_array_lcd_controller[i])
        {
            p_array_lcd_controller[i] = plcdcon;
            return i;
        }
    }
    return -1;        
}

int select_lcd_controller(char *name)
{
    int i;
    for (i = 0; i < LCD_CONTROLLER_NUM; i++)
    {
        if (p_array_lcd_controller[i] && !strcmp(p_array_lcd_controller[i]->name, name))
        {
            g_p_lcd_controller_selected = p_array_lcd_controller[i];
            return i;
        }
    }
    return -1;        
}


/* 向上: 接收不同LCD的参数
 * 向下: 使用这些参数设置对应的LCD控制器
 */

int lcd_controller_init(p_lcd_params plcdparams)
{
    /* 调用所选择的LCD控制器的初始化函数 */
    if (g_p_lcd_controller_selected)
    {
        g_p_lcd_controller_selected->init(plcdparams);
        g_p_lcd_controller_selected->init_palette();
        return 0;
    }
    return -1;
}

void lcd_controller_enable(void)
{
    if (g_p_lcd_controller_selected)
    {
        g_p_lcd_controller_selected->enable();
    }
}

void lcd_controller_disable(void)
{
    if (g_p_lcd_controller_selected)
    {
        g_p_lcd_controller_selected->disable();
    }
}


void lcd_contoller_add(void)
{
    s3c2440_lcd_contoller_add();
}

4、lcd_4.3.c   各个屏的屏参数设置,向lcd.c注册。


#include "lcd.h"

#define LCD_FB_BASE 0x33c00000

lcd_params lcd_4_3_params = {
    .name = "lcd_4.3",
    .pins_pol = {
        .de    = NORMAL,    /* normal: 高电平时可以传输数据 */
        .pwren = NORMAL,    /* normal: 高电平有效 */
        .vclk  = NORMAL,    /* normal: 在下降沿获取数据 */
        .rgb   = NORMAL,    /* normal: 高电平表示1 */
        .hsync = INVERT,    /* normal: 高脉冲 */
        .vsync = INVERT,     /* normal: 高脉冲 */
    },
    .time_seq = {
        /* 垂直方向 */
        .tvp=    10, /* vysnc脉冲宽度 */
        .tvb=    2,  /* 上边黑框, Vertical Back porch */
        .tvf=    2,  /* 下边黑框, Vertical Front porch */

        /* 水平方向 */
        .thp=    41, /* hsync脉冲宽度 */
        .thb=    2,  /* 左边黑框, Horizontal Back porch */
        .thf=    2,  /* 右边黑框, Horizontal Front porch */

        .vclk=    9,  /* MHz */
    },
    .xres = 480,
    .yres = 272,
    .bpp  = 8,  /* 16, no 24bpp */
    .fb_base = LCD_FB_BASE,
};


void lcd_4_3_add(void)
{
    register_lcd(&lcd_4_3_params);
}

5、lcd.c    提供下面lcd_4_3显示屏的注册接口,还有和控制器管理者去申请资源

#include "lcd.h"
#include "lcd_controller.h"

#define LCD_NUM 10

static p_lcd_params p_array_lcd[LCD_NUM];
static p_lcd_params g_p_lcd_selected;

int register_lcd(p_lcd_params plcd)
{
    int i;
    for (i = 0; i < LCD_NUM; i++)
    {
        if (!p_array_lcd[i])
        {
            p_array_lcd[i] = plcd;
            return i;
        }
    }
    return -1;        
}

int select_lcd(char *name)
{
    int i;
    for (i = 0; i < LCD_NUM; i++)
    {
        if (p_array_lcd[i] && !strcmp(p_array_lcd[i]->name, name))
        {
            g_p_lcd_selected = p_array_lcd[i];
            return i;
        }
    }
    return -1;        
}

void get_lcd_params(unsigned int *fb_base, int *xres, int *yres, int *bpp)
{
    *fb_base = g_p_lcd_selected->fb_base;
    *xres = g_p_lcd_selected->xres;
    *yres = g_p_lcd_selected->yres;
    *bpp = g_p_lcd_selected->bpp;
}

void lcd_enable(void)
{
    lcd_controller_enable();
}

void lcd_disable(void)
{
    lcd_controller_disable();
}

int lcd_init(void)
{
    /* 注册LCD */
    lcd_4_3_add();

    /* 注册LCD控制器 */
    lcd_contoller_add();
    
    /* 选择某款LCD */
    select_lcd("lcd_4.3");

    /* 选择某款LCD控制器 */
    select_lcd_controller("s3c2440");

    /* 使用LCD的参数, 初始化LCD控制器 */
    lcd_controller_init(g_p_lcd_selected);
}

6、lcd_controller.h  在s3c2440_lcd_controller.c去实现这些接口再向lcd_controller.c注册


#ifndef _LCD_CONTROLLER_H
#define _LCD_CONTROLLER_H

#include "lcd.h"

typedef struct lcd_controller {
    char *name;
    void (*init)(p_lcd_params plcdparams);
    void (*enable)(void);
    void (*disable)(void);
    void (*init_palette)(void);
}lcd_controller, *p_lcd_controller;

#endif /* _LCD_CONTROLLER_H */

7、lcd.h       在lcd_4.3.c中实现如下结构体,向lcd.c注册


#ifndef _LCD_H
#define _LCD_H


enum {
    NORMAL = 0,
    INVERT = 1,
};

/* NORMAL : 正常极性
 * INVERT : 反转极性
 */
typedef struct pins_polarity {
    int de;    /* normal: 高电平时可以传输数据 */
    int pwren; /* normal: 高电平有效 */
    int vclk;  /* normal: 在下降沿获取数据 */
    int rgb;   /* normal: 高电平表示1 */
    int hsync; /* normal: 高脉冲 */
    int vsync; /* normal: 高脉冲 */
}pins_polarity, *p_pins_polarity;

typedef struct time_sequence {
    /* 垂直方向 */
    int tvp; /* vysnc脉冲宽度 */
    int tvb; /* 上边黑框, Vertical Back porch */
    int tvf; /* 下边黑框, Vertical Front porch */

    /* 水平方向 */
    int thp; /* hsync脉冲宽度 */
    int thb; /* 左边黑框, Horizontal Back porch */
    int thf; /* 右边黑框, Horizontal Front porch */

    int vclk;
}time_sequence, *p_time_sequence;


typedef struct lcd_params {
    char *name;
    
    /* 引脚极性 */
    pins_polarity pins_pol;
    
    /* 时序 */
    time_sequence time_seq;
    
    /* 分辨率, bpp */
    int xres;
    int yres;
    int bpp;
    
    /* framebuffer的地址 */
    unsigned int fb_base;
}lcd_params, *p_lcd_params;

void get_lcd_params(unsigned int *fb_base, int *xres, int *yres, int *bpp);

#endif /* _LCD_H */


 

猜你喜欢

转载自blog.csdn.net/qq_18077275/article/details/89416688