Linux2.6.32 for Utu2440(5)
Oct 25, 2014
Technology
In this chapter we will continue to migrate driver on LCD, first we want to get the LCD information.
LCD Info
From the LCD we could see “LTV350QV-F0E”, Search it on google and we know it’s SAMSUNG TFT 3.5-inch 320*240 LTV350QV-F0E lcd panel
.
Its datasheet could be downloaded from:
http://www.datasheet-pdf.com/datasheet-html/L/T/V/LTV350QV-F0E_Samsung.pdf.html
TFT means (Thin Film Transistor).
Beware, the kernel we should choose is uImage_T1_F0E_320x240_ts
, because we bought the Package 1 of the development board, they shipped us with Samsung screen .
Code Modification
Kernel configuration modification:
Device Drivers --->
Graphics support --->
<*> Support for frame buffer devices
Support for buffer devices --->
<*> S3C2410 LCD framebuffer support
Backlight & LCD device sipport --->
<*>Lowlevel LCD controls
Display device support --->
<*> Display panel/monitor support
Console display driver support --->
<*> Framebuffer Console support
[*] Framebuffer Console Rotation
[*] Select compiled-in fonts
[*] VGA 8x8 font
[*] VGA 8x16 font
[*] Mini 4x6 font
[*] Sparc console 8x16 font
[*] Bootup logo --->
--- Bootup logo
[*] Standard 224-color Linux logo
arch/arm/mach-s3c2440/mach-smdk2440.c:
static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {
.lcdcon5 = S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVCLK |
S3C2410_LCDCON5_INVVLINE |
S3C2410_LCDCON5_INVVFRAME |
// S3C2410_LCDCON5_PWREN |
S3C2410_LCDCON5_HWSWP,
.type = S3C2410_LCDCON1_TFT,
.width = 320, // 240,
.height = 240, //320,
.pixclock = 100000, //HCLK/10 166667,
.xres = 320, //240,
.yres = 240, //320,
.bpp = 16,
.left_margin = 17, //HFPD+1 20,
.right_margin = 17, //HBPD+1 8,
.hsync_len = 13, //HSPW+1 4,
.upper_margin = 5, //VBPD+1 8,
.lower_margin = 5, //VFPD+1 7,
.vsync_len = 9, //VSPW+1 4,
};
static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = {
.displays = &smdk2440_lcd_cfg,
.num_displays = 1,
.default_display = 0,
//#if 0
.gpccon = 0xaaaa56a9, //0xaa940659,
.gpccon_mask = 0xffffffff,
.gpcup = 0xffffffff, //0x0000ffff,
.gpcup_mask = 0xffffffff,
.gpdcon = 0xaaaaaaaa, //0xaa84aaa0,
.gpdcon_mask = 0xffffffff,
.gpdup = 0xffffffff, //0x0000faff,
.gpdup_mask = 0xffffffff,
//#endif
.lpcsel = 0, //((0xCE6) & ~7) | 1<<4,
};
Enable the lcd:
static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
arch/arm/mach-s3c2410/include/mach/regs-lcd.h:
#define S3C2410_LCDCON1_MMODE (0<<7)
drivers/video/s3c2410fb.c, after around line 52:
//LTV350QV_FOE_V0.0
static void LTV350QV_Short_Delay(u_char time)
{
ndelay(150);
}
#define LTV350QV_FOE 0x1d //device ID
typedef struct _LTV350qv_spi_data_{
unsigned char Device_ID; //ID of the device
unsigned int Index; //index of register
unsigned long Structure; //structure to be writed
}LTV350QV_SPI_Data;
//micro for LTV350QV_FOE
#define CS_H __raw_writel(__raw_readl(S3C2410_GPCDAT) |(1<< 8),S3C2410_GPCDAT)//MAKE_HIGH(LTV350QV_CS)
#define CS_L __raw_writel(__raw_readl(S3C2410_GPCDAT)&~(1<< 8),S3C2410_GPCDAT)//MAKE_LOW(LTV350QV_CS)
#define SCLK_H __raw_writel(__raw_readl(S3C2410_GPCDAT) |(1<< 9),S3C2410_GPCDAT)//MAKE_HIGH(LTV350QV_SCL)
#define SCLK_L __raw_writel(__raw_readl(S3C2410_GPCDAT)&~(1<< 9),S3C2410_GPCDAT)//MAKE_LOW(LTV350QV_SCL)
#define SDI_H __raw_writel(__raw_readl(S3C2410_GPCDAT) |(1<<10),S3C2410_GPCDAT)//MAKE_HIGH(LTV350QV_SDI)
#define SDI_L __raw_writel(__raw_readl(S3C2410_GPCDAT)&~(1<<10),S3C2410_GPCDAT)//MAKE_LOW(LTV350QV_SDI)
#define RST_H __raw_writel(__raw_readl(S3C2410_GPDDAT) |(1<< 0),S3C2410_GPDDAT)//MAKE_HIGH(LTV350QV_RST)
#define RST_L __raw_writel(__raw_readl(S3C2410_GPDDAT)&~(1<< 0),S3C2410_GPDDAT)//MAKE_LOW(LTV350QV_RST)
//
static void LTV350QV_Register_Write(LTV350QV_SPI_Data regdata)
{
u_char i,temp1;
u_int temp2;
u_long temp3;
unsigned long flags;
//write index
temp1=regdata.Device_ID<<2 | 0<<1 | 0<<0; //register index
temp2=regdata.Index;
temp3=(temp1<<24) | (temp2<<8);
local_irq_save(flags);
CS_L;
LTV350QV_Short_Delay(1);
for(i=0;i<24;i++)
{
SCLK_L;
if(temp3 & (1<<(31-i)) ) //if is H
SDI_H;
else
SDI_L;
LTV350QV_Short_Delay(1); //setup time
SCLK_H;
LTV350QV_Short_Delay(1); //hold time
}
CS_H;
LTV350QV_Short_Delay(5);
//write instruction
temp1=regdata.Device_ID<<2 | 1<<1 | 0<<0; //instruction
temp2=regdata.Structure;
temp3=(temp1<<24) | (temp2<<8);
CS_L;
LTV350QV_Short_Delay(1);
for(i=0;i<24;i++)
{
SCLK_L;
if(temp3 & (1<<(31-i)) ) //if is H
SDI_H;
else
SDI_L;
LTV350QV_Short_Delay(1);
SCLK_H;
LTV350QV_Short_Delay(1);
}
CS_H;
local_irq_restore(flags);
}
static void LTV350QV_Write(u_int index, u_int regdata)
{
LTV350QV_SPI_Data WriteData;
WriteData.Device_ID = LTV350QV_FOE;
WriteData.Index = index;
WriteData.Structure = regdata;
LTV350QV_Register_Write(WriteData);
}
static void LTV350QV_Power_ON(void)
{
LTV350QV_Write( 9, 0x0000);
mdelay(150);
LTV350QV_Write( 9, 0x4000);
LTV350QV_Write(10, 0x2000);
LTV350QV_Write( 9, 0x4055);
mdelay(550);
LTV350QV_Write( 1, 0x409d);
LTV350QV_Write( 2, 0x0204);
LTV350QV_Write( 3, 0x0100);
LTV350QV_Write( 4, 0x3000);
LTV350QV_Write( 5, 0x4003);
LTV350QV_Write( 6, 0x000a);
LTV350QV_Write( 7, 0x0021);
LTV350QV_Write( 8, 0x0c00);
LTV350QV_Write(10, 0x0103);
LTV350QV_Write(11, 0x0301);
LTV350QV_Write(12, 0x1f0f);
LTV350QV_Write(13, 0x1f0f);
LTV350QV_Write(14, 0x0707);
LTV350QV_Write(15, 0x0307);
LTV350QV_Write(16, 0x0707);
LTV350QV_Write(17, 0x0000);
LTV350QV_Write(18, 0x0004);
LTV350QV_Write(19, 0x0000);
mdelay(200);
LTV350QV_Write( 9, 0x4a55);
LTV350QV_Write( 5, 0x5003);
}
static void s3c2440fb_init_ltv350qv(void)
{
__raw_writel(0xaa9556a9, S3C2410_GPCCON); //Initialize VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
//LCDVF[0],[1],[2]---output;VD[0],[1],[2]----output.
__raw_writel(0xffffffff, S3C2410_GPCUP); // Disable Pull-up register
LTV350QV_Power_ON() ; //init LCD model
__raw_writel(0xaaaaaaaa, S3C2410_GPDCON);
__raw_writel(0xffffffff, S3C2410_GPDUP);
// __raw_writel(3, S3C2410_LCDINTMSK); // MASK LCD Sub Interrupt
// __raw_writel(0, S3C2410_TPAL); // Disable Temp Palette
// __raw_writel(0, S3C2410_LPCSEL); // Disable LPC3600
}
Then add following sentense before the “return 0” of static int s3c2410fb_init_registers(struct fb_info *info)
:
s3c2440fb_init_ltv350qv();
Now recompile the kernel, you will see framebuffer OK.
Comment all of the function content of drivers/char/vt.c blank_screen_t(unsigned long dummy), this will disable the LCD’s display from closing.
Directly boot from tftp
Avoiding flash into the nand.
>tftp 30000000 uImage
dm9000 i/o: 0x18000300, id: 0x90000a46
> bootm