《Linux driver: s3c2440 lcd driver analysis》

Publisher:BlossomWhisperLatest update time:2024-07-09 Source: elecfansKeywords:s3c2440  lcd  driver Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

I. Introduction

The content of s3c2440 lcd driver analysis includes the principle of LCD image display, the operation of s3c2440 LCD controller, the example of LCD driver using platform bus-device-driver model, the setting of LCD related parameters, fb character device driver example, framebuffer registration and management, and the complete process analysis of an LCD display.

2. LCD principle and hardware analysis

2.1 LCD Principle Analysis

SDRAM: A continuous memory is applied in SDRAM as the storage of LCD display data, called framebuffer.
LCD controller: The LCD controller is connected to the LCD screen through hardware circuits. LCD
screen: As a peripheral, it is connected to the MCU (pins are configured as LCD pins) through hardware circuits.


When an image is displayed on an LCD screen, it can be seen that the LCD controller first takes out a frame of image data from the video memory and then inputs it to the LCD screen. For a 480*272 screen, a frame displayed has 480*272 pixels, 272 rows, and 480 columns. For each row of pixels, the LCD controller has a VCLK signal control. With each VCLK, the displayed pixel moves one pixel to the right. When it moves to the last pixel in this row, the LCD controller has an HSYNC signal to control the pixel to jump to the first pixel of the next row for display. For a frame of image (also called a field), that is, when the pixel moves to the last position of the last row and is displayed, the LCD controller has a VSYNC signal to control the pixel to move back to the first pixel of the first row to display the next frame of image.

2.2 Hardware Circuit

2.2.1 LCD backlight circuit

To turn on the LCD display, you need to enable KEYBOARD (generally EN means high level is valid, and a horizontal line above EN means low level is valid) to turn on the backlight.


2.2.2 LCD screen

VLINE: HSYNC signal output pin (operated by LCD controller)
VFRAME: VSYNC signal output pin (operated by LCD controller)
VCLK: VCLK signal output pin (operated by LCD controller)
VD3~VD7: B data output pins in RGB (565)
VD10~VD15: G data output pins in RGB (565)
VD19~VD23: R data output pins in RGB (565) TS*: for ts touch screen connection


2.2.3 S3c2440 master control

Involving GPG, GPD, GPC pins.
VM: LCD controller enable pin (configured by the register of the LCD controller). To turn on the LCD display, you need to configure the corresponding bit of the relevant register to enable. LCD_PWREN: LCD power enable pin (configured by the register of the LCD controller). To turn on the LCD display, you need to configure the corresponding bit of the relevant register to enable.


3. LCD Application Platform Bus-Device-Driver Model

3.1 Loading and registering lcd devices

MACHINE_START(S3C2440, "SMDK2440")

/* Maintainer: Ben Dooks */

.phys_io    = S3C2410_PA_UART,

.io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

.boot_params    = S3C2410_SDRAM_PA + 0x100,


.init_irq   = s3c24xx_init_irq,

.map_io     = smdk2440_map_io,

.init_machine   = smdk2440_machine_init,

.timer      = &s3c24xx_timer,

MACHINE_END

Expand the above macro


static const struct machine_desc __mach_desc_SMDK2440

__attribute_used__

__attribute__((__section__(".arch.info.init"))) = {

.nr = MACH_TYPE_SMDK2410, /* architecture number */

.name = "SMDK2440", /* architecture name */

/* Maintainer: Jonas Dietsche */

.phys_io = S3C2410_PA_UART, /* start of physical io */

.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

.boot_params = S3C2410_SDRAM_PA + 0x100, /* tagged list */

.map_io = smdk2440_map_io, /* IO mapping function */

.init_irq = s3c24xx_init_irq,

.init_machine = smdk2440_machine_init,

.timer = &s3c24xx_timer,

}

MACHINE_START mainly defines the type of "struct machine_desc", which is placed in section (".arch.info.init"), and is the initialization data. It will be discarded after the kernel starts. Each member function is called at different times:

1. init_machine is called by customize_machine in arch/arm/kernel/setup.c. It is placed in the arch_initcall() section and will be called automatically in sequence.

2. init_irq is called in start_kernel() -> init_IRQ() -> init_arch_irq().

3. map_io is called in setup_arch() -> paging_init() -> devicemaps_init(). Other functions are mainly used in setup_arch().

When the system is initialized, smdk2440_machine_init is called


static void __init smdk2440_machine_init(void)

{

// Set the LCD parameters here, separate from the driver. In this way, when you want to modify the LCD, you don't need to change the driver layer program, you only need to modify the device layer parameters, which is convenient for transplantation.

s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);


// Register the devices in the smdk2440_devices array to the platform bus

platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));

smdk_machine_init();

}


// smdk2440_devices array

static struct platform_device *smdk2440_devices[] __initdata = {

&s3c_device_usb,

&s3c_device_lcd,

&s3c_device_wdt,

&s3c_device_i2c,

&s3c_device_iis,

&s3c2440_device_sdi,

};


// lcd device

