- First, the principle of LCD hardware
The display LCD made of liquid crystal can be divided into static drive, simple matrix drive and active matrix Drive 3 according to drive mode. The simple matrix type can be used to differentiate the torsional column type (TN) and the ultra-torsional type (STN), while the active matrix is the mainstream of the thin-film transistor type (TFT).
A piece of LCD screen display image not only need LCD driver, also need to have the corresponding LCD controller. Usually the LCD driver conference COF/COG is made with an LCD glass substrate, while the LCD control is implemented by an external circuit. Many MCUs are directly integrated with LCD controls in the north, and the STN and TFT screens can be conveniently controlled via the LCD controller.
The parameters of TFT screen which should be set in LCD controller are given, the upper and lower boundary is the regression time of frame switching, the left border and right convenience are the regression time of row switching, and the horizontal and vertical synchronization are the time required by the line and frame synchronization respectively. Xres and Yres are the horizontal and vertical resolution of the screen respectively, and the LCD resolution of common embedded devices is mainly 320*240, 640*480 and so on.
Second, frame buffer
2.1 Concept of frame buffering
Frame buffering (Framebutter) is an interface provided by the Linux system for display devices, which shows buffer abstraction, shielding the underlying differences in the image hardware, allowing the upper-level application to read and write directly to the display buffer in graphical mode. The user does not have to care about the physical display buffer location and how to store it. These are done by the true buffering device driver itself. For the vibration buffer device, as long as the real buffer finally shows the point corresponding to the region to write the color value, the corresponding color will be automatically displayed on the screen, followed by the display buffer and display point of the corresponding relationship.
The frame buffer device is a standard character device, the main device number bit 29, corresponding to the/DEV/FBN device file. Frame buffer driver is widely used in Linux desktop system, the X window server is the use of frame buffer for window drawing, embedded system qt/embedded and other graphical user interface environment is also based on frame buffer design.
2.2 Displaying buffers and display points
In the frame buffer device, the operation of the screen real point is done by reading and writing display buffer, in different color mode, the display buffer and the actual point on the screen have different correspondence, the following table gives 16 levels of gray, 8-bit color and 16-bit case display buffer and display point corresponding relationship.
The corresponding relationship between the 16 level grayscale display buffer and the display point
-bit |
31~28 |
27~24 |
23~20 |
19~16 |
15~12 |
11~8 |
7~4 |
3~0 |
0x00 |
Point 7 |
Point 6 |
Point 5 |
Point 4 |
Point 3 |
Point 2 |
Point 1 |
Point 0 |
0x04 |
Point 15 |
Point 14 |
Point 13 |
Point 12 |
Point 11 |
Point 10 |
Point 9 |
Point 8 |
... |
... |
... |
... |
... |
... |
... |
... |
... |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8-bit color displays the corresponding relationship between the buffer and the display point
Rgb |
BGR |
7~5 |
4~2 |
1~0 |
7~5 |
4~2 |
1~0 |
R |
G |
B |
|
|
|
16-bit color displays the corresponding relationship between the buffer and the display point
-bit |
15~11 |
10~5 |
4~0 |
RGB565 |
R |
G |
B |
RGB555 |
R |
G |
B |
2.3 Linux frame buffer related data structures and functions
2.3.1 Fb_info Structural Body
struct Fb_info {
int node;
int flags;
struct mutex lock;
struct Fb_var_screeninfo var; /* Variable parameter */
struct Fb_fix_screeninfo fix; /* Fixed parameter */
struct Fb_monspecs monspecs; /* Display Standard */
struct work_struct queue; /* Frame Buffer Event Queue */
struct Fb_pixmap pixmap; /* Image Hardware Mapper */
struct FB_PIXMAP sprite; /* Cursor Hardware mapper */
struct Fb_cmap cmap; /* Current Color Table */
struct Fb_vediomode *mode; /* Current vedio mode */
struct List_head modelist;
#ifdef Config_fb_backlight
/* The corresponding backlight device */
struct Backlight_device *bl_dev;
/* Backlight Adjustment */
struct Mutex Bl_mutex;
U8 Bl_curve[fb_backlight_levels];
#endif
#ifdef CONFIG_FB_DEFERRED_IO
struct Delayed_work deferred_work;
struct Fb_deferred_io *fbdefio;
#endif
struct Fb_ops *fops; /* Fb_ops, Frame buffer operation */
struct device *device; /* Parent Device */
struct device *dev; /* FB Device */
int Class_flag; /* Private SYSFS flag */
#ifdef config_fb_tilebliting
struct Fb_tile_ops *tileops; /* Clod blitting */
#endif
Char __iomem *screen_base;
unsigned long screen_size;
void *pseudo_palette;
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
U32 State;
void *fbcon_ptr;
void *par;
};
The FBI recorded all the information about the frame buffer, including the device's setup parameters, status, and operation function pointers. Each frame buffer device must correspond to an FBI.
2.3.2 Fb_ops Structural Body
The FBI member variable fbops is a function pointer to the underlying operation, which is written by the driver driver and is defined as follows:
struct Fb_ops {
struct module *owner;
/* Open/close function */
Int (*fb_open) (struct fb_info *info, int user);
Int (*fb_close) (struct fb_info *info, int user);
/* Frame buffer devices that do not work for non-linear layouts/general memory mappings are required */
ssize_t (*fb_read) (struct file *file, char __user *buf, size_t count, loff_t *ppos);
ssize_t (*fb_write) (struct file *file, const char __user *buf, size_t count, loff_t *ppos);
/* Detect mutable parameters and adjust to supported values */
Int (*fb_check_var) (struct fb_var_screeninfo *var, struct fb_info *info);
/* Set video mode according to Info->var */
Int (*fb_set_par) (struct fb_info *info);
/* Set COLOR Register */
Int (*fb_setcolreg) (unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info);
/* Set the color register in bulk, set the colour table */
Int (*fb_setcmap) (struct fb_cmap *cmap, struct fb_info *info);
/* Show Blank */
Int (*fb_blank) (int blank, struct fb_info *info);
/* Pan Display */
Int (*fb_pan_display) (struct fb_var_screeninfo *var, struct fb_info *info);
/* Rectangle Fill */
Int (*fb_fillract) (struct fb_info *info, const struct fb_fillrect *rect);
/* Data replication */
void (*fb_copyarea) (struct fb_info *info, const struct Fb_copyarea *region);
/* Graphics Fill */
void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
/* Draw cursor */
Int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
/* Rotate Display */
void (*fb_rotate) (struct fb_info *info, int angle);
/* Wait for blit idle (optional) */
void (*fb_sync) (struct fb_info *info);
/* FB specific IOCTL (optional) */
void (*fb_ioctl) (struct fb_info *info, unsigned int cmd, unsigned long arg);
/* Handle 32-bit COMPAT IOCTL (optional) */
Int (*fb_compat_ioctl) (struct fb_info *info,unsigned cmd, unsigned long arg);
/* FB-specific MMAP */
Int (*fb_mmap) (struct fb_info *info,struct vm_area_struct *vma);
/* Save the current hardware status */
void (*fb_save_state) (struct fb_info *info);
/* Restore the saved hardware status */
void (*fb_get_state) (struct fb_info *info, struct fb_blit_caps *caps, struct fb_var_screeninfo *var);
};
The Fb_ops Fb_check_var () member function checks the screen parameters that can be modified and adjusts to the appropriate values, while Fb_set_par () is the user-set screen parameter that is valid on the hardware.
2.3.3 Fb_var_screeninfo and Fb_fix_screeninfo structural bodies
The FBI's Fb_var_screeninfo and Fb_fix_screeninfo members are also structural, Fb_var_screeninfo records the display controller parameters that users can modify, including the screen resolution and the specific ratio of each pixel point. The parameters of the display controller that the user cannot modify are recorded in Fb_fix_screeninfo, such as the physical address and length of the screen buffer. When the frame buffer device is mapped, the physical address of the buffer is obtained from the fb_fix_screeninfo. All of the above data members need to be initialized and set in the driver.
Fb_var_screeninfo Structural Body
struct Fb_var_screeninfo {
/* Visible Resolution */
U32 xres;
U32 Yres;
/* Virtual Resolution */
U32 xres_virtual;
U32 yres_virtual;
/* Offset between virtual to visible */
U32 Xoffset;
U32 Yoffset;
U32 Bits_per_pixel; /* Number of bits per pixel, BPP */
U32 Qrayscale; / * Non-0 o'clock-point grayscale */
/* r/g/b bit domain of the FB cache */
struct Fb_bitfield red;
struct Fb_bitfield Green;
struct Fb_bitfield blue;
struct Fb_bitfield transp; /* Transparency */
/*! = 0 non-standard pixel format */
U32 nonstd;
U32 activate;
U32 height; /* Height */
U32 width; /* Width */
U32 accel_flags; / * See Fb_info.flags */
/* Timing: Except for the Pixclock itself, the others are in pixel clock units */
U32 Pixclock; /* Pixel clock */
U32 Left_margin; /* Line toggle: Delay from sync to drawing */
U32 Right_margin; /* Line Toggle: Delay from Drawing to synchronization */
U32 Upper_margin; /* Frame Toggle: Delay from sync to drawing */
U32 Lower_margin; /* Frame Toggle: Delay from Drawing to synchronization */
U32 Hsync_len; /* Length of horizontal sync */
U32 Vsync_len; /* Length of vertical sync */
U32 sync;
U32 Vmode;
U32 rotate;
U32 Reserved[5]; / * Reserved */
};
Fb_fix_screeninfo Structural Body
struct Fb_fix_screeninfo {
Char ld[16]; /* Identifier as a string */
unsigned long smem_start; /* The starting position of the FB buffer memory */
U32 Smem_len; /* FB buffer field length */
U32 type; /* Fb_type_ */
U32 Type_aux; / * Interleave */
U32 Visual; /* Fb_visual_ */
U16 XPANSTRP; /* If there is no hardware panning, assign 0 */
U16 Ypanstep;
U16 Ywrapstep;
U32 line_length; /* Number of bytes in 1 rows */
Unsinged long Mmio_start; /* Start location of memory mapped I/O */
U32 Mmio_len; /* Length of memory mapped I/O */
U32 Accel;
U16 Reserved[3];
};
Fb_bitfield Structural Body
struct Fb_bitfield {
__u32 offset; /* bit field offset */
__u32 length; /* bit field length */
__u32 Msb_right; /*!=0; MSB on the right */
};
Fb_cmap Structural Body
The FB_CMAP structure records device-independent color table information, and user space can read or set the color table through the Fbiogetcmap and FBIOPUTCMAP commands of the IOCTL ().
struct fb_cmap{
U32 start; /* First element entry */
U32 Len; /* Number of elements */
/* r,g,b Transparency */
U16 *red;
U16 *green;
U16 *blue;
U16 *TRANSP;
};
2.3.6 file Operation structure Body
struct File_operations fb_ops = {
. Owner = This_module,
. Read = Fb_read,
. write = Fb_write,
. IOCTL = Fb_ioctl,
#ifdef CONFIG_COMPAT
. Compat_ioctl = Fb_compat_ioctl,
#endif
. mmap = Fb_mmap,
. open = Fb_open,
. Release = Fb_release,
#ifdef Have_arch_fb_unmapped_area
. Get_unmapped_area = Get_fb_unmapped_area,
#endif
#ifdef CONFIG_FB_DEFERRED_IO
. Fsync = Fb_deferred_io_fsync,
#endif
};
The driver file operation interface function of the frame buffer device has been implemented uniformly in fbmem.c, which is generally not required by the driver engineer in writing.
2.3.7 registration and main frame buffer device
The Linux kernel provides the Register_framebuffer () and Unregister_framebuffer () functions to register and unregister the framebuffer devices separately, which are the parameters of the FBI pointers for both functions.
int Register_framebuffer (struct fb_info *info);
int Unregister_framebuffer (struct fb_info *info);
Third, Linux frame buffer device drive structure
The main structure of the Linux frame buffer device driver, the file_operations structure provided to the user space by the frame buffer device is provided by File_operation in FBMEM.C, and the specific frame buffer setting Fb_info the registration, logoff and maintenance of the members. In particular, the implementation of member functions in Fb_ops is implemented by the corresponding XXXFB.C file, and the member functions in Fb_ops will eventually operate the LCD controller hardware registers.
Four, frame buffer device-driven module loading and unloading functions
In the module load function of the frame buffer device, the following 4 tasks should be completed:
1. Apply for the memory space of the FBI structure, initialize the fixed and variable screen parameters in the FBI structure, i.e. populate the Fb_var_screeninfo and Fb_fix_screeninfo members of the FBI.
2, according to the specific LCD screen features, complete the LCD controller hardware initialization.
3. Request the display buffer space of the frame buffer device.
4, register the frame buffer device.
In the case of a platform-driven scenario, the release of the FBI structure in vivo, the shutdown of the LCD, the release of the display buffer, and the logoff of the frame buffer device are also transferred to the platform-driven removal function.
static struct Platform_device {
. Proce = Xxxfb_probe,
. remove = Xxxfb_remove,
. Suspend = Xxxfb_suspend,
. Resume = Xxxfn_resume,
. Driver = {
. Name = "XXX-LCD",
. Owner = This_module,
}
};
/* Platform-driven probing function */
static int __init xxxfb_probe (...)
{
struct Fb_info *info;
info = Framebuffer_alloc (...);
Info->screen_var = Xxxfb_var;
Info->fix = xxxfb->fix;
Alloc_dis_buffer (...);
Lcd_init (...);
Xxxfb_check_var (&info->var,info);
if (Register_framebuffer (info) < 0)
{
Return-einval;
}
return 0;
}
static void __exit Xxxfb_remove (...)
{
struct Fb_info *info = dev_get_drv_data (dev);
if (info)
{
Unregister_framebuffer (info);
Dealloc_dis_buffer (...);
Framebuffer_release (info);
}
return 0;
}
static int __init xxxfb_init (void)
{
Return Platfrom_driver_register (&xxxfb_driver);
}
static void __exit xxxfb_exit (void)
{
Platform_driver_unregister (&xxxfb_driver);
}
Five, frame buffer device display buffer application and release
In embedded systems, a common way is to allocate a display buffer directly in RAM space, the typical structure is as follows:
Writecombining means that the write merge, which allows the data to be written to be merged, is temporarily saved in the write-merge buffer until a brust transfer is made and no more single transmissions are required, via Dma_alloc_writeconbine () The allocation of the display buffer does not occur with the cache consistency issue, which is similar to Dma_alloc_coherent ().
static int __init xxxfb_map_video_memory (struct xxxfb_info *fbi)
{
Fbi->map_size = Page_align (fbi->fb->fix.smem_len+page_size);
FBI->MAP_CPU = Dma_alloc_writecombine (Fbi->dev,fbi->map_size,&fbi->map_dma,gfp_kernel);
Fbi->map_size = fbi->fb->fix.smem_len;
if (FBI->MEM_CPU)
{
memset (fbi->mem_cpu,0xf0,fbi->map_size);
FBI->SCREEN_DMA = fbi->map_dma;
Fbi->fb->screen_base = fbi->map_cpu;
Fbi->fb->fix.smem_start = fbi->screen_dma;
}
Return fbi->mem_cpu?0:-enomem;
}
static inline void xxxfb_unmap_vedio_memory (struct s3c2410fb_info *fbi)
{
Dma_free_writeconbine (Fbi->dev, Fbi->map_size, FBI->MAP_CPU, FBI->MAP_DMA);
}
Six, the frame buffer device parameter setting
6.1 Timing Parameters
The Left_margin, Right_margin, Upper_margin, Lower_margin, Hsync_len, and Vsync_len in the FBI structural variable-parameter var can be found directly in the LCD data sheet.
6.2 Megapixel Clock
The Pixclock in the FBI variable parameter var means the pixel clock.
6.3 Color Bit field
6.4 Fixed parameters
The FBI fixed parameter in fix Smem_start indicates that the framebuffer device displays the first address of the buffer, and Smem_len displays the buffer size for the frame buffer device.
Smem_len = max_xres*max_yres*max_bpp.
Fb_ops member function driven by frame buffer device
The FBI's Fb_ops is a collection of functions needed to make the framebuffer work, and they finally deal with the LCD controller hardware.
Fb_check_var () Adjusts the variable parameters and corrects the values supported by the hardware; Fb_set_par () sets the register of the LCD controller according to the screen parameters to allow the LCD controller to enter the corresponding working state. For Fb_fillrect (), Fb_copyarea (), and Fb_imageblit () member functions in Fb_ops, the corresponding generic Cfb_fillrect (), Cfb_copyarea (), and cfb_ are usually used directly Imageblit () function. The Cfb_fillrect () function is defined in the Drivers/vedio/cfbfill.c file. The Cfb_copyarea () function is defined in the Drivers/video/cfbcopyarea.c file. The Cfb_imageblit () function is defined in the Drivers/video/cfbimgblt.c file.
The Fb_setcolreg () member function in Fb_ops implements the fill of the pseudo-color table (for Fb_visual_truecolor, Fb_visual_directcolor mode), and the color table.
static int Xxxfb_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp,
struct Fb_info *info)
{
struct Xxxfb_info *FBI = info->par;
unsigned int val;
Switch (fbi->fb->fix.visual)
{
Case Fb_visual_truecolor:
/* True Color, set to pseudo color table */
if (Regno < 16)
{
U32 *pal = fbi->fb->pseudo_palette;
val = Chan_to_field (red,&fbi->fb->var.red);
Val |= Chan_to_field (Green,&fbi->fb->var.green);
Val |= Chan_to_field (Blue,&fbi->fb->var.blue);
Pal[reqno] = val;
}
Break
Case Fb_visual_pseudocolor:
if (Regno < 256)
{
val = (Red >> 0) & 0xf800;
Val |= (Green >> 5) & 0x7a0;
Val |= (Blue >>) & 0x1f;
Writel (Val,xxx_tftpal (Regno));
Schedule_palette_update (Fbi,regno,val);
}
Break
}
return 0;
}
Viii. read-write, mmap, and IOCTL functions driven by LCD devices
Although the File_operations member function in the frame buffer device, That is, the file operation function has been implemented by the kernel in the fbmem.c file, generally no longer requires the driver engineer to modify, but the analysis of these functions to consolidate the self-read device driver instructions and deepen the understanding of the true buffer device driver is very good spleen.
Static ssize_t fb_read (struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
struct Inode *inode = file->f_path.dentry->d_inode;
int fbidx = Iminor (inode);
struct Fb_info *info = REGISTERED_FB (FBIDX);
U32 *buffer, *DST;
U32 __iomem *src;
int c,i,cnt = 0, err = 0;
unsigned long total_size;
......
Buffer = Kmalloc ((Count > Page_size)? Page_size:count,gfp_kernel);
if (!buffer)
{
Return-enomem;
}
src = (u32 __iomem *) (info->screen_base + p);
if ()
}
Ix. user space for frame buffer devices
With/DEV/DBN, there are several main applications that can be performed on a true buffering device:
- Read/write DEV/DBN: A buffer equivalent to the read/write screen, such as the CP/DEV/FB0 tmp command, which copies the contents of the current screen to a file, while the command CP tmp>/dev/fb0 displays the graphics file tmp on the screen.
- Mapping operation, for a framebuffer device, the physical address of the screen buffer can be mapped to a virtual address in the user space via the mmap () action, after which the user can access the buffer by reading/writing the virtual address and drawing on the screen. and a number of processes can be mapped to the same skilful buffer. In fact, applications that use frame-buffering devices display graphics through mapping operations.
- I/O control: For frame buffer devices, the IOCTL () operation on the device file reads/sets the parameters of the display device and screen, resolution, number of display colors, screen size, etc.
18.6, in the application, the general steps to manipulate/DEV/FBN are as follows:
1. Open/DEV/FBN Device file
2. The parameters of the current display screen with the IOCTL () operation area, such as resolution, specific and offset of each pixel point. Depending on the screen parameters, the screen buffer size can be calculated.
3. Map the screen buffer to the user space.
4. After mapping, you can read/write the screen buffer directly, and make the drawing and picture display.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
int main (void)
{
int FBFD = 0;
struct Fb_var_screeninfo vinfo;
char *fbp = 0;
FBFD = open ("/dev/fb0", O_RDWR);
if (FNFD = = 0)
{
printf ("Error:cannot Open framebuffer device.\n");
return 1;
}
ptintf ("The Frambuffer device was opened successfully.\n");
if (IOCTL (Fbfd,fbioget_vsceeninfo,&vinfo))
{
printf ("error:reading variable information.\n");
return 1;
}
printf ("%dx%d,%dbpp\n", Vinfo.xres,vinfo.yres,vinfo.bits_per_pixel);
if (vinfo.bits_per_pixel! = 16)
{
printf ("Error:not supported Bits_per_pixel,it Onlu supports-bit color.\n");
return 1;
}
FBP = (char *) mmap (0,screensize,prot_read| prot_write,map_shard,fbfd,0);
if ((int) FBP = =-1)
{
printf ("Error:failed to map framebuffer device to memory.\n");
return 4;
}
printf ("The framebuffer device is mapped to memory successfully.\n");
for (i = 0;i < 3;i++)
{
for (y = i* (VINFO.YRES/3), y < (i+1) * (VINFO/YRES/3); y++)
{
for (x = 0;x < vinfo.xres;x++)
{
Long location = x*2 + y * vinfo.res*2;
int r = 0,g = 0, b = 0;
if (i = = 0)
{
R = ((x*1.0)/vinfo.xres) *32;
}
if (i = = 1)
{
g = ((x*1.0)/vinfo.xres) *64;
}
if (i = = 2)
{
B = ((x*1.0)/vinfo.xres) *32;
}
RGB = (r<<11) | (q<<5) |b;
* ((unsigned short *) (FBP + location)) = RGB;
}
}
}
Munmap (fbp,screensize);
Close (FBFD);
return 0;
}
Summarize
The frame buffer device is a typical character device that unifies the video memory and maps the display buffer directly to the user space. The VFS interface function in true buffer device driver File_operations is implemented uniformly by FBMEM.C file. In this way, the driver engineer's work focuses on monitoring the member functions that implement Fb_ops in Fb_ops for a particular device. In addition, it is critical to understand and be able to flexibly modify the Varhe fix parameters in Fb_info. The parameters in the fb_info correspond directly to the LCD controller's hardware device and the LCD screen.
In user space, the application directly follows the pre-set r/g/b and offset write through the mmap () mapped display buffer to achieve graphical display, eliminating the memory from the user space to the kernel space of the replication process.
LCD device Driver