smdkv210 uboot增加LCD显示(一)

本文介绍了在U-Boot环境下为华天正smdkv210开发板移植LCD驱动的过程,包括解决显示问题及调整配置使其适用于7寸800*480电容屏的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

华天正smdkv210开发板的自带的uboot没有加入LCD显示功能,需要用串口进行交互,给烧写系统带来麻烦。

所以考虑修改uboot源码增加LCD显示和按键驱动,使得板子可以不用串口也能烧写系统。开发板用的是7寸

800*480电容屏。

在此过程中我主要参考了两篇文章,一篇文章是简单的LCD驱动,对应的配置是 CONFIG_LCD,核心源码是

/common/lcd.c ; 另一篇是带console的驱动,对应CONFIG_VIDEO,核心源码是/drivers/video/cfb_console.c。

这两个也是我移植过程中经历的两个阶段,先介绍简单的LCD驱动。主要参考文章

s3c6410 LCD 在uboot下的驱动http://hi.baidu.com/sundongxia2008/blog/item/8a43f9470f01399eb2b7dc97.html

由于没有LCD的datasheet,得不到时序参数,在仿照这篇文章移植后没有任何显示,后来在开发板自带的uboot

源码中找到了一个lcd驱动,/cpu/s5pc11x/fimd.c,调用里面的LCD初始化代码修改lcd.c,实现lcd刷蓝色背景,在

指定位置显示字符。lcd.c源码如下:

/*
 * Common LCD routines for supported CPUs
 *
 */
/************************************************************************/
/* ** HEADER FILES */
/************************************************************************/

/* #define DEBUG */

#include <config.h>
#include <common.h>
#include <command.h>
#include <version.h>
#include <stdarg.h>
#include <linux/types.h>
#include <devices.h>
#if defined(CONFIG_POST)
#include <post.h>
#endif
#include <lcd.h>
#include <watchdog.h>
#ifdef CONFIG_LCD

/************************************************************************/
/* ** FONT DATA */
/************************************************************************/
#include <fonts.h> /* Get font data, width and height*/

#define LCD_WIDTH 800
#define LCD_HEIGHT 480
#define LCD_BGCOLOR 0x1428A0
#define LCD_SETCURSOR(Xpos,Ypos) (CFG_LCD_FBUFFER + Xpos*LCD_WIDTH*4 + Ypos*4)

static unsigned int TextColor = 0x0000;
static unsigned int BackColor = LCD_BGCOLOR;

void LCD_Initialize_NONAME1(void);   //fimd.c中的LCD初始化函数
/*
 * Frame buffer memory information
 */
//void *lcd_base; /* Start of framebuffer memory*/

static int lcd_init ();
void lcd_Enable (void);

/************************************************************************/
/* ** GENERIC Initialization Routines */
/************************************************************************/
int drv_lcd_init (void)
{
struct device_t lcddev;
int rc;
//        lcd_base = (void*)CFG_LCD_FBUFFER;

lcd_init (); /* LCD initialization */
#ifdef CONFIG_NO_VIDEO_CONSOLE
return 0;
#endif
// Device initialization 
memset (&lcddev, 0, sizeof (lcddev));
strcpy (lcddev.name, "lcd");
lcddev.ext   = 0;
lcddev.flags = DEV_FLAGS_OUTPUT;
lcddev.putc  = lcd_putc;
lcddev.puts  = lcd_puts;
rc = device_register (&lcddev); //重定向输出信息 
return (rc == 0) ? 1 : rc; 
}
/*----------------------------------------------------------------------*/
static int lcd_init ()
{
/* Initialize the lcd controller */
printf("LCD Initializing......");
LCD_Initialize_NONAME1();
printf("complete\n");
LCD_clear();                      //刷蓝色背景色
LCD_DisplayChar(0,0,'E');  //在(0,0)处写字母”E”
return 0;
}
void LCD_DrawChar(u16 Xpos, u16 Ypos, uc16 *c)
{
  u32 index = 0, i = 0;
  u16 Xaddress = 0;
   Xaddress = Xpos;
    u32* pBuffer = (u32*)LCD_SETCURSOR(Xaddress, Ypos);
  for(index = 0; index < 24; index++)
  {
    for(i = 0; i < 16; i++)
    {
      if((c[index] & (1 << i)) == 0x00)
      {
        *pBuffer++ = BackColor;
      }
      else
      {
        *pBuffer++ = TextColor;
      }
    }
    Xaddress++;
    pBuffer = (u32*)LCD_SETCURSOR(Xaddress, Ypos);
  }
}

