LCD는 일반적으로 사용되는 주변 장치이며, 반도체 제조사는 일반적으로 자사 칩에 대해 사전에 작성된 LCD 인터페이스 드라이버 프로그램을 제공합니다. 개발자는 LCD 드라이버 부분을 수정할 필요가 없으며, 사용 중인 특정 LCD 장치에 따라 장치 트리만 조정하면 됩니다. 드라이버에서 수정이 필요하지는 않지만, LCD 드라이버 프로세스를 이해하는 것은 여전히 필수적입니다.

1. 프레임버퍼 장치
Linux 운영 체제에서 애플리케이션은 궁극적으로 RGB LCD의 비디오 메모리와 상호 작용하여 LCD 화면에 문자, 이미지 및 기타 정보를 표시합니다. Linux의 메모리 관리는 엄격하며, 비디오 메모리를 할당해야 합니다. 또한 가상 메모리가 존재하기 때문에 드라이버가 설정한 비디오 메모리와 애플리케이션이 액세스하는 비디오 메모리는 동일한 물리적 메모리에 대응해야 합니다. 이 문제를 해결하기 위해 프레임버퍼(“fb”라고 함)가 도입되었습니다. 프레임버퍼는 한 프레임의 이미지를 저장하는 메모리 영역을 나타냅니다. 이 메모리에 데이터를 쓰는 것은 화면에 데이터를 쓰는 것과 동일합니다. 본질적으로 프레임버퍼는 화면의 각 지점을 선형 메모리 공간에 매핑하여 프로그램이 이 메모리 세그먼트의 값을 변경하여 화면의 특정 지점 색상을 변경할 수 있도록 합니다.
.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,
};
프레임버퍼 메커니즘은 사용자 공간에서 디스플레이 장치를 조작하기 위한 통합 인터페이스를 제공하여 기본 하드웨어 구성 요소 간의 차이를 추상화합니다. LCD 드라이버가 성공적으로 로드되면 /dev/fbX. 라는 이름의 장치 파일이 생성됩니다. 애플리케이션은 이 장치 파일을 통해 LCD에 액세스할 수 있습니다. /dev/fbX 는 문자 장치이며, 이에 해당하는 file_operations 연산 집합이 있으며, 이는 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;
};
Linux 커널은 모든 프레임버퍼를 fb_info 구조체로 추상화합니다. fb_info 구조체는 프레임버퍼 장치의 완전한 속성과 연산 집합을 포함합니다. 결과적으로 각 프레임버퍼 장치는 하나의 fb_info. 와 연결됩니다. 구조체는 include/linux/fb.h 파일에 정의되어 있습니다.
2. LCD 드라이버 분석
특정 칩의 경우, 해상도가 다른 LCD 화면을 위한 eLCDIF 컨트롤러의 드라이버 코드는 동일하게 유지됩니다. 예를 들어, Linux에서 NXP IMX6ULL 칩용 LCD 드라이버를 고려하여 LCD 드라이버 프로세스를 간략히 설명하겠습니다.
- 장치 트리 열기:
imx6ull.dtsi파일을 열고 다음 내용을 찾습니다.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, “Cannot get memory IO resource\n”);
return -ENODEV;
}
host = devm_kzalloc(&pdev->dev, sizeof(struct mxsfb_info), GFP_KERNEL);
if (!host) {
dev_err(&pdev->dev, “Failed to allocate IO resource\n”);
return -ENOMEM;
}
fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
if (!fb_info) {
dev_err(&pdev->dev, “Failed to allocate 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) failed with error %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 failed\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, “Failed to register framebuffer\n”);
goto fb_destroy;
}
……
return ret;
}
- 프레임버퍼 초기화: 프레임버퍼 장치가 초기화되며, 드라이버가 이를 리눅스 커널에 등록합니다.
해당 함수의 주요 작업은 mxsfb_probe 메모리 할당, fb_info, 메모리 할당, pseudo_palette, eLCDIF 컨트롤러 초기화 및 fb_info 리눅스 커널에 등록을 포함합니다.
실제로 리눅스 시스템의 사용은 많은 LCD 모듈 공급업체에게 항상 기술적으로 어려운 측면이었습니다. 리눅스 시스템을 사용하여 제품을 개발하는 사람들에게 적합한 LCD 모듈 공급업체를 선택하는 것은 쉽지 않습니다. RJOYTEK은 LCD 모듈 및 보드 개발을 전문으로 하는 기술 회사입니다. 추가 기술 지원이 필요하시면 언제든지 문의해 주십시오. 문의해 주십시오!
- 제품 목록은 다음에서 확인하실 수 있습니다: TFT LCD 디스플레이 모듈
- LCD 패널 동영상 확인 방문 LCD 솔루션 RJY
- 엔지니어링 지원이 필요하신 경우 문의해 주십시오