Transplantation of LCD driver on TQ2440 platform

Publisher:码字先生Latest update time:2023-06-26 Source: elecfans Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

reference:

http://liu1227787871.blog.163.com/blog/static/205363197201242393031250/

http://blog.csdn.net/cumtgao/article/details/8649006

http://www.360doc.com/content/12/0424/17/9159905_206213245.shtml

http://blog.csdn.net/yj4231/article/details/7878762

 

Hardware platform: TQ2440

LCD model: WXCAT43, resolution 480*270

U-boot version: u-boot-2015.04

Kernel version: Linux-3.14

 

The following mainly completes the transplantation of the LCD driver under Linux.

 

First we need to know some knowledge about LCD:

The LCD we use is TFT type. The following are the signal pins of the S3C2440 LCD controller:

image

 

The following is the LCD schematic diagram of TQ2440:

image

 

The functions of these pins are introduced below:

VCLK: Sends out the LCD clock signal. Each time a clock comes, a pixel will be displayed on the screen.

VLINE: Send LCD line scan signal

VFRAME: Send LCD frame scanning signal

VM: VDEN, pixels will be displayed on the screen only when it is valid

LCD_PWREN: Send LCD panel power enable control signal

VD[3]——VD[7]: LCD data bus

VD[10]——VD[15]: LCD data bus

VD[19]——VD[23]: LCD data bus

 

The meaning of each signal

VSYNC: frame synchronization signal

Each time a pulse is sent out, it means that a new screen of image data begins to be transmitted.

HSYNC: horizontal synchronization signal

Each time a pulse is issued, it indicates that a new line of image data begins to be transmitted.

VCLK: pixel clock signal

Each time a pulse is sent out, it means that a new point of image data starts to be transmitted.

LEND: Line end signal

 

VBPD: Indicates the number of invalid lines after the frame synchronization signal at the beginning of a frame of image, corresponding to the upper_margin in the driver;

VFBD: Indicates the number of invalid lines before the frame synchronization signal after the end of one frame of image, corresponding to the lower_margin in the driver;

VSPW: Indicates the width of the vertical synchronization pulse, the unit is the number of lines

HBPD: Indicates the number of vclks between the start of the horizontal synchronization signal and the start of valid data in a row, corresponding to the left_margin in the driver;

HFPD: Indicates the number of vclks between the end of a row of valid data and the start of the next horizontal synchronization signal, corresponding to the right_margin in the driver;

HSPW: indicates the width of the horizontal synchronization signal, the unit is the number of vclk

 

Let’s understand it by combining the two pictures:

image

 

0_1332308765VvL6.gif

Let’s analyze it based on the LCD chip manual on TQ2440:

image

Pay attention to the description of CLK and H in the text below the above picture, where: CLK represents the pixel clock cycle, and H represents the horizontal synchronization clock cycle. You can find the rules in the picture above:

525=480+2+41+2 Their units are all CLK

286=272+2+10+2 Their units are all H

So the frame rate is: 1/(525*286*pixel clock period) Hz

In this way, we can easily understand the two formulas on S3C2440:

VCLK(Hz) = HCLK/[(CLKVAL+1)x2] Pixel clock frequency (Hz)

Frame Rate = 1/ [ { (VSPW+1) + (VBPD+1) + (LIINEVAL + 1) + (VFPD+1) } x {(HSPW+1) + (HBPD +1)+ (HFPD+1) + (HOZVAL + 1) } x { 2 x ( CLKVAL+1 ) / ( HCLK ) } ]   帧率(Hz)

image

Comparing the two pictures above, we use typical values ​​to fill this structure

static struct s3c2410fb_display tq2440_lcd_cfg __initdata = {

 

    .lcdcon5    = S3C2410_LCDCON5_FRM565 |

              S3C2410_LCDCON5_INVVLINE |

              S3C2410_LCDCON5_INVVFRAME |

              S3C2410_LCDCON5_PWREN |

              S3C2410_LCDCON5_HWSWP,

 

    .type        = S3C2410_LCDCON1_TFT,

 

    .width        = 480,

    .height        = 272,

 

    .pixclock    = 100000,

    .xres = 480,

    .yres = 272,

    .bpp        = 16,

    .left_margin = 2, /* For HBPD+1, here we take typical values ​​*/

    .right_margin    = 2,  /* For HFPD+1  */

    .hsync_len    = 41,    /* For HSPW+1  */

    .upper_margin    = 2,  /* For VBPD+1  */