void LCD_DisplayChar(u16 Line, u16 Column, u8 Ascii)
{
  Ascii -= 32;
  LCD_DrawChar(Line, Column, &ASCII_Table[Ascii * 24]);
}
void LCD_clear()
{
u16 i, j;
u32* pBuffer = (u32*)CFG_LCD_FBUFFER;
for (i=0; i < LCD_HEIGHT; i++)
{
for (j=0; j < LCD_WIDTH; j++)
{
*pBuffer++ = BackColor;
}
}
}
ulong calc_fbsize (void)
{
  ulong size;
  
  int line_length = (panel_info.vl_col * panel_info.vl_bpix) / 8;
  size = line_length * panel_info.vl_row;
#ifdef CFG_LCD_FBUFFER
  size = 1536000;
#endif
    return size;
}
/************************************************************************/
/* ** ROM capable initialization part - needed to reserve FB memory*/
/************************************************************************/
/*
 * This is called early in the system initialization to grab memory
 * for the LCD controller.
 * Returns new address for monitor, after reserving LCD buffer memory
 *
 * Note that this is running from ROM, so no write access to global data.
 */
ulong lcd_setmem (ulong addr)
{
ulong size;
int line_length = (panel_info.vl_col * panel_info.vl_bpix) / 8;
debug ("LCD panel info: %d x %d, %d bit/pix\n",
panel_info.vl_col, panel_info.vl_row, NBITS (panel_info.vl_bpix) );
size = line_length * panel_info.vl_row;
#ifdef CFG_LCD_FBUFFER
        size = 1536000;    //800*480*4 bytes
#endif
/* Round up to nearest full page */
size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
/* Allocate pages for the frame buffer. */
addr -= size;
debug ("Reserving %ldk for LCD Framebuffer at: %08lx\n", size>>10, addr);
return (addr);
}
#endif /* CONFIG_LCD */


调用fimd.c中的初始化代码LCD有显示,但是不能在指定位置显示数据,是lcd配置的问题,原来它的配置是1366*768.

对照s5pc210处理器的datasheet,给LCD初始化过程做注释,代码如下:

