初心者向けLinuxにおけるLCDスクリーンドライバーの基礎

目次

LCD is a commonly used peripheral, and semiconductor manufacturers typically provide pre-written LCD interface driver programs for their chips. Developers don’t need to modify the LCD driver section; they only need to adjust the device tree according to the specific LCD device they are using. While no modifications are necessary in the driver, it’s still essential to comprehend the LCD driver process.

 

 

 

 

 

 

 

 

 

1. Framebuffer Device

In the Linux operating system, applications ultimately interact with the video memory of RGB LCD to display characters, images, and other information on the LCD screen. Memory management in Linux is rigorous, and video memory needs to be allocated. Moreover, because of the presence of virtual memory, the video memory set by the driver and the video memory accessed by the application must correspond to the same physical memory. To address this issue, the Framebuffer (referred to as “fb”) was introduced. The Framebuffer represents a memory area that stores a frame of an image. Writing data to this memory is equivalent to writing data to the screen. In essence, the Framebuffer maps each point on the screen to a linear memory space, enabling programs to change the value of this memory segment to alter the color of a specific point on the screen.

static const struct file_operations fb_fops = {
.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,
};

The Framebuffer mechanism provides a unified interface for user space operations on display devices, abstracting away the differences between underlying hardware components. When the LCD driver is successfully loaded, it generates a device file named /dev/fbX. Applications can access the LCD through this device file. /dev/fbX is a character device, and it has its corresponding file_operations operation set, which is defined in the drivers/video/fbdev/core/fbmem.c file.

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;
};

The Linux kernel abstracts all Framebuffers as fb_info structures. The fb_info structure contains the complete attributes and operation sets of the Framebuffer device. As a result, each Framebuffer device is associated with an fb_info. The structure is defined in the include/linux/fb.h file.

2. Analysis of the LCD Driver

For a given chip, the driver code for the eLCDIF controller for LCD screens with different resolutions remains the same. As an example, let’s consider the LCD driver for the NXP IMX6ULL chip in Linux and briefly outline the LCD driver’s process.

  • Opening the Device Tree: Open the imx6ull.dtsi file and locate the content of the lcdif LCDインターフェースコントローラの設定詳細を含むノード。

lcdif: lcdif@021c8000 {
compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";
reg = ;
interrupts = ;
clocks = ,
,
;
clock-names = "pix", "axi", "disp_axi";
status = "disabled";
};

  • デバイスドライバのマッチング: compatible プロパティの値は、Linuxソースコード内のデバイスドライバと対応付けるために使用されます。 mxsfb.c ファイルには、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], },
{ /* sentinel */ }
};
……
……
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);

  • プローブ関数: ドライバがデバイスと一致すると、 mxsfb_probe 関数が実行されます。この関数は、フレームバッファデバイスの初期化、リソースの割り当て、メモリのマッピング、および割り込みハンドラの設定を行います。

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, "メモリIOリソースを取得できません\n");
return -ENODEV;
}

host = devm_kzalloc(&pdev->dev, sizeof(struct mxsfb_info), GFP_KERNEL);
if (!host) {
dev_err(&pdev->dev, "IOリソースの割り当てに失敗しました\n");
return -ENOMEM;
}

fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
if (!fb_info) {
dev_err(&pdev->dev, "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) がエラー %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, "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, "フレームバッファの登録に失敗しました\n");
goto fb_destroy;
}
……
return ret;
}

  • フレームバッファ初期化: フレームバッファデバイスを初期化し、ドライバはLinuxカーネルに登録します。

主なタスクは、 mxsfb_probe メモリの割り当て、 fb_info疑似パレット用のメモリ割り当て、 pseudo_palette、eLCDIFコントローラの初期化、および fb_info をLinuxカーネルに登録することです。

実際、Linuxシステムの使用は、多くのLCDモジュールサプライヤーにとって常に挑戦的な技術的側面です。Linuxシステムを使用して製品を開発する場合、適切なLCDモジュールサプライヤーを選択することは容易ではありません。RJOYTEKは、LCDモジュールおよびボード開発に特化したテクノロジー企業です。さらに技術サポートが必要な場合は、お気軽にご連絡ください。 お問い合わせください!

RJY Displayについて

当社は中国に拠点を置く主要なLCDパネルメーカーおよびディスプレイソリューションプロバイダーであり、高性能、コスト効率に優れ、信頼性の高いLCDパネルの開発と生産に専念しています。さらに、多様なHMI(ヒューマンマシンインターフェース)アプリケーションのニーズを満たすために設計されたカスタマイズされたディスプレイソリューションを提供します。私たちの使命は、お客様が市場競争力を高めながら、設備のメンテナンスリスクを軽減できるよう支援することです。新しいディスプレイソリューションを模索中であるか、長期的な供給パートナーを探している場合、当社チームは以下の提供を準備しています 無料の専門相談、最新の製品カタログ、競争力のある見積もり.

RJY Displayを選ぶ理由

  • ワンストップソリューション: 完全にカスタマイズされたLCDモジュールに加えて、シームレスな統合のために一緒に購入できる matching 制御ボード、デジタルケーブル、およびタッチソリューションも供給します。

  • カスタマイズの柔軟性: 製品サイズ、タッチスクリーンタイプ、デジタルインターフェース、および制御ボードのオプションは、すべて特定のプロジェクトのニーズに合わせて調整できます。

  • 認証された品質: 当社の製品と工場は、以下の認証を保持しています ISO9001、ISO45001、REACH、CE、コンプライアンスと信頼性を保証します。

  • 強力な生産能力: 当社は 2つの先進的な工場を有しており、あらゆる規模のプロジェクトを支援するために、短いリードタイムと効率的な大量生産を保証します。

RJY Displayと提携する利点 信頼できるディスプレイソリューション、より速いプロジェクトの納品、長期的なビジネス価値.

この投稿をシェア
Facebook
Twitter
LinkedIn
WhatsApp

メッセージを送信

このフォームに入力するには、ブラウザーで JavaScript を有効にしてください。
トップへスクロール