struct platform_device s3c_device_lcd = {

.name         = "s3c2410-lcd",

.id       = -1,

.num_resources    = ARRAY_SIZE(s3c_lcd_resource),

.resource     = s3c_lcd_resource,

.dev              = {

.dma_mask       = &s3c_device_lcd_dmamask,

.coherent_dma_mask  = 0xffffffffUL

}

};


// Set the LCD device parameters smdk2440_lcd_cfg. The meaning of each parameter will be explained later during probe analysis.

/* 480x272 */

static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {

.right = {

.lcdcon1 =  S3C2410_LCDCON1_TFT16BPP |

S3C2410_LCDCON1_TFT |

S3C2410_LCDCON1_CLKVAL(0x04),


.lcdcon2 =  S3C2410_LCDCON2_VBPD(1) |

S3C2410_LCDCON2_LINEVAL(271) |

S3C2410_LCDCON2_VFPD(1) |

S3C2410_LCDCON2_VSPW(9),


.lcdcon3 =  S3C2410_LCDCON3_HBPD(1) |

S3C2410_LCDCON3_HOZVAL(479) |

S3C2410_LCDCON3_HFPD(1),


.lcdcon4 =  S3C2410_LCDCON4_HSPW(40),


.lcdcon5    = S3C2410_LCDCON5_FRM565 |

S3C2410_LCDCON5_INVVLINE |

S3C2410_LCDCON5_INVVFRAME |

S3C2410_LCDCON5_PWREN |

S3C2410_LCDCON5_HWSWP,

},


.gpccon      =  0xaaaaaaaa,

.gpccon_mask    = 0xffffffff,

.gpcup       =  0xffffffff,

.gpcup_mask = 0xffffffff,


.gpdcon      =  0xaaaaaaaa,

.gpdcon_mask    = 0xffffffff,

.gpdup       =  0xffffffff,

.gpdup_mask = 0xffffffff,


.fixed_syncs =  1,

.type        =  S3C2410_LCDCON1_TFT,

.width      = 480,

.height     = 272,


.xres = {

.min    = 480,

.max    = 480,

.defval = 480,

},


.yres = {

.max    =   272,

.min    =   272,

.defval =   272,

},


.bpp    = {

.min    =   16,

.max    =   16,

.defval =   16,

},

};

Call platform_device_register to register the platform device


int platform_add_devices(struct platform_device **devs, int num)

{

int i, ret = 0;


for (i = 0; i < num; i++) {

ret = platform_device_register(devs[i]);

if (ret) {

while (--i >= 0)

platform_device_unregister(devs[i]);

break;

}

}


return ret;

}

3.2 Loading and registering the lcd driver

3.2.1 Compile into kernel and load driver

Compile kernel settings, make menuconfig

-> Device Drivers

-> Graphics support

<*> Support for frame buffer devices

linux-2.6.22.6/.config


CONFIG_FB_S3C2410=y


linux-2.6.22.6/drivers/video/Makefile


obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o


Then make uImage, compile the s3c2410fb driver into the kernel, and it will be loaded when the system starts, that is, the driver's s3c2410fb_init function will be called.

int __devinit s3c2410fb_init(void)

{

// Register to the platform bus driver

return platform_driver_register(&s3c2410fb_driver);

}

3.3 LCD device and driver matching

platform_driver_register->

driver_register->

bus_add_driver->

driver_attach->

bus_for_each_dev->

__driver_attach

__driver_attach(kernel 2.6.22)

static int __driver_attach(struct device * dev, void * data)

{

struct device_driver * drv = data;


/*

* Lock device and try to bind to it. We drop the error

* here and always return 0, because we need to keep trying

* to bind to devices and some drivers will return an error

* simply if it didn't support the device.

*

* driver_probe_device() will spit a warning if there

* is an error.

*/


if (dev->parent)    /* Needed for USB */

down(&dev->parent->sem);

down(&dev->sem);

if (!dev->driver)

driver_probe_device(drv, dev); //Call the probe function of the driver layer program

up(&dev->sem);

if (dev->parent)

up(&dev->parent->sem);


return 0;

}

__driver_attach(kernel 3.4)

static int __driver_attach(struct device *dev, void *data)

{

struct device_driver *drv = data;


/*

* Lock device and try to bind to it. We drop the error

* here and always return 0, because we need to keep trying

* to bind to devices and some drivers will return an error

* simply if it didn't support the device.

*

* driver_probe_device() will spit a warning if there

* is an error.

*/


// Match driver and device

if (!driver_match_device(drv, dev))

return 0;


if (dev->parent)    /* Needed for USB */

device_lock(dev->parent);

device_lock(dev);

if (!dev->driver)

driver_probe_device(drv, dev);

device_unlock(dev);

if (dev->parent)

device_unlock(dev->parent);


return 0;

}

driver_probe_device calls the probe of the driver layer

[1] [2]
Keywords:s3c2440  lcd  driver Reference address:《Linux driver: s3c2440 lcd driver analysis》

Previous article:《Linux driver: s3c2440 lcd driver analysis -- final chapter》
Next article:《Linux driver: s3c2410/s3c2440 ts driver analysis -- final chapter》

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号