TQ2440移植u-boot2016.11全過程記錄-【4】LCD驅動移植並顯示

TQ2440移植u-boot2016.11-LCD驅動移植並顯示


LCD初始化流程分析

u-boot的LCD初始化代碼是在common/lcd.c中,我們找到lcd_init函數:
在這裏插入圖片描述
該函數功能流程爲:lcd_ctrl_init初始化了LCD的硬件參數---->開闢LCD的幀緩衝(緩衝基地址保存在了gd->fs_base變量中)—>清屏—>使能LCD—>設置LCD控制檯參數

lcd_ctrl_initlcd_enable函數是u-boot抽離出的函數接口,需要根據LCD的實際情況進行底層硬件的初始化操作實現這兩個函數;除此之外還需要定義一個名爲panel_infovidinfo_t結構類型變量,該結構變量保存了LCD屏幕的大小和顏色位深,用於LCD屏幕的控制檯顯示。


LCD驅動移植

我的屏幕是W43,分辨率480x272,驅動編寫參考的TQ2440官方的LCD屏幕驅動代碼修改而來。

添加LCD的相關配置宏:
gedit include/configs/tq2440.h

末尾添加如下代碼:

/*
 * LCD configuration
 */
#define CONFIG_LCD                        /* 該宏用於添加進LCD相關的編譯項 */
#define LCD_BPP LCD_COLOR16               /* 每像素爲16bits */
#define CONFIG_LCD_LOGO                   /* 顯示LOGO */
#define CONFIG_LCD_INFO                   /* 顯示用戶自定義信息 */
#define CONFIG_LCD_INFO_BELOW_LOGO        /* 用戶自定義信息與LOGO的位置無關 */
#define CONFIG_SYS_WHITE_ON_BLACK         /* 黑底白字 */
#define CONFIG_SYS_CONSOLE_IS_IN_ENV      /* 控制檯接收自環境變量 */
#define CONFIG_CONSOLE_MUX                /* 定義該宏可支持將打印信息同時輸出到串口和LCD */
#define CONFIG_CONSOLE_SCROLL_LINES 16    /* 屏幕顯示總行數 */

/* 以下三個宏爲我自己定義的 */
#define CONFIG_TQ2440_LCD                  /* 該宏用於將tq2440_lcd.c文件編譯進來 */
#define LCD_XSIZE_TFT 480                  /* LCD行數 */
#define LCD_YSIZE_TFT 272                  /* LCD列數 */

#define MVAL      13
#define MVAL_USED 0           /* 0:each frame    1:rate by MVAL */
#define INVVDEN   1           /* 0:normal        1:inverted     */
#define BSWP      0           /* byte swap control              */
#define HWSWP     1           /* half word swap control         */

#define CONFIG_TQ2440_LCD_VBPD    1
#define CONFIG_TQ2440_LCD_VFPD    1
#define CONFIG_TQ2440_LCD_VSPW    9
#define CONFIG_TQ2440_LCD_HBPD    1
#define CONFIG_TQ2440_LCD_HFPD    1
#define CONFIG_TQ2440_LCD_HSPW    40
#define CONFIG_TQ2440_LCD_CLKVAL  4

添加tq2440的LCD文件:

gedit drivers/video/tq2440_lcd.c

粘貼進如下代碼:

#include <common.h>
#include <lcd.h>
#include <asm/system.h>
#include <asm/gpio.h>
#include <asm/arch/s3c24x0_cpu.h>
#include <lcd.h>
#include <version.h>

DECLARE_GLOBAL_DATA_PTR;    /* 導入gd_t結構變量gd */

/* to get lower 21bits */
#define M5D(n) ((n) & 0x1FFFFF)

vidinfo_t panel_info =
{
    .vl_col  = LCD_XSIZE_TFT,    /* 列數 */
    .vl_row  = LCD_YSIZE_TFT,    /* 行數 */
    .vl_bpix = LCD_BPP,          /* 像素位數爲16bits,該宏在tq2440.h中被定義 */
};

/* 將LCD緩衝數組轉爲二維數組來用 */
#define tq2440_lcd_frame_pbuf ((volatile unsigned short (*)[LCD_XSIZE_TFT])(gd->fb_base))

void tq2440_lcd_clear_screen(unsigned short color)
{
    int x = 0, y = 0;

    for (y = 0; y < LCD_YSIZE_TFT; y++)
    {
        for (x = 0; x < LCD_XSIZE_TFT; x++)
        {
            tq2440_lcd_frame_pbuf[y][x] = color;
        }
    }
}

