【i.MX6ULL】Driver Development 11——LCD Driver Practice[Copy link]
The LCD driver was mentioned before when porting the Linux system. This article will look at how to configure the LCD driver in the Linux device tree.
1 Knowledge Points
First, you need to understand a new concept: Framebuffer
1.1 Framebuffer
Framebuffer literally means frame buffer, abbreviated as fb. Linux brings together all display-related hardware and software in the system, and abstracts the underlying LCD virtual device into a /dev/fbX device. Applications can control the screen display by operating /dev/fbX.
The NXP official Linux kernel has enabled the LCD driver by default. You can see a device like fb0 in the dev/directory.
struct fb_info {
atomic_t count;
int node;
int flags;
struct mutex lock; /* Lock for open/release/ioctl funcs */
struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */
struct fb_var_screeninfo var; /* 当前的可变参数 */
struct fb_fix_screeninfo fix; /* 当前的固定参数 */
struct fb_monspecs monspecs; /* Current Monitor specs */
struct work_struct queue; /* Framebuffer event queue */
struct fb_pixmap pixmap; /* Image hardware mapper */
struct fb_pixmap sprite; /* Cursor hardware mapper */
struct fb_cmap cmap; /* Current cmap */
struct list_head modelist; /* mode list */
struct fb_videomode *mode; /* current mode */
#ifdef CONFIG_FB_BACKLIGHT
/* assigned backlight device */
/* set before framebuffer registration,
remove after unregister */
struct backlight_device *bl_dev;
/* Backlight level curve */
struct mutex bl_curve_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 *fbops; /* 帧缓冲操作函数集 */
struct device *device; /* This is the parent */
struct device *dev; /* This is this fb device */
int class_flag; /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */
#endif
char __iomem *screen_base; /* 虚拟内存基地址(屏幕显存) */
unsigned long screen_size; /* 虚拟内存大小(屏幕显存大小) */
void *pseudo_palette; /* 伪16位调色板 */
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
u32 state; /* Hardware state i.e suspend */
void *fbcon_par; /* fbcon use-only private area */
/* From here on everything is device dependent */
void *par;
/* we need the PCI or similar aperture base/size not
smem_start/size as smem_start may just be an object
allocated inside the aperture so may not actually overlap */
struct apertures_struct {
unsigned int count;
struct aperture {
resource_size_t base;
resource_size_t size;
} ranges[0];
} *apertures;
bool skip_vt_switch; /* no VT switch on suspend/resume required */
};
Note the fb_fops item in the structure . /dev/fb0 is a character device, and fb_fops is its file operation structure. Its file_operations operation set is in the drivers/video/fbdev/core/fbmem.c file:
You can see familiar function interfaces such as open and release.
Therefore, the focus of LCD driver is to initialize each member in fb_info .
There are many member variables of the fb_info structure, and the following ones need to be focused on:
var: current variable parameter
fix: current fixed parameters
fbops: frame buffer operation function set
screen_base: virtual memory base address (screen video memory)
screen_size: virtual memory size (screen video memory size)
pseudo_palette: pseudo 16-bit palette
After initializing fb_info, register the newly initialized fb_info with the kernel through the register_framebuffer function .
1.2 Introduction to LCD driver file mxsfb
The driver file of LCD is mxsfb.c , which is a platform driver framework. After the driver and device are matched, the mxsfb_probe function will be executed.
LCD initialization is implemented through the mxsfb_probe function , the main functions of this function are:
Apply for fb_info
Initialize each member variable in the fb_info structure
Initialize the eLCDIF controller
Use the register_framebuffer function to register the initialized fb_info with the Linux kernel
This function is located in: /drivers/video/fbdev/mxsfb.c
Return value: 0 - success, negative value - failure
1.3 LCD driver programming
NXP has already written the eLCDIF interface driver for 6ULL, so we don't need to modify the LCD driver part. All we need to do is modify the device tree according to the LCD used.
1.3.1 View the device tree
1.3 Let's first look at the LCD driver for Linux officially written by NXP. Open imx6ull.dtsi and find the content of the lcdif node:
This node information does not need to be modified, and the default configuration can be used. If you want to modify it, do not modify it here, but modify it in the imx6ull-myboard.dts file.
When uboot is started, the NXP logo will be displayed on the upper left corner of the LCD, and when the Linux kernel is started, a small penguin will be displayed on the upper left corner of the LCD. Therefore, the display of the small penguin logo can be used to verify whether the LCD driver is normal.
By default, the logo display is turned on, you can confirm it again.
In the Linux kernel source directory, enter the following command to open the kernel's graphical configuration:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
These three options correspond to the logo in black and white, 16-bit, and 24-bit color formats respectively.
2.2 Compile device tree
After modifying the lcdif node in the device tree (mainly modifying the screen parameters), execute the following command in the Linux kernel source directory to recompile the device tree and copy it to the network boot location.
make imx6ull-myboard.dtb
cp arch/arm/boot/dts/imx6ull-myboard.dtb ~/myTest/tftpboot/nxp/
Then restart the development board, and you can see the penguin icon on the screen when the Linux kernel is driven:
Previously, the serial port was used to display the startup and debugging information of the board. In fact, the LCD can be set as a terminal for synchronous display:
2.3.1 Setting uboot bootargs
Restart the development board, and press recharge during the countdown to enter ubout. You can first look at the previous bootargs configuration:
Comparing the information output by the serial port, we can see that the screen output is nothing after the sentence Freeing unused kernel memory: 400K (8090e000 - 80972000). There is no prompt to press the Enter key to continue , and there is no display to start the printing of the self-starting hello word test program. This is because some settings have not been completed.
Now you can also operate the board on the screen by plugging a keyboard into the board.
Note that the print of the hello word program that was set to start up previously does not appear on the screen because the input of printf is not set in the LCD. We can print on the LCD screen by directing the output to /dev/tty1, such as testing the screen output of hello linux:
When the LCD screen is not operated for a period of time, the screen will automatically go black. At this time, you can wake it up by connecting a keyboard and pressing the Enter key (you can also wake it up through the board's ON/OFF button , because this button is also assigned the function of the Enter key).
This time is set in drivers/tty/vt/vt.c in the Linux source code, and the default is 10 minutes (10*60 seconds).
If you want the screen to stay on all the time, you can set the value to 0, re-edit the Linux kernel to get the zImage, and then use the new zImage to start the development board.
If you do not want to modify zImage, another way is to create an application that starts at startup to control the screen from turning off. The content of lcd_always_on.c is:
After saving, restart the development board and the screen will not turn off automatically.
2.4.2 Screen Brightness Adjustment
The brightness of the screen can also be adjusted. The backlight node in the device tree has 8 levels set, and the brightness can be adjusted in the range of 0 to 7. Enter the following directory to view the current screen brightness:
This article introduces the knowledge related to LCD screen driver and conducts experiments. Because the LCD pins of NXP official board are the same as mine, the main modification is to modify the screen parameters of the lcdif node in the device tree.
Through the experiment, the penguin logo can be displayed, and the output information of the board can be directed to the LCD screen display. By connecting the keyboard, the interaction with the Linux board can be realized. Finally, the screen off and brightness adjustment functions are also tested.
【i.MX6ULL】 Driver development series articles summary entry:
【i.MX6ULL】Driver Development——by DDZZ669 - ARM Technology - Electronic Engineering World - Forum (eeworld.com.cn)
Sub-directories:
【i.MX6ULL】Driver Development 1——Character Device Development Template
【i.MX6ULL】Driver Development 2——New Character Device Development Template
【i.MX6ULL】Driver Development 3——GPIO Register Configuration Principle
【i.MX6ULL】Driver Development 4——Light up the LED (Register Version)
【i.MX6ULL】Driver Development 5——Device Tree Principle and Lighting LED
【i.MX6ULL】Driver Development 6——Pinctrl subsystem and GPIO subsystem light up LED
【i.MX6ULL】Driver Development 7——Key Input Capture
【i.MX6ULL】Driver Development 8——Interrupt Method to Detect Buttons
【i.MX6ULL】Driver Development 9——Linux IO Model Analysis
【i.MX6ULL】Driver Development 10——Blocking & Non-blocking Key Detection
【i.MX6ULL】Driver Development 11——LCD Driver Practice
【i.MX6ULL】Driver Development 12——Capacitive Touch Driver Practice (Part 1)
【i.MX6ULL】Driver Development 13——Capacitive Touch Driver Practice (Part 2)
Details
Published on 2022-3-21 07:41
The author is very serious and attentive, and has a great spirit! If this program is written by the author himself, the technical level is still very high!