LCD driver based on s5pv-210 Development Board

Source: Internet
Author: User

LCD Hardware principle:

The monitor made of liquid crystal is called LCD, which can be divided into static drive, simple matrix drive and active matrix drive 3 kinds According to drive mode . Among them, the simple matrix can be subdivided into the torsional column type ( TN) and the ultra-torsional type ( STN) Two , while the active matrix is based on the thin-film transistor type (TFT).
TftScreen is the mainstream of the current embedded system application,The Typical timing of TFT screen is given. The VCLK, HSYNC, and VSYNC in the timing diagram are pixel clock signals (pixel clocks used to latch image data), line synchronization signals, and frame synchronization signals, which are Vden as valid signal signals for data. VD is the data signal of the image.


as frame synchronization Signal vsync HSYNC Each pulse indicates a new line of image data to start sending. In frame synchronization and line The synchronization must have a back sweep time. Such scheduling originated in crt The time required to monitor the electron gun deflection, but later became the de facto industry standard, so tft


How to write LCD driver?

1. Assigning a fb_info structure: framebuffer_alloc

2. Settings

 /* Configure FB_INFO Member */* Fix fixed parameter */strcpy (lcd_info->fix.id, "S5PV210_LCD");      Lcd_info->fix.smem_len = 800*480*4;      Lcd_info->fix.type = Fb_type_packed_pixels;      Lcd_info->fix.visual = Fb_visual_truecolor;        Lcd_info->fix.line_length = 800*4;      /* var variable parameter */lcd_info->var.xres = 800;      Lcd_info->var.yres = 480;      lcd_info->var.xres_virtual = 800;      lcd_info->var.yres_virtual = 480;        Lcd_info->var.bits_per_pixel = 32;      Lcd_info->var.red.offset = 16;      Lcd_info->var.red.length = 8;      Lcd_info->var.green.offset = 8;      Lcd_info->var.green.length = 8;      Lcd_info->var.blue.offset = 0;      Lcd_info->var.blue.length = 8;        Lcd_info->var.activate = Fb_activate_now;      Lcd_info->screen_size = 800*480*4;        Lcd_info->pseudo_palette = Pseudo_palette;   Lcd_info->fbops = &lcd_fbops; <span style= "FONT-FAMILY:TIMESNEWROMANPSMT;" >fbops <span style= "fOnt-family:simsun; " > Pointer to a function that points to the underlying operation <br style= "ORPHANS:2; Text-align:-webkit-auto; Widows:2; "/></span></span>

3. Hardware-related operations

Map the corresponding registers according to the schematic diagram:



/* Configure Hardware Resources *      /* Mapped memory *      /Display_control = Ioremap (0xe0107008,4);      Gpf0con      = Ioremap (0xe0200120, 4);      Gpf1con      = Ioremap (0xe0200140, 4);      Gpf2con      = Ioremap (0xe0200160, 4);      Gpf3con      = Ioremap (0xe0200180, 4);            Gpd0con      = Ioremap (0xe02000a0, 4);      Gpd0dat      = Ioremap (0XE02000A4, 4);            Vidcon0      = Ioremap (0xf8000000, 4);      Vidcon1      = Ioremap (0xf8000004, 4);      Vidtcon0     = Ioremap (0xf8000010, 4);      Vidtcon1     = Ioremap (0xf8000014, 4);      Vidtcon2     = Ioremap (0xf8000018, 4);      Wincon0      = Ioremap (0xf8000020, 4);      vidosd0a     = Ioremap (0xf8000040, 4);      vidosd0b     = Ioremap (0xf8000044, 4);      vidosd0c     = Ioremap (0xf8000048, 4);      vidw00add0b0 = Ioremap (0xf80000a0, 4);      vidw00add1b0 = Ioremap (0xf80000d0, 4);      Shodowcon    = Ioremap (0xf8000034, 4);  


View the chip manuals and configure the GPIO, for example:


/* Config gpio*/      *gpf0con = 0x22222222;      *gpf1con = 0x22222222;      *gpf2con = 0x22222222;      *gpf3con = 0x22222222;      *gpd0con &= ~0xf;      *gpd0con |= 0x1;      *gpd0dat |= 1<<0;      *display_control = 2<<0;  