void lcd_ctrl_init(void* lcdbase)
{
    char vbpd = 0;
    char vfpd = 0;
    char vspw = 0;
    char hbpd = 0;
    char hfpd = 0;
    char hspw = 0;
    char clkval = 0;
    char* lcdenv = NULL;
    struct s3c24x0_gpio* const gpio = s3c24x0_get_base_gpio();
    struct s3c24x0_lcd*  const lcd  = s3c24x0_get_base_lcd();

    /* set lcd frame buffer start adddress */
    lcd->lcdsaddr1 = (((unsigned int)tq2440_lcd_frame_pbuf >> 22) << 21) | M5D((unsigned int)tq2440_lcd_frame_pbuf >> 1);

    /* set lcd frame buffer end adddress */
    lcd->lcdsaddr2 = M5D(((unsigned int)tq2440_lcd_frame_pbuf + (LCD_XSIZE_TFT * LCD_YSIZE_TFT * 2)) >> 1);

    /* set virtul screen page wigth */
    lcd->lcdsaddr3 = (((LCD_XSIZE_TFT - LCD_XSIZE_TFT) / 1) << 11) | (LCD_XSIZE_TFT / 1);

    lcdenv = getenv("dwVBPD");
    vbpd = lcdenv ? (int)simple_strtol(lcdenv, NULL, 10) : CONFIG_TQ2440_LCD_VBPD;

    lcdenv = getenv("dwVFPD");
    vfpd = lcdenv ? (int)simple_strtol(lcdenv, NULL, 10) : CONFIG_TQ2440_LCD_VFPD;

    lcdenv = getenv("dwVSPW");
    vspw = lcdenv ? (int)simple_strtol(lcdenv, NULL, 10) : CONFIG_TQ2440_LCD_VSPW;

    lcdenv = getenv("dwHBPD");
    hbpd = lcdenv ? (int)simple_strtol(lcdenv, NULL, 10) : CONFIG_TQ2440_LCD_HBPD;

    lcdenv = getenv("dwHFPD");
    hfpd = lcdenv ? (int)simple_strtol(lcdenv, NULL, 10) : CONFIG_TQ2440_LCD_HFPD;

    lcdenv = getenv("dwHSPW");
    hspw = lcdenv ? (int)simple_strtol(lcdenv, NULL, 10) : CONFIG_TQ2440_LCD_HSPW;

    lcdenv = getenv("dwCLKVAL");
    clkval = lcdenv ? (int)simple_strtol(lcdenv, NULL, 10) : CONFIG_TQ2440_LCD_CLKVAL;

    /* clear screen */
    tq2440_lcd_clear_screen(0x0000);

	/* initialize VD[7:0] */
	gpio->gpcup  = 0xFFFFFFFF;
	gpio->gpccon = 0xAAAAAAAA;

	/* initialize VD[15:8] */
	gpio->gpdup  = 0xFFFFFFFF;
	gpio->gpdcon = 0xAAAAAAAA;
	
    /* lcd config */
    lcd->lcdcon1 = (clkval << 8) | (MVAL_USED << 7) | (3 << 5) | (12 << 1) | 0;
    lcd->lcdcon2 = (vbpd << 24) | ((LCD_YSIZE_TFT - 1) << 14) | (vfpd << 6) | vspw;
    lcd->lcdcon3 = (hbpd << 19) | ((LCD_XSIZE_TFT - 1) << 8) | hfpd;
    lcd->lcdcon4 = (MVAL << 8) | hspw;
    lcd->lcdcon5 = (1 << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 7) | (0 << 6) | (1 << 3) | (BSWP << 1) | HWSWP;

    /* make lcd sub interrupt */
    lcd->lcdintmsk |= 0x3;

    /* disable lpc3480 */
    lcd->lpcsel &= ~(0x7);

    /* disbale temp palette */
    lcd->tpal = 0x0;

    /* disable gpg4 pull-up */
    gpio->gpgup &= ~(1 << 4);

    /* set gpg4 mode to lcd_pwrdn */
    gpio->gpgcon |= 3 << 8;

    /* set gpg4 to high */
    gpio->gpgdat |= 1 << 4;

    /* enable pwren signal */
    lcd->lcdcon5 |= 1 << 3;

    /* set signal polarity to normal */
    lcd->lcdcon5 &= ~(1 << 5);
}

void lcd_enable(void)
{
	struct s3c24x0_lcd* const lcd = s3c24x0_get_base_lcd();

	/* Enable the video output and the LCD control signal. */
	lcd->lcdcon1 |= (1 << 0);
}

#ifdef CONFIG_LCD_INFO
void lcd_show_board_info(void)
{
	lcd_printf("%s (%s - %s)\n", U_BOOT_VERSION, U_BOOT_DATE, U_BOOT_TIME);
}
#endif

添加進編譯項:
gedit drivers/video/Makefile

末尾添加一行:

obj-$(CONFIG_TQ2440_LCD) += tq2440_lcd.o

測試

編譯後使用tftp下載到內存0x30008000處並運行程序,查看效果:
在這裏插入圖片描述
下面操作將輸出信息重定向到LCD上顯示:

使用以下命令查看可以將輸出信息重定向到哪些設備:
coninfo
在這裏插入圖片描述
可以看到可以將輸出信息重定向到串口和LCD,serial就是我們使用的串口一,標誌爲IO,也就是說可以輸入輸出,LCD爲.O,也就是說只能輸出不能輸入。

將輸出信息同時重定向到LCD和串口一:

setenv stdout 'lcd,serial'

在這裏插入圖片描述
在這裏插入圖片描述


ends…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章