    .lower_margin    = 2,  /* For VFPD+1  */

    .vsync_len    = 10,    /* For VSPW+1  */

};

 

#define S3C2410_GPCCON_MASK(x)    (3 << ((x) * 2))

#define S3C2410_GPDCON_MASK(x)    (3 << ((x) * 2))

 

static struct s3c2410fb_mach_info tq2440_fb_info __initdata = {

    .displays    = &tq2440_lcd_cfg,

    .num_displays    = 1,

    .default_display = 0,

 

    /* Enable VD[2..7], VD[10..15], VD[18..23] and VCLK, syncs, VDEN

     * and disable the pull down resistors on pins we are using for LCD

     * data. */

 

    .gpcup        = (0xf << 1) | (0x3f << 10),

 

    .gpccon = (S3C2410_GPC1_VCLK | S3C2410_GPC2_VLINE |

               S3C2410_GPC3_VFRAME | S3C2410_GPC4_VM |

               S3C2410_GPC8_VD0   | S3C2410_GPC9_VD1 |

               S3C2410_GPC10_VD2 | S3C2410_GPC11_VD3 |

               S3C2410_GPC12_VD4   | S3C2410_GPC13_VD5 |

               S3C2410_GPC14_VD6   | S3C2410_GPC15_VD7),

 

    .gpccon_mask    = (S3C2410_GPCCON_MASK(1)  | S3C2410_GPCCON_MASK(2)  |

               S3C2410_GPCCON_MASK(3)  | S3C2410_GPCCON_MASK(4)  |

               S3C2410_GPCCON_MASK(8) | S3C2410_GPCCON_MASK(9) |

               S3C2410_GPCCON_MASK(10) | S3C2410_GPCCON_MASK(11) |

               S3C2410_GPCCON_MASK(12) | S3C2410_GPCCON_MASK(13) |

               S3C2410_GPCCON_MASK(14) | S3C2410_GPCCON_MASK(15)),

 

    .gpdup        = (0x3f << 2) | (0x3f << 10),

 

    .gpdcon        = (S3C2410_GPD2_VD10  | S3C2410_GPD3_VD11 |

               S3C2410_GPD4_VD12 | S3C2410_GPD5_VD13 |

               S3C2410_GPD6_VD14 | S3C2410_GPD7_VD15 |

               S3C2410_GPD10_VD18 | S3C2410_GPD11_VD19 |

               S3C2410_GPD12_VD20 | S3C2410_GPD13_VD21 |

               S3C2410_GPD14_VD22 | S3C2410_GPD15_VD23),

 

    .gpdcon_mask    = (S3C2410_GPDCON_MASK(2)  | S3C2410_GPDCON_MASK(3) |

               S3C2410_GPDCON_MASK(4)  | S3C2410_GPDCON_MASK(5) |

               S3C2410_GPDCON_MASK(6)  | S3C2410_GPDCON_MASK(7) |

               S3C2410_GPDCON_MASK(10) | S3C2410_GPDCON_MASK(11)|

               S3C2410_GPDCON_MASK(12) | S3C2410_GPDCON_MASK(13)|

               S3C2410_GPDCON_MASK(14) | S3C2410_GPDCON_MASK(15)),

 

// .lpcsel = ((0xCE6) & ~7) | 1<<4, // Disable lpsel, because if the Samsung LPC3600/LCC3600 LCD is not used, the LPC3600/LCC3600 mode must be disabled (write 0 to TCONSEL).

};

 

 


The next parameter to talk about is pixclock, which is used to calculate the pixel frequency.


In driver/video/s3c2410fb.c:


static void s3c2410fb_activate_var(struct fb_info *info)

{

    struct s3c2410fb_info *fbi = info->par;

    void __iomem *regs = fbi->io;

    int type = fbi->regs.lcdcon1 & S3C2410_LCDCON1_TFT;

    struct fb_var_screeninfo *var = &info->var;

    you clkdiv;

 

    clkdiv = DIV_ROUND_UP(s3c2410fb_calc_pixclk(fbi, var->pixclock), 2);

 

    dprintk("%s: var->xres  = %dn", __func__, var->xres);

    dprintk("%s: var->yres  = %dn", __func__, var->yres);

    dprintk("%s: var->bpp   = %dn", __func__, var->bits_per_pixel);

 

    if (type == S3C2410_LCDCON1_TFT) {

        s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs);

        --clkdiv;

        if (clkdiv < 0)

            clkdiv = 0;

    } else {

        s3c2410fb_calculate_stn_lcd_regs(info, &fbi->regs);

        if (clkdiv < 2)

            clkdiv = 2;

    }

 

    fbi->regs.lcdcon1 |=  S3C2410_LCDCON1_CLKVAL(clkdiv);

 

     ......

}

 


