显示屏驱动

Posted 四季帆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了显示屏驱动相关的知识,希望对你有一定的参考价值。

1. frambuffer简介

        Linux kernel为显示屏设备提供了一个驱动框架叫FrameBuffer(中文也称“帧缓冲区”),所以编写显示屏驱动的任务也就变成了调用FrameBuffer框架提供的接口,注册包含具体显示屏控制器信息的结构体到FrameBuffer框架。

        所以正常情况下,显示屏驱动应该就两层,第一层是FrameBuffer 驱动框架层,第二层就是具体的显示屏控制器对应的驱动代码。

        通过阅读Imx6dl SOC数据手册可知

显示接口桥接:提供从IPU支持的数字显示接口到其他接口的可选转换:
	LVDS bridge (LDB): providing up to one LVDS interface
	HDMI transmitter
	MIPI/DSI transmitter

        Imx6dl 这款SOC 集成了三种显示屏接口的控制器,所以Imx6dl 的显示屏驱动在第二层的基础上,将各种接口不同的部分分离出去形成第三层,三种接口的共性部分留在第二层。

2. 驱动分析

        以hdmi接口的显示屏为例,驱动第三层:mxc_hdmi.c文件

//hdmi_i2c和hdmi_video驱动都在mxc_hdmi.c文件中
module_init(mxc_hdmi_i2c_init);

static int __init mxc_hdmi_i2c_init(void)
{
	return i2c_add_driver(&mxc_hdmi_i2c_driver);
}

static struct i2c_driver mxc_hdmi_i2c_driver = {
	.driver = {
		   .name = "mxc_hdmi_i2c",
			.of_match_table	= imx_hdmi_i2c_match,
		   },
	.probe = mxc_hdmi_i2c_probe,
	.remove = mxc_hdmi_i2c_remove,
	.id_table = mxc_hdmi_i2c_id,
};

static int mxc_hdmi_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	if (!i2c_check_functionality(client->adapter,
				I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))	//检查i2c_adapter的特性
		return -ENODEV;

	hdmi_i2c = client;		//将该设备赋值到全局变量中hdmi_i2c

	return 0;
}
----------------------------------------------------------------------------------------
static int __init mxc_hdmi_init(void)
{
	return platform_driver_register(&mxc_hdmi_driver);
}
module_init(mxc_hdmi_init);

static struct platform_driver mxc_hdmi_driver = {
	.probe = mxc_hdmi_probe,
	.remove = mxc_hdmi_remove,
	.driver = {
		.name = "mxc_hdmi",
		.of_match_table	= imx_hdmi_dt_ids,
		.owner = THIS_MODULE,
	},
};

static int mxc_hdmi_probe(struct platform_device *pdev)
{
	struct mxc_hdmi *hdmi;
	struct device *temp_class;
	struct resource *res;
	int ret = 0;

	/* Check I2C driver is loaded and available check hdcp function is enable by dts */
	hdmi_hdcp_get_property(pdev);
	if (!hdmi_i2c && !hdcp_init)
		return -ENODEV;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);	//获取platform资源res

	hdmi = devm_kzalloc(&pdev->dev, sizeof(struct mxc_hdmi), GFP_KERNEL);
	g_hdmi = hdmi;		//将申请到的mxc_hdmi结构体类型的内存赋值给全局指针g_hdmi

	hdmi_major = register_chrdev(hdmi_major, "mxc_hdmi", &mxc_hdmi_fops);	//注册字符设备mxc_hdmi
	hdmi_class = class_create(THIS_MODULE, "mxc_hdmi");	//在sys/class/路径下创建mxc_hdmi/目录

    //在sys/class/mxc_hdmi/路径下创建设备节点mxc_hdmi
	temp_class = device_create(hdmi_class, NULL, MKDEV(hdmi_major, 0), NULL, "mxc_hdmi");

	hdmi->pdev = pdev;
	hdmi->core_pdev = platform_device_alloc("mxc_hdmi_core", -1);
	hdmi->gpr_base = ioremap(res->start, resource_size(res));	//通过ioremap将hdmi_video的物理地址映射为虚拟地址
	hdmi->gpr_hdmi_base = hdmi->gpr_base + 3;
	hdmi->gpr_sdma_base = hdmi->gpr_base;

	hdmi->disp_mxc_hdmi = mxc_dispdrv_register(&mxc_hdmi_drv);	//注册mxc_hdmi_drv
    ······
	return 0;
}

static struct mxc_dispdrv_driver mxc_hdmi_drv = {
	.name	= DISPDRV_HDMI,
	.init	= mxc_hdmi_disp_init,
	.deinit	= mxc_hdmi_disp_deinit,
	.enable = mxc_hdmi_power_on,
	.disable = mxc_hdmi_power_off,
};

struct mxc_dispdrv_handle *mxc_dispdrv_register(struct mxc_dispdrv_driver *drv)
{
	struct mxc_dispdrv_entry *new;
	new = kzalloc(sizeof(struct mxc_dispdrv_entry), GFP_KERNEL);
	new->drv = drv;
	list_add_tail(&new->list, &dispdrv_list);	//添加到dispdrv_list 链表
	return (struct mxc_dispdrv_handle *)new;
}

以上是关于显示屏驱动的主要内容,如果未能解决你的问题,请参考以下文章

片段着色器中设置的颜色未显示 GLSL 1.30

Sphinx、reStructuredText 显示/隐藏代码片段

执行代码时有时不显示对话框片段

如何运用领域驱动设计 - 值对象

python selenium片段+网络驱动程序

如何在 Resharper IntelliSense 中显示所有 Visual Studio 代码片段?