/* Enable clock *      /LCD_CLK = Clk_get (NULL, "LCD");      if (!LCD_CLK | | Is_err (LCD_CLK)) {          PRINTK (kern_info "failed to get LCD clock source\n");      }  


According to the chip manual and schematic diagram, configure the appropriate registers:




Timing diagram, as follows:


 /* Configure LCD Controller *///VCLK = HCLK/(clkval+1), where Clkval >= 1 hclk=200mhz vclk=clock Frequency=40mhz clkval=4    *vidcon0 &= ~ (0xFF << 6 | 1 << 4); Data |= vidcon0_clkval_f (Clkdiv-1) |    Vidcon0_clkdir; *vidcon0 |= (3 << 6) |   (1 << 4);       #define VIDCON0_CLKVAL_F (_x) ((_x) << 6) clkval=3; *vidcon0 |= (1 << 1) |    (1 << 0);      *vidcon1 = 0x04;   Writel (Pd->vidcon1, Vidcon1);//writel (0x04, Vidcon1); /*data = VIDTCON0_VBPD (var->upper_margin-1) | VIDTCON0_VFPD (var->lower_margin-1) |   VIDTCON0_VSPW (var->vsync_len-1); Writel (data, regs + Sfb->variant.vidtcon); *//*data = VIDTCON1_HBPD (var->left_margin-1) | VIDTCON1_HFPD (var->right_margin-1) |   VIDTCON1_HSPW (var->hsync_len-1); Writel (data, regs + Sfb->variant.vidtcon + 4); *//*data = Vidtcon2_lineval (var->yres-1) |   Vidtcon2_hozval (VAR-&GT;XRES-1); Writel (data, regs + Sfb->variant.vidtcon + 8); *//*VBPD [23:16]Vertical back Porch Specifies the number of inactive lines at TheStart for a frame after Vertical synchronization period. 0X00VFPD [15:8] Vertical front porch Specifies the number of inactive lines at the EndOf a frame before Vertical Synchroni Zation period.    0x00*///tvbp = 22; /*TVFP = TVP-TVW-TVBP-TW = 635-1-22-480 =125*/*vidtcon0 = (<< 16) |  (<< 8); *vidtcon0 = (<< 16) |      (<< 8); /*HBPD [23:16] Horizontal back porch Specifies the number of VCLK Periodsbetween the falling edge of HSYNC and start of AC tive data. 0X00HFPD [15:8] Horizontal front porch Specifies the number of VCLK Periodsbetween the end of active data and rising edge of HSYNC. *///THBP = 45;/*THFP = THP-THW-THBP-THV = 1056-1-45-800 = 210*/*vidtcon1 = (<< 16) | (<< 8); *vidtcon1 = (<< 16) |     (<< 8); *vidtcon2 = (479 << 11) |  (799 << 0); Hozval = (horizontal display size)-1; LINeval = (Vertical display size)-1 *wincon0 &= ~ (0xf<<2);  *wincon0 |= (0XB&LT;&LT;2); Select BPP *vidosd0a = (0<<11) |  (0<<0); Upper left corner coordinate *vidosd0b = (799<<11) |  (479<<0);   Lower right corner coordinates *vidosd0c = 480*800; specified window size//Physical Address Lcd_info->screen_base = Dma_alloc_writecombine (Null,lcd_info->fix.smem_len, (dma_addr_t *) &            amp; (lcd_info->fix.smem_start), Gfp_kernel);      *vidw00add0b0 = lcd_info->fix.smem_start;        *vidw00add1b0 = Lcd_info->fix.smem_start + lcd_info->fix.smem_len;     *shodowcon = 0x1;

4. Registration: Register_framebuffer

ret = Register_framebuffer (lcd_info);  