void LCD_Initialize_NONAME1(void)
{
u32 uFbAddr = CFG_LCD_FBUFFER;
u32 i;
u32* pBuffer = (u32*)uFbAddr;

Outp32(0xe0200040, 0x10000000);  //GPBCON [31:28]:output [27:0]:input
Outp32(0xe0200048, 0x1555);  //GPBPUD GPBPUD[7]:Pull-up/ down disabled GPBPUD[6:0]:Pull-down enabled
Outp32(0xe020004c, 0xc000);  //GPBDRV GPBDRV[7]:4x  GPBDRV[6:0]:1x
Outp32(0xe0200040, 0x10010000); //GPBCON [31:28],[19:16]:output [27:20],[15:0]:input
Outp32(0xe0200048, 0x1455); //GPBPUD GPBPUD[7],[4]:Pull-up/ down disabled ,GPBPUD[6:5][3:0]:Pull-down enabled
Outp32(0xe020004c, 0xc300);  //GPBDRV GPBDRV[7],[4]:4x  GPBDRV[6:5][3:0]:1x
Outp32(0xe0200040, 0x10110000); //GPBCON [31:28],[23:20],[19:16]:output [27:24],[15:0]:input
Outp32(0xe0200048, 0x1055);  //GPBPUD GPBPUD[7],[5][4]:Pull-up/ down disabled ,GPBPUD[6][3:0]:Pull-down enabled
Outp32(0xe020004c, 0xcf00); //GPBDRV GPBDRV[7],[5],[4]:4x  GPBDRV[6][3:0]:1x
Outp32(0xe02000c0, 0x1); //GPD1CON [23:4]:input [3:0]:output
Outp32(0xe02000c8, 0x54); //GPD1PUD GPD1PUD[5:4],[0]:Pull-up/ down disabled ,GPBPUD[3:1]:Pull-down enabled
Outp32(0xe02000cc, 0x3); //GPD1DRV GPD1DRV[0]:4x  GPBDRV[5:1]:1x
Outp32(0xe02000c0, 0x11); //GPD1CON [23:8]:input [7:0]:output
Outp32(0xe02000c8, 0x50); //GPD1PUD GPD1PUD[5:4],[1:0]:Pull-up/ down disabled ,GPBPUD[3:2]:Pull-down enabled
Outp32(0xe02000cc, 0xf); //GPD1DRV GPD1DRV[1:0]:4x  GPBDRV[5:2]:1x
Outp32(0xe02000a0, 0x1001); //GPD0CON GPD0CON[3],[0]:output GPD0CON[2:1]:input  
Outp32(0xe02000a8, 0x15);  //GPD0PUD GPD0PUD[3]:Pull-up/ down disabled,GPD0PUD[2:0]:Pull-down enabled
Outp32(0xe02000ac, 0xc0); //GPD0DRV GPD0DRV[3]:4x,GPD0DRV[2:0]:1x
Outp32(0xe0200c00, 0x1000010); // GPH0CON GPH0CON[6],[1]:output,GPH0CON[7],[5:2],[0]:input  
Outp32(0xe0200c08, 0x4455);  // GPH0PUD GPH0PUD[6],[4]:Pull-up/ down disabled GPH0PUD[7],[5],[4:0]:Pull-down enabled
Outp32(0xe0200c0c, 0x3000);  // GPH0DRV GPH0DRV[6]:4x GPH0DRV[7],[5:0]:1x
Outp32(0xe0200040, 0x11110000); //GPBCON [31:16]:output [15:0]:input
Outp32(0xe0200048, 0x55);  //GPBPUD GPBPUD[7:4]:Pull-up/ down disabled GPBPUD[3:0]:Pull-down enabled
Outp32(0xe020004c, 0xff00);  //GPBDRV GPBDRV[7:4]:4x  GPBDRV[3:0]:1x
Outp32(0xe0200040, 0x11110100);  //GPBCON [31:16],[11:8]:output [15:12],[7:0]:input
Outp32(0xe0200048, 0x55);  //GPBPUD GPBPUD[7:4]:Pull-up/ down disabled GPBPUD[3:0]:Pull-down enabled
Outp32(0xe020004c, 0xff00);  //GPBDRV GPBDRV[7:4]:4x  GPBDRV[3:0]:1x
Outp32(0xe0200044, 0x80);  //GPBDAT GPBDAT[7]=1,GPBDAT[6:0]=0  
Outp32(0xe0200044, 0x98);  //GPBDAT GPBDAT[7],[4:3]=1,GPBDAT[6:5],[2:0]=0
Outp32(0xe0200044, 0xb9);  //GPBDAT GPBDAT[7],[5:3],[0]=1,GPBDAT[6],[2:1]=0
Outp32(0xe0200044, 0xbb);  //GPBDAT GPBDAT[7],[5:3],[1:0]=1,GPBDAT[6],[2]=0
Outp32(0xe0200044, 0xbb);  //GPBDAT GPBDAT[7],[5:3],[1:0]=1,GPBDAT[6],[2]=0
Outp32(0xe02000a4, 0xd); //GPD0DAT GPD0DAT[3:2],[0]=1,GPD0DAT[1]=0  
Outp32(0xe0200c04, 0xd1);  //GPH0DAT[7:6],[4],[0]=1,GPH0DAT[5],[3:1]=0  
Outp32(0xe0200044, 0xfb);  //GPBDAT GPBDAT[7:3],[1:0]=1,GPBDAT[2]=0
Outp32(0xe0200044, 0xff);  //GPBDAT GPBDAT[7:0]=1
Outp32(0xe0200c04, 0x91);  //GPH0DAT[7],[4],[0]=1,GPH0DAT[6:5],[3:1]=0
Outp32(0xe0200c04, 0xd1);  //GPH0DAT[7:6],[4],[0]=1,GPH0DAT[5],[3:1]=0
Outp32(0xe0200c04, 0xd3);  //GPH0DAT[7:6],[4],[1:0]=1,GPH0DAT[5],[3:2]=0

Outp32(0xe0200120, 0x22222222);//set GPF0[0:7] as HSYNC,VSYNC,VDEN,VCLK,VD[0:3]
Outp32(0xe0200128,0x0);//set pull-up,down disable
Outp32(0xe0200140, 0x22222222);//set GPF1CON[7:0]  as VD[11:4]
Outp32(0xe0200148,0x0);//set pull-up,down disable
Outp32(0xe0200160, 0x22222222);//set GPF2CON[7:0] as VD[19:12]
Outp32(0xe0200168,0x0);//set pull-up,down disable
Outp32(0xe0200180, 0x00002222);//set GPF3CON[3:0]  as VD[23:20]
Outp32(0xe0200188,0x0);//set pull-up,down disable

//--------- S5PC110 EVT0 needs MAX drive strength---------//
Outp32(0xe020012c,0xffffffff);//set GPF0 drive strength max by WJ.KIM(09.07.17)
Outp32(0xe020014c,0xffffffff);//set GPF1 drive strength max by WJ.KIM(09.07.17)
Outp32(0xe020016c,0xffffffff);//set GPF2 drive strength max by WJ.KIM(09.07.17)
Outp32(0xe020018c,0x3ff);//set GPF3 drive strength max by WJ.KIM(09.07.17)

Outp32(0xe0107008,0x2); //DISPLAY_CONTROL output path RGB=FIMD I80=FIMD ITU=FIMD
Outp32(0xe0100204,0x700000); //CLK_SRC1 fimdclk = EPLL
Outp32(0xf8000004, 0x60);  //VIDCON1  HSYNC pulse Inverted,VSYNC pulse Inverted 
// Outp32(0xf8000010, 0xe0e0305);  //VIDTCON0  VBPDE=14,VBPD=14,VFPD=3,VSPW=5
Outp32(0xf8000010, 0x60400);  //VIDTCON0  VBPDE=0,VBPD=6,VFPD=4,VSPW=0
Outp32(0xf8000014, 0x3103020);  //VIDTCON1  VFPDE=3,HBPD=16,HFPD=48,HSPW=32

// Outp32(0xf8000170, 0x0);  //DITHMODE  Disables dithering 
Outp32(0xf8000018, 0xefb1f);  //VIDTCON2   0xefb1f:HOZVAL=799  LINEVAL=479,800*480;     0x17fd55:HOZVAL=1365  LINEVAL=767,1366*768;
// Outp32(0xf8000000, 0x0);  //VIDCON0 RGB interface 0 + RGB parallel format + Normal: RGBORDER[2] @VIDCON3 + VCLK Free Run :Normal mode 
                                  //video clock source:HCLK 
// Outp32(0xf8000000, 0x254); //VIDCON0
// Outp32(0xf8000130, 0x20);  //VIDINTCON0 FIFO Interrupt Window 0 control = enables 
/* Outp32(0xf8000020, 0x0);  //WINCON0 Window 0 Buffer set 0 
Outp32(0xf8000024, 0x0);  //WINCON1 Window 1 Buffer set 0
Outp32(0xf8000028, 0x0);  //WINCON2 Window 2 Buffer set 0
Outp32(0xf800002c, 0x0);  //WINCON3 Window 3 Buffer set 0
Outp32(0xf8000030, 0x0);  //WINCON4 Window 4 Buffer set 0
Outp32(0xf8000034, 0x0);
Outp32(0xf8000180, 0x0);
Outp32(0xf8000184, 0x0);
Outp32(0xf8000188, 0x0);
Outp32(0xf800018c, 0x0);
Outp32(0xf8000190, 0x0);
Outp32(0xf8000140, 0x0);
Outp32(0xf8000148, 0x0);
Outp32(0xf8000150, 0x0);
Outp32(0xf8000158, 0x0);
Outp32(0xf8000058, 0x0);
Outp32(0xf8000208, 0x0);
Outp32(0xf800020c, 0x0);
Outp32(0xf8000068, 0x0);
Outp32(0xf8000210, 0x0);
Outp32(0xf8000214, 0x0);
Outp32(0xf8000078, 0x0);
Outp32(0xf8000218, 0x0);
Outp32(0xf800021c, 0x0);
Outp32(0xf8000088, 0x0);
Outp32(0xf8000220, 0x0);
Outp32(0xf8000224, 0x0);  */
// Outp32(0xf8000260, 0x1);  //BLENDCON BLEND_NEW=8-bit alpha value
// Outp32(0xf8000200, 0xffffff); //VIDW0ALPHA0  Window 0 Alpha0
// Outp32(0xf8000204, 0xffffff);  //VIDW0ALPHA1  Window 0 Alpha1
// Outp32(0xf8000034, 0x0);
// Outp32(0xf8000020, 0x802c);
Outp32(0xf80000a0, uFbAddr + 0x00000000);
Outp32(0xf80000d0, uFbAddr + 0x00177000);  //buffer size  0x00177000:800*480*4   0x00400800:1366*768*4
// Outp32(0xf80000a4, uFbAddr + 0x00000000);
// Outp32(0xf80000d4, uFbAddr + 0x00400800);
// Outp32(0xf80020a0, uFbAddr + 0x00000000);
// Outp32(0xf80020d0, uFbAddr + 0x00400800);
Outp32(0xf8000100, 0xc80); //VIDW00ADD2  0xc80:PAGEWIDTH_F=800*4 0x1558:PAGEWIDTH_F=1366*4
Outp32(0xf8000040, 0x0); //VIDOSD0A 配置窗口位置寄存器A 和 B win0左上角的X、Y坐标(0,0)
Outp32(0xf8000044, 0x18f9df);//VIDOSD0B win0右下角角的X、Y坐标(799,479)
Outp32(0xf8000048, 0x5dc00);  //VIDOSD0C  0x5dc00:OSDSIZE=800*480    0x100200:OSDSIZE=1366*768

// Outp32(0xf8000020, 0x802d);
// Outp32(0xf8000034, 0x1);
Outp32(0xf8000020, 0x802d); //WINCON0 ENWIN_F=1,ALPHA_SEL_F=0,BPPMODE_F=Unpacked 24 bpp,WSWP_F =1
Outp32(0xf8000034, 0x1);  //VIDOSD0C  C0_EN_F=Enables Channel 0
// Outp32(0xf8000000, 0x257);
// Outp32(0xf8000000, 0x57); //===> MPLL should be 667 !!!!
Outp32(0xf8000000, 0x53); //ENVID_F=1,ENVID=1,CLKDIR=Divided by CLKVAL_F ,CLKVAL_F=1
Outp32(0xf80001a4, 0x3);  //TRIGCON 

// LCD_setprogress(0);
}

原来代码中有些配置是重复的,已经注释掉了,可以正常显示。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值