S3C2440 Linux driver transplantation——LCD

Publisher:JoyfulSunflowerLatest update time:2017-09-23 Source: eefocusKeywords:S3C2440 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

PC host: Ubuntu 10.4 and redhat 9.0

Target board: TQ2440 development board Linux kernel: 2.6.30

Screen model: WXCAT35-TG3#001F Resolution: 320X240


This article will introduce how to port LCD devices.

Before porting, configure the kernel and compile the LCD device into the kernel.


1. Transplantation

To port the LCD settings, you only need to modify the data of the two structures located in arch/arm/mach-s3c2440/mach-smdk2440.c.

1.1 s3c2410fb_display structure

The modified content is as follows:



  1. /* LCD driver info */  

  2.   

  3. static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {  

  4.   

  5.     .lcdcon5 = S3C2410_LCDCON5_FRM565 |  

  6.               S3C2410_LCDCON5_INVVLINE |  

  7.               S3C2410_LCDCON5_INVVFRAME |  

  8.               S3C2410_LCDCON5_PWREN |  

  9.               S3C2410_LCDCON5_HWSWP,  

  10.   

  11.     .type = S3C2410_LCDCON1_TFT,  

  12.   

  13.     .width = 320, // 240,  

  14.     .height = 240, // 320,  

  15.   

  16.     .pixclock = 156250,//166667, /* HCLK 60 MHz, divisor 10 */  

  17.     .xres = 320, // 240,  

  18.     .yres = 240, // 320,  

  19.     .bpp = 16,  

  20.     .left_margin = 20,  

  21.     .right_margin = 38, //8,  

  22.     .hsync_len = 30, //4,  

  23.     .upper_margin = 15, //8,  

  24.     .lower_margin = 12, //7,  

  25.     .vsync_len = 3, //4,  

  26. };  


How are the above parameters modified? Let's take a look.


Type indicates the display mode, here it is TFT mode.

Width and height indicate the screen resolution, my resolution is 320X240.

xres and yres are equal to width and height respectively.

bpp means the number of bits per pixel, 16 bits is used here.

The values ​​of the six parameters left_margin, right_margin, hsync_len, upper_margin, lower_margin, and vsync_len are given in the LCD manual. The following figure shows the parameters in the LCD:


Here, I give the corresponding relationship between the above 6 parameters and the data in the LCD manual:


       .left_margin = Hsync front porch = 20

       .right_margin = Hsync back porch = 38

       .hsync_len = Hsync pulse width = 30

       .upper_margin = Vsync back porch = 15

       .lower_margin = Vsync front porch = 12

       .vsync_len = Vsync pulse width = 3

  

The value of pixclock is used to calculate CLKVAL. In the S3C2440 datasheet, the calculation formula for CLKVAL is:

CLKVAL = HCLK / VCLK / 2 -1, where VCLK is Dclk in the figure above, and its value is 6.4MHz.


  1. /* s3c2410fb_activate_var 

  2.  * 

  3.  * activate (set) the controller from the given framebuffer 

  4.  * information 

  5.  */  

  6. static void s3c2410fb_activate_var(struct fb_info *info)  

  7. {  

  8.     struct s3c2410fb_info *fbi = info->par;  

  9.     void __iomem *regs = fbi->io;  

  10.     int type = fbi->regs.lcdcon1 & S3C2410_LCDCON1_TFT; /*regs.lcdcon1 is set in s3c2410fb_check_var*/  

  11.     struct fb_var_screeninfo *var = &info->var;  

  12.     int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock) / 2;  

  13.   

  14.     dprintk("%s: var->xres = %d\n", __func__, var->xres);  

  15.     dprintk("%s: var->yres = %d\n", __func__, var->yres);  

  16.     dprintk("%s: var->bpp = %d\n", __func__, var->bits_per_pixel);  

  17.   

  18.     if (type == S3C2410_LCDCON1_TFT) {  

  19.         s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs);/*Calculate the value that needs to be set to the control register based on var*/  

  20.         --clkdiv;  

  21.         if (clkdiv < 0)  

  22.             clkdiv = 0;  

  23.     } else {  

  24.         s3c2410fb_calculate_stn_lcd_regs(info, &fbi->regs);  

  25.         if (clkdiv < 2)  

  26.             clkdiv = 2;  

  27.     }  

  28.   

  29.     fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv);/*Set CLKVAL*/  

  30.   

  31.     /* write new registers */  

  32.   

  33.     dprintk("new register set:\n");  

  34.     dprintk("lcdcon[1] = 0x%08lx\n", fbi->regs.lcdcon1);  

  35.     dprintk("lcdcon[2] = 0x%08lx\n", fbi->regs.lcdcon2);  

  36.     dprintk("lcdcon[3] = 0x%08lx\n", fbi->regs.lcdcon3);  

  37.     dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4);  

  38.     dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5);  

  39.     /*Fill the calculated value into the LCD controller*/  

  40.     writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID,     

  41.         regs + S3C2410_LCDCON1); /*LCD is still disabled*/  

  42.     writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2);  

  43.     writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3);  

  44.     writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4);  

  45.     writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5);  

  46.   

  47.     /* set lcd address pointers */  

  48.     s3c2410fb_set_lcdaddr(info); /*Set LCD frame buffer start address*/  

  49.   

  50.     fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID,  

  51.     writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1); /*Enable LCD*/  

  52. }  

  53. static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi,  

  54.                       unsigned long pixclk)  

  55. {  

  56.     unsigned long clk = clk_get_rate(fbi->clk); /*Get the current clock frequency (Hz)*/  

  57.     unsigned long long div;  

  58.   

  59.     /* pixclk is in picoseconds, our clock is in Hz 

  60.      * 

  61.      * Hz -> picoseconds is / 10^-12 

  62.      */  

  63.   

  64.     div = (unsigned long long)clk * pixclk;  

  65.     div >>= 12; /* div / 2^12 */  

  66.     do_div(div, 625 * 625UL * 625); /* div / 5^12 */  

  67.   

  68.     dprintk("pixclk %ld, divisor is %ld\n", pixclk, (long)div);  

  69.     return div;  

  70. }  