The full LCD driver is as follows:

 #include <linux/module.h> #include <linux/fb.h> #include <linux/dma-mapping.h> #include <linux/c  lk.h> static struct Fb_info *lcd_info;    unsigned long pseudo_palette[16];    unsigned long *display_control;  volatile unsigned long* Gpf0con;  volatile unsigned long* Gpf1con;  volatile unsigned long* Gpf2con;  volatile unsigned long* Gpf3con;  volatile unsigned long* Gpd0con;  volatile unsigned long* gpd0dat;  volatile unsigned long* vidcon0;  volatile unsigned long* vidcon1;  volatile unsigned long* vidtcon0;  volatile unsigned long* vidtcon1;  volatile unsigned long* vidtcon2;  volatile unsigned long* wincon0;  volatile unsigned long* vidosd0a;  volatile unsigned long* vidosd0b;  volatile unsigned long* vidosd0c;  volatile unsigned long* vidw00add0b0;  volatile unsigned long* vidw00add1b0;    volatile unsigned long* Shodowcon;      struct CLK *lcd_clk; static inline unsigned int chan_to_field (unsigned int chan, struct Fb_bitfield *bf) {chan & = 0xFFFF;      Chan >>= 16-bf->length;  Return Chan << bf->offset; } static int Lcdfb_setcolreg (unsigned int regno, unsigned int red, unsigned int green, unsigned int b            Lue, unsigned int transp, struct fb_info *info) {unsigned int val;        if (Regno >) return 1;      /* Use Red,green,blue to construct val */val = Chan_to_field (red, &info->var.red);      Val |= Chan_to_field (Green, &info->var.green);            Val |= Chan_to_field (Blue, &info->var.blue);      ((U32 *) (Info->pseudo_palette)) [Regno] = val;      Pseudo_palette[regno] = val;  return 0; } static struct Fb_ops lcd_fbops = {. Owner = This_module,. Fb_setcolreg = Lcdfb_setcolreg,. Fb_f    Illrect = Cfb_fillrect,. Fb_copyarea = Cfb_copyarea,. fb_imageblit = Cfb_imageblit,};        static int lcd_init (void) {int ret; /* Assign Fb_info */lcd_info = FramebuffeR_alloc (0, NULL);          if (Lcd_info = = NULL) {PRINTK (kern_err "Alloc framebuffer failed!\n");      Return-enomem;      }/* Configure FB_INFO Members */* fix */strcpy (lcd_info->fix.id, "S5PV210_LCD");      Lcd_info->fix.smem_len = 800*480*4;      Lcd_info->fix.type = Fb_type_packed_pixels;      Lcd_info->fix.visual = Fb_visual_truecolor;        Lcd_info->fix.line_length = 800*4;      /* var */lcd_info->var.xres = 800;      Lcd_info->var.yres = 480;      lcd_info->var.xres_virtual = 800;      lcd_info->var.yres_virtual = 480;        Lcd_info->var.bits_per_pixel = 32;      Lcd_info->var.red.offset = 16;      Lcd_info->var.red.length = 8;      Lcd_info->var.green.offset = 8;      Lcd_info->var.green.length = 8;      Lcd_info->var.blue.offset = 0;      Lcd_info->var.blue.length = 8;        Lcd_info->var.activate = Fb_activate_now;      Lcd_info->screen_size = 800*480*4; Lcd_info->pseudo_palette = Pseudo_Palette      Lcd_info->fbops = &lcd_fbops;      /* Configure Hardware Resources */* mapped memory */Display_control = Ioremap (0xe0107008,4);      Gpf0con = Ioremap (0xe0200120, 4);      Gpf1con = Ioremap (0xe0200140, 4);      Gpf2con = Ioremap (0xe0200160, 4);            Gpf3con = Ioremap (0xe0200180, 4);      Gpd0con = Ioremap (0xe02000a0, 4);            Gpd0dat = Ioremap (0XE02000A4, 4);      Vidcon0 = Ioremap (0xf8000000, 4);      Vidcon1 = Ioremap (0xf8000004, 4);      Vidtcon0 = Ioremap (0xf8000010, 4);      Vidtcon1 = Ioremap (0xf8000014, 4);      Vidtcon2 = Ioremap (0xf8000018, 4);      Wincon0 = Ioremap (0xf8000020, 4);      vidosd0a = Ioremap (0xf8000040, 4);      vidosd0b = Ioremap (0xf8000044, 4);      vidosd0c = Ioremap (0xf8000048, 4);      vidw00add0b0 = Ioremap (0xf80000a0, 4);      vidw00add1b0 = Ioremap (0xf80000d0, 4);            Shodowcon = Ioremap (0xf8000034, 4);      /* Config gpio*/*gpf0con = 0x22222222; *gpf1con= 0x22222222;      *gpf2con = 0x22222222;      *gpf3con = 0x22222222;      *gpd0con &= ~0xf;      *gpd0con |= 0x1;      *gpd0dat |= 1<<0;      *display_control = 2<<0;      /* Enable clock */LCD_CLK = Clk_get (NULL, "LCD"); if (!LCD_CLK | |      Is_err (LCD_CLK)) {PRINTK (kern_info "failed to get LCD clock source\n");       } clk_enable (LCD_CLK);    /* Configure LCD Controller *///VCLK = HCLK/(clkval+1), where Clkval >= 1 hclk=200mhz vclk=clock Frequency=40mhz clkval=4    *vidcon0 &= ~ (0xFF << 6 | 1 << 4); Data |= vidcon0_clkval_f (Clkdiv-1) |    Vidcon0_clkdir; *vidcon0 |= (3 << 6) |   (1 << 4);       #define VIDCON0_CLKVAL_F (_x) ((_x) << 6) clkval=3; *vidcon0 |= (1 << 1) |    (1 << 0);      *vidcon1 = 0x04;   Writel (Pd->vidcon1, Vidcon1);//writel (0x04, Vidcon1); /*data = VIDTCON0_VBPD (var->upper_margin-1) | VIDTCON0_VFPD (var->lower_margin-1) |   VIDTCON0_VSPW (var->vsync_len-1); Writel (Data, regs + Sfb->variant.vidtcon); *//*data = VIDTCON1_HBPD (var->left_margin-1) | VIDTCON1_HFPD (var->right_margin-1) |   VIDTCON1_HSPW (var->hsync_len-1); Writel (data, regs + Sfb->variant.vidtcon + 4); *//*data = Vidtcon2_lineval (var->yres-1) |   Vidtcon2_hozval (VAR-&GT;XRES-1); Writel (data, regs + Sfb->variant.vidtcon + 8); *//*VBPD [23:16] Vertical back porch Specifies the number of inactive Lines at TheStart for a frame after vertical synchronization period. 0X00VFPD [15:8] Vertical front porch Specifies the number of inactive lines at the EndOf a frame before Vertical Synchroni Zation period.    0x00*///tvbp = 22; /*TVFP = TVP-TVW-TVBP-TW = 635-1-22-480 =125*/*vidtcon0 = (<< 16) |  (<< 8); *vidtcon0 = (<< 16) |      (<< 8); /*HBPD [23:16] Horizontal back porch Specifies the number of VCLK Periodsbetween the falling edge of HSYNC and start of AC tive data. 0X00HFPD [15:8] Horizontal front Porch Specifies the number of VCLK Periodsbetween the end of active data and rising edge of HSYNC. *///THBP = 45;/*THFP = THP-THW-THBP-THV = 1056-1-45-800 = 210*/*vidtcon1 = (<< 16) | (<< 8); *vidtcon1 = (<< 16) |     (<< 8); *vidtcon2 = (479 << 11) |  (799 << 0); Hozval = (horizontal display size)-1;      Lineval = (Vertical display size)-1 *wincon0 &= ~ (0xf<<2);  *wincon0 |= (0XB&LT;&LT;2); Select BPP *vidosd0a = (0<<11) |  (0<<0); Upper left corner coordinate *vidosd0b = (799<<11) |  (479<<0);   Lower right corner coordinates *vidosd0c = 480*800; specified window size//Physical Address Lcd_info->screen_base = Dma_alloc_writecombine (Null,lcd_info->fix.smem_len, (dma_addr_t *) &            amp; (lcd_info->fix.smem_start), Gfp_kernel);      *vidw00add0b0 = lcd_info->fix.smem_start;        *vidw00add1b0 = Lcd_info->fix.smem_start + lcd_info->fix.smem_len;        *shodowcon = 0x1;    Open state *wincon0 |= 1;  *vidcon0 |= 3;      /* Register Fb_info */ret = Register_framebuffer (lcd_info);  return ret;      } static void Lcd_exit (void) {Unregister_framebuffer (lcd_info); Dma_free_writecombine (NULL, Lcd_info->fix.smem_len, (void*) lcd_info->screen_base, (dma_addr_t) Lcd_info-&gt        ; fix.smem_start);      Iounmap (Shodowcon);      Iounmap (VIDW00ADD1B0);      Iounmap (vidw00add0b0);      Iounmap (VIDOSD0C);      Iounmap (VIDOSD0B);      Iounmap (vidosd0a);      Iounmap (Wincon0);      Iounmap (Vidtcon2);      Iounmap (Vidtcon1);      Iounmap (Vidtcon0);      Iounmap (Vidcon1);      Iounmap (Vidcon0);      Iounmap (Gpd0dat);      Iounmap (Gpd0con);      Iounmap (Gpf3con);      Iounmap (Gpf2con);      Iounmap (Gpf1con);      Iounmap (Gpf0con);  Framebuffer_release (Lcd_info);  } module_init (Lcd_init);  Module_exit (Lcd_exit);  Module_license ("GPL");

Test:

Remove the original driver and load your own compiled driver.

echo Hello >/dev/tty1//Can see Hello on the LCD
Cat Lcd.ko >/dev/fb0//huaping




LCD driver based on s5pv-210 Development Board

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.