The clkdiv calculated above is CLKVAL in VCLK(Hz) = HCLK/[(CLKVAL+1)x2].


static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi,

                      unsigned long pixclk)

{

    unsigned long clk = fbi->clk_rate;

    unsigned long long div;

 

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

     *

     * Hz -> picoseconds is / 10^-12

     */

 

    div = (unsigned long long)clk * pixclk;

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

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

 

    dprintk("pixclk %ld, divisor is %ldn", pixclk, (long)div);

    return div;

}

First, pixclock is passed to the s3c2410fb_calc_pixclk function as a parameter. After the function is executed,


clkdiv  = (clk * pixclk  / 10^12 + (2 - 1))/ 2。


Then, since TFT mode is used, clkdiv-1 is used. Finally got:


clkdiv  = (clk * pixclk  / 10^12 + (2 - 1))/ 2 - 1,


The clk here is HCLK. The LCD module uses HCLK as the clock source. You can see from the kernel startup code that HCLK is 100MHz.


For the convenience of 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, which means pixclk = 10^12 / VCLK. From the LCD chip manual, we can see that the typical value of VCLK is 9MHz, we take 10MHz.


Therefore, pixclk=100000.


In fact, there is this passage in the kernel reference documentation:


The speed at which the electron beam paints the pixels is determined by the

dotclock in the graphics board. For a dotclock of e.g. 28.37516 MHz (millions

of cycles per second), each pixel is 35242 ps (picoseconds) long:

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


In other words, the reciprocal of VCLK, multiplied by 10^12 is pixclk. The picoseconds unit represents picoseconds, which is 10^12.


 


over.


Reference address:Transplantation of LCD driver on TQ2440 platform

Previous article:Transplantation of u-boot-2015.04 on tq2440 (use spl to boot u-boot)
Next article:How to solve the problem that FrameBuffer console (vc) automatically turns off the display

Recommended ReadingLatest update time:2024-11-16 21:49

The single chip microcomputer adds a PCF8574 module to realize the IIC mode to drive LCD1602
The PCF8574 module makes it possible to realize IIC driving LCD1602. The following figure is the connection circuit diagram of PCF8574 module and 1602: The actual connection method is as follows: If you want to use the PCF8574 module to implement IIC driving LCD1602, it is very necessary to first understand the ti
[Microcontroller]
The single chip microcomputer adds a PCF8574 module to realize the IIC mode to drive LCD1602
Nuvoton M051 drives LCD1602 LCD screen program
Share a program for Nuvoton M051 to drive LCd1602 LCD display:   #include "LCD1602.h" /***************************************************  * A large number of macro definitions to facilitate code porting and reading  ***************************************************/ #define LCD1602_LINE1        0 #de
[Microcontroller]
Simulate 8(COM)*8(SEG) LCD driver on EM78Pxx
;/*===================================================== ; Simulate 8(COM)*8(SEG) LCD driver on EM78Pxx                              ;                                                                              ;                                                                              ;I. LCD scanning princi
[Microcontroller]
STM8L152 LCD module principle and driver
The STM8L182 integrates a driver module for an LCD with up to 320 pixels. The block diagram is as follows: 1. Configure the LCD clock source, division ratio, duty cycle, offset voltage, enable LCD port multiplexing function, definition, and enable LCD function. void LCD_Config(void) {     /* Enable RTC CLK */  
[Microcontroller]
STM8L152 LCD module principle and driver
80x126 pixel LCD driving technology based on PCF8811 design
This article introduces the main features and advantages of PCF8811, block diagram, and several typical application block diagrams. PCF8811 is a low-power 80x126 pixel CMOS LCD controller from NXP, with 80 rows and 128 columns of output, display data RAM 80x128 bits, 8-bit parallel interface, 3/4-way SPI and hig
[Microcontroller]
80x126 pixel LCD driving technology based on PCF8811 design
S3C2440, Linux, LCD driver
When I got to the mysterious LCD driver, I was a little timid, but I had to go on. I made a summary of the Linux driver I just learned. After all, it is something in the Linux kernel, and it is so complicated. I made a summary and wrote down what I learned in my notes so that I won't forget it. Haha! Let’s get started
[Microcontroller]
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号