First, pixclock is passed as a parameter to the s3c2410fb_calc_pixclk function. After the function is executed, clkdiv = clk x pixclk / 10^12 / 2.


Then, because the TFT mode is adopted, clkdiv-1. Finally, we get:

clkdiv = clk X pixclk / 10^12 / 2 - 1, where clk is HCLK, and the LCD module uses HCLK as the clock source.

For easy observation, the calculation formula in the previous datasheet is copied here: CLKVAL = HCLK / VCLK / 2 -1.

We can see that 1/VCLK = pixclk / 10^12, that is, pixclk = 10^12 / VCLK. We already know that VCLK = Dclk = 6.4MHz,

Therefore, pixclk = 156250.

In fact, there is such a passage in the kernel reference document:

The speed at which the electron beam paints the pixels is determined by the
dotclock in the graphics board. For a dotclock of eg 28.37516 MHz (millions
of cycles per second), each pixel is 35242 ps (picoseconds) long:

    1/(28.37516E6 Hz) = 35.242E-9 s

That is to say, the reciprocal of VCLK multiplied by 10^12 is pixclk. The unit picoseconds stands for picoseconds, which is 10^12.

The last parameter, lcdcon5, is the configuration information of register LCDCON5.

S3C2410_LCDCON5_FRM565 means using 565 format.

S3C2410_LCDCON5_PWREN indicates that the PWREN pin output signal is enabled.

S3C2410_LCDCON5_INVVLINE and S3C2410_LCDCON5_INVVFRAME indicate inverting the VLINE/HSYNC and VFRAME/VSYNC signal lines. This can be determined by comparing the LCD manual and the S3C2440 datasheet.

S3C2410_LCDCON5_HWSWP: Since little-endian mode is used, half-word swapping needs to be set.


1.2 s3c2410fb_mach_info structure


The modified content is as follows:


  1. static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = {  

  2.     .displays = &smdk2440_lcd_cfg,  

  3.     .num_displays = 1,  

  4.     .default_display = 0,  

  5.   

  6. #if 0  

  7.     /* currently setup by downloader */  

  8.     .gpccon = 0xaa940659,  

  9.     .gpccon_mask = 0xffffffff,  

  10.     .gpcup = 0x0000ffff,  

  11.     .gpcup_mask = 0xffffffff,  

  12.     .gpdcon = 0xaa84aaa0,  

  13.     .gpdcon_mask = 0xffffffff,  

  14.     .gpdup = 0x0000faff,  

  15.     .gpdup_mask = 0xffffffff,  

  16. #endif  

  17. //no  

  18. // .lpcsel = ((0xCE6) & ~7) | 1<<4,  

  19. };  


The only modification made is to disable lpsel, because if you are not using a Samsung LPC3600/LCC3600 LCD, you must disable LPC3600/LCC3600 mode (write 0 to TCONSEL).


num_displays indicates how many LCD devices there are.

default_display indicates which LCD device this is.


2. Testing

After modifying the above two data structures, compile the kernel directly and then download it to the development board.

You can execute the command fbset, the output is as follows:

mode "320x240-58"

        # D: 6.400 MHz, H: 15.686 kHz, V: 58.097 Hz
        geometry 320 240 320 240 16
        timings 156250 20 38 15 12 30 3
        accel false
        rgba 5/11,6/5,5/0,0/0
endmode

The values ​​above are the parameters we set.

