L'écran LCD est un périphérique couramment utilisé, et les fabricants de semi-conducteurs fournissent généralement des programmes pilotes d'interface LCD pré-écrits pour leurs puces. Les développeurs n'ont pas besoin de modifier la section du pilote LCD ; ils doivent uniquement ajuster l'arborescence des périphériques en fonction du dispositif LCD spécifique qu'ils utilisent. Bien qu'aucune modification ne soit nécessaire dans le pilote, il est toujours essentiel de comprendre le processus du pilote LCD.

1. Périphérique Framebuffer
Dans le système d'exploitation Linux, les applications interagissent finalement avec la mémoire vidéo de l'écran LCD RGB pour afficher des caractères, des images et d'autres informations sur l'écran LCD. La gestion de la mémoire sous Linux est rigoureuse, et la mémoire vidéo doit être allouée. De plus, en raison de la présence de mémoire virtuelle, la mémoire vidéo définie par le pilote et la mémoire vidéo accessible par l'application doivent correspondre à la même mémoire physique. Pour résoudre ce problème, le Framebuffer (appelé “fb”) a été introduit. Le Framebuffer représente une zone de mémoire qui stocke une image complète. Écrire des données dans cette mémoire équivaut à écrire des données sur l'écran. En substance, le Framebuffer mappe chaque point de l'écran à un espace mémoire linéaire, permettant aux programmes de modifier la valeur de ce segment de mémoire pour changer la couleur d'un point spécifique sur l'écran.
.owner = THIS_MODULE,
.read = fb_read,
.write = fb_write,
.unlocked_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
.llseek = default_llseek,
};
Le mécanisme Framebuffer fournit une interface unifiée pour les opérations en espace utilisateur sur les dispositifs d'affichage, en masquant les différences entre les composants matériels sous-jacents. Lorsque le pilote LCD est chargé avec succès, il génère un fichier de périphérique nommé /dev/fbX. Les applications peuvent accéder à l'écran LCD via ce fichier de périphérique. /dev/fbX est un périphérique caractère, et il possède son propre ensemble d'opérations file_operations , qui est défini dans le fichier drivers/video/fbdev/core/fbmem.c .
struct fb_info {
atomic_t count;
int node;
int flags;
struct mutex lock;
struct mutex mm_lock;
struct fb_var_screeninfo var;
struct fb_fix_screeninfo fix;
struct fb_monspecs monspecs;
struct work_struct queue;
struct fb_pixmap pixmap;
struct fb_pixmap sprite;
struct fb_cmap cmap;
struct list_head modelist;
struct fb_videomode *mode;
#ifdef CONFIG_FB_BACKLIGHT
struct backlight_device *bl_dev;
struct mutex bl_curve_mutex;
u8 bl_curve[FB_BACKLIGHT_LEVELS];
#endif
struct fb_ops *fbops;
struct device *device;
struct device *dev;
int class_flag;
char __iomem *screen_base;
unsigned long screen_size;
void *pseudo_palette;
};
Le noyau Linux abstrait tous les Framebuffers sous la forme de structures fb_info . La structure fb_info contient les attributs complets et les ensembles d'opérations du périphérique Framebuffer. Par conséquent, chaque périphérique Framebuffer est associé à une fb_info. La structure est définie dans le fichier include/linux/fb.h .
2. Analyse du Pilote LCD
Pour une puce donnée, le code du pilote pour le contrôleur eLCDIF des écrans LCD avec différentes résolutions reste le même. À titre d'exemple, considérons le pilote LCD pour la puce NXP IMX6ULL sous Linux et décrivons brièvement le processus du pilote LCD.
- Ouverture de l'Arborescence des Périphériques : Ouvrez le fichier
imx6ull.dtsiet localisez le contenu dulcdifnœud, qui contient les détails de configuration pour le contrôleur d'interface LCD.
lcdif: lcdif@021c8000 {
compatible = “fsl,imx6ul-lcdif”, “fsl,imx28-lcdif”;
reg = ;
interrupts = ;
clocks = ,
,
;
clock-names = “pix”, “axi”, “disp_axi”;
status = “disabled”;
};
- Correspondance du pilote de périphérique : La
compatiblevaleur de propriété est utilisée pour faire correspondre le pilote de périphérique dans le code source Linux. Lefichier mxsfb.ccontient le pilote de plateforme pour le Framebuffer MXS.
static const struct of_device_id mxsfb_dt_ids[] = {
{ .compatible = “fsl,imx23-lcdif”, .data = &mxsfb_devtype[0], },
{ .compatible = “fsl,imx28-lcdif”, .data = &mxsfb_devtype[1], },
{ /* sentinelle */ }
};
……
……
static struct platform_driver mxsfb_driver = {
.probe = mxsfb_probe,
.remove = mxsfb_remove,
.shutdown = mxsfb_shutdown,
.id_table = mxsfb_devtype,
.driver = {
.name = DRIVER_NAME,
.of_match_table = mxsfb_dt_ids,
.pm = &mxsfb_pm_ops,
},
};
module_platform_driver(mxsfb_driver);
- Fonction Probe : Lorsque le pilote correspond au périphérique, la
fonction mxsfb_probeest exécutée. Cette fonction initialise le périphérique Framebuffer, alloue les ressources, mappe la mémoire et configure le gestionnaire d'interruption.
static int mxsfb_probe(struct platform_device *pdev) {
const struct of_device_id *of_id = of_match_device(mxsfb_dt_ids, &pdev->dev);
struct resource *res;
struct mxsfb_info *host;
struct fb_info *fb_info;
struct pinctrl *pinctrl;
int irq = platform_get_irq(pdev, 0);
int gpio, ret;
……
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, “Impossible d'obtenir la ressource mémoire IO\n”);
return -ENODEV;
}
host = devm_kzalloc(&pdev->dev, sizeof(struct mxsfb_info), GFP_KERNEL);
if (!host) {
dev_err(&pdev->dev, “Échec de l'allocation de la ressource IO\n”);
return -ENOMEM;
}
fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
if (!fb_info) {
dev_err(&pdev->dev, “Échec de l'allocation de fbdev\n”);
devm_kfree(&pdev->dev, host);
return -ENOMEM;
}
host->fb_info = fb_info;
fb_info->par = host;
ret = devm_request_irq(&pdev->dev, irq, mxsfb_irq_handler, 0, dev_name(&pdev->dev), host);
if (ret) {
dev_err(&pdev->dev, “request_irq (%d) a échoué avec l'erreur %d\n”, irq, ret);
ret = -ENODEV;
goto fb_release;
}
host->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(host->base)) {
dev_err(&pdev->dev, “Échec de ioremap\n”);
ret = PTR_ERR(host->base);
goto fb_release;
}
……
fb_info->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16, GFP_KERNEL);
if (!fb_info->pseudo_palette) {
ret = -ENOMEM;
goto fb_release;
}
INIT_LIST_HEAD(&fb_info->modelist);
pm_runtime_enable(&host->pdev->dev);
ret = mxsfb_init_fbinfo(host);
if (ret != 0)
goto fb_pm_runtime_disable;
mxsfb_dispdrv_init(pdev, fb_info);
if (!host->dispdrv) {
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(pinctrl)) {
ret = PTR_ERR(pinctrl);
goto fb_pm_runtime_disable;
}
}
if (!host->enabled) {
writel(0, host->base + LCDC_CTRL);
mxsfb_set_par(fb_info);
mxsfb_enable_controller(fb_info);
pm_runtime_get_sync(&host->pdev->dev);
}
ret = register_framebuffer(fb_info);
if (ret != 0) {
dev_err(&pdev->dev, “Échec de l'enregistrement du framebuffer\n”);
goto fb_destroy;
}
……
return ret;
}
- Initialisation du Framebuffer : Le périphérique Framebuffer est initialisé et le pilote l'enregistre auprès du noyau Linux.
Les principales tâches de la fonction mxsfb_probe fonction incluent l'allocation de mémoire pour fb_info, l'allocation de mémoire pour la pseudo_palette, l'initialisation du contrôleur eLCDIF, et l'enregistrement du fb_info auprès du noyau Linux.
En effet, l'utilisation du système Linux a toujours été un aspect technique difficile pour de nombreux fournisseurs de modules LCD. Choisir le bon fournisseur de modules LCD n'est pas facile pour ceux qui développent des produits avec le système Linux. RJOYTEK est une entreprise technologique spécialisée dans les modules LCD et le développement de cartes. Si vous avez besoin d'une assistance technique supplémentaire, n'hésitez pas à nous contacter!
- Pour la liste des produits, veuillez consulter Module d'affichage TFT LCD
- Pour voir une vidéo du panneau LCD, visitez SOLUTION LCD RJY
- Si vous avez besoin d'une assistance technique, veuillez nous contacter