In addition, testing can be performed using the following test procedures:


  1. #include   

  2. #include   

  3. #include   

  4. #include   

  5. #include   

  6. //#include   

  7.   

  8. int main()  

  9. {  

  10.     int fd, retval, i;  

  11.     struct fb_var_screeninfo var;  

  12.     struct fb_fix_screeninfo fix;  

  13.     unsigned short *memstart;  

  14.   

  15.     fd = open("/dev/fb0", O_RDWR);  

  16.     if(fd < 0){  

  17.         printf("open /dev/fb0 failed\n");  

  18.         return -1;  

  19.     }  

  20.       

  21.     retval = ioctl(fd, FBIOGET_FSCREENINFO, &fix);  

  22.     if(retval < 0){  

  23.         printf("ioctl failed\n");  

  24.         return -1;  

  25.     }  

  26.   

  27.     printf("seme len= %d\n", fix.smem_len);  

  28.   

  29.     memstart = mmap(NULL, 240*320*2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  

  30.     if (memstart == MAP_FAILED){  

  31.         printf("mmap wrong\n");  

  32.     }  

  33.       

  34.     for(; ;){  

  35.     sleep(1);  

  36.     for(i = 0; i < (153600>>1); i++)  

  37.         *(memstart + i) = 0xf800;  

  38.     sleep(1);  

  39.     for(i = 0; i < (153600>>1); i++)  

  40.         *(memstart + i) = 0x0c00;  

  41.     }  

  42. }  

The test program is from the Internet, I just modified it slightly.


Keywords:S3C2440 Reference address:S3C2440 Linux driver transplantation——LCD

Previous article:S3C2440 Linux driver transplantation——SPI
Next article:S3C2440 Linux driver transplantation - button

Recommended ReadingLatest update time:2024-11-16 13:28

PIC microcontroller realizes LCD1602 scrolling display of character string
When I first started learning microcontrollers, the scrolling of LCD1602 could only achieve 2 lines moving at the same time, so I changed it and wrote a scrolling program. When testing, I found a problem. The code that worked properly on the learning board went wrong when put on Proteus and could not be displayed norm
[Microcontroller]
PIC microcontroller realizes LCD1602 scrolling display of character string
Discussion on LCD floating point display function
In the learning materials provided with the microcontroller, there are rarely any functions for displaying floating-point numbers, and the operation of displaying floating-point numbers is also quite annoying! General conversion display method Taking the STM32 microcontroller resources, we select the ADC sampling fu
[Microcontroller]
STM32f4---TFTLCD display experimental code (02)
The seventh function to be introduced is the coordinate setting function. The function code is as follows: //Set the cursor position //Xpos: horizontal coordinate //Ypos: vertical coordinate void LCD_SetCursor(u16 Xpos, u16 Ypos) {   if(lcddev.id==0X9341||lcddev.id==0X5310)   {     LCD_WR_REG(lcddev.setxcmd);       LC
[Microcontroller]
S3C2440-Bare Metal Edition-06 | UART data sending and receiving experiment (scan mode)
For more information about RS-232C serial bus communication standards, please refer to another series of special articles: EIA RS-232C Serial Bus Standard Experiment - UART data transmission and reception experiment  1. Look at the schematic to determine how the UART hardware is connected As can be seen from the
[Microcontroller]
S3C2440-Bare Metal Edition-06 | UART data sending and receiving experiment (scan mode)
(II) s3c2440——Serial port experiment
introduce:   Universal Asynchronous Receiver/Transmitter (UART). It is used to transmit serial data. When sending data, the CPU writes parallel data into the UART, and the UART sends it serially on a wire according to a certain format; when receiving data, The UART detects the signal from another wire and places the s
[Microcontroller]
S3C2440 Bare Metal Program Audio
/************************************************ *************** NAME: u2440mon.c DESC: u2440mon entry point,menu,download HISTORY: Mar.25.2002: purnnamu: S3C2400X profile.c is ported for S3C2410X. Mar.27.2002: purnnamu: DMA is enabled. Apr.01.2002:purnnamu: isDownloadReady flag is added.
[Microcontroller]
Driver design of touch screen in Linux input subsystem based on kernel object
    As people's requirements for control continue to increase, capacitive touch screens are widely used because they can support multi-touch. Based on the open source operating system MeeGo developed by Nokia and Intel, this paper uses the Linux input subsystem based on kernel objects to design a touch screen driver.
[Microcontroller]
Driver design of touch screen in Linux input subsystem based on kernel object
Design of extended serial port based on S3C2440 and embedded Linux
With the widespread use of fieldbus and other technologies, serial communication is increasingly used in various occasions. In centralized control systems, communication is required between multiple serial ports, but on general computers, there are only 1 to 3 serial ports. In order to achieve multi-point control, the
[Power Management]
Design of extended serial port based on S3C2440 and embedded Linux
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
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号