linux子系统之drm dsi

本文将从以下几个方面来学习研究mipi_dsi总线

  • mipi-dsi总线的注册
    • 总线的匹配规则
  • dsi控制器的注册
    • mipi_dsi总线设备的解析与生成
    • dsi控制器驱动示例
  • mipi-dsi总线驱动的注册

mipi-dsi总线的注册

源文件:kernel/driver/gpu/drm/drm_mipi_dsi.c

c 复制代码
static int __init mipi_dsi_bus_init(void)
{
	return bus_register(&mipi_dsi_bus_type);
}
postcore_initcall(mipi_dsi_bus_init);
c 复制代码
static struct bus_type mipi_dsi_bus_type = {
	.name = "mipi-dsi",
	.match = mipi_dsi_device_match,
	.uevent = mipi_dsi_uevent,
	.pm = &mipi_dsi_device_pm_ops,
};

总线的匹配规则

这里的匹配规则比较简单与platform设备匹配规则 比较相似。

dsi控制器的注册

dis控制器注册使用函数module_mipi_dsi_driver来实现

mipi_dsi_host_register

复制代码
int mipi_dsi_host_register(struct mipi_dsi_host *host)
{
	struct device_node *node;

	for_each_available_child_of_node(host->dev->of_node, node) {
		/* skip nodes without reg property */
		if (!of_find_property(node, "reg", NULL))
			continue;
		of_mipi_dsi_device_add(host, node);
	}

	mutex_lock(&host_lock);
	list_add_tail(&host->list, &host_list);
	mutex_unlock(&host_lock);
	return 0;
}

这个函数主要有两点:

  • 解析控制器配置的总线设备,每个设备节点必须包含reg属性,不然不会生成相应的总线设备。
  • 将控制器添加到host_list链表上

总线设备的解析与生成

of_mipi_dsi_device_add

mipi_dsi_device_register_full

dsi控制器驱动示例

控制器源码:linux-6.4\drivers\gpu\drm\sprd\sprd_dsi.c

c 复制代码
static int sprd_dsi_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct sprd_dsi *dsi;

	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
	if (!dsi)
		return -ENOMEM;

	dev_set_drvdata(dev, dsi);

	dsi->host.ops = &sprd_dsi_host_ops;
	dsi->host.dev = dev;

	return mipi_dsi_host_register(&dsi->host);
}

此控制器代码简单明了,思路一目了然。

核心的回调函数如下:

复制代码
static const struct mipi_dsi_host_ops sprd_dsi_host_ops = {
	.attach = sprd_dsi_host_attach,
	.detach = sprd_dsi_host_detach,
	.transfer = sprd_dsi_host_transfer,
};

mipi-dsi总线驱动的注册

此总线的驱动注册一般使用宏module_mipi_dsi_driver进行驱动模块的加载,其定义如下:

c 复制代码
int mipi_dsi_driver_register_full(struct mipi_dsi_driver *driver,
				  struct module *owner);
void mipi_dsi_driver_unregister(struct mipi_dsi_driver *driver);

#define mipi_dsi_driver_register(driver) \
	mipi_dsi_driver_register_full(driver, THIS_MODULE)

#define module_mipi_dsi_driver(__mipi_dsi_driver) \
	module_driver(__mipi_dsi_driver, mipi_dsi_driver_register, \
			mipi_dsi_driver_unregister)

mipi_dsi_driver_register_full

复制代码
int mipi_dsi_driver_register_full(struct mipi_dsi_driver *drv,
				  struct module *owner)
{
	drv->driver.bus = &mipi_dsi_bus_type;
	drv->driver.owner = owner;

	if (drv->probe)
		drv->driver.probe = mipi_dsi_drv_probe;
	if (drv->remove)
		drv->driver.remove = mipi_dsi_drv_remove;
	if (drv->shutdown)
		drv->driver.shutdown = mipi_dsi_drv_shutdown;

	return driver_register(&drv->driver);
}

mipi-dsi总线驱动示例分析

源文件:linux-6.4\drivers\gpu\drm\panel\panel-asus-z00t-tm5p5-n35596.c

复制代码
static struct mipi_dsi_driver tm5p5_nt35596_driver = {
	.probe = tm5p5_nt35596_probe,
	.remove = tm5p5_nt35596_remove,
	.driver = {
		.name = "panel-tm5p5-nt35596",
		.of_match_table = tm5p5_nt35596_of_match,
	},
};

tm5p5_nt35596_probe

下面一一对上述关键的函数进行解析:

  • dsi->lanes = 4; 一般情况下dphy用的4lan
  • dsi->format = MIPI_DSI_FMT_RGB888;格式设置,支持的格式如下
    • enum mipi_dsi_pixel_format {
      MIPI_DSI_FMT_RGB888,
      MIPI_DSI_FMT_RGB666,
      MIPI_DSI_FMT_RGB666_PACKED,
      MIPI_DSI_FMT_RGB565,
      };
drm_panel_init
复制代码
void drm_panel_init(struct drm_panel *panel, struct device *dev,
		    const struct drm_panel_funcs *funcs, int connector_type)
{
	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
		DRM_WARN("%s: %s: a valid connector type is required!\n", __func__, dev_name(dev));

	INIT_LIST_HEAD(&panel->list);
	panel->dev = dev;
	panel->funcs = funcs;
	panel->connector_type = connector_type;
}

static const struct drm_panel_funcs tm5p5_nt35596_panel_funcs = {
	.prepare = tm5p5_nt35596_prepare,
	.unprepare = tm5p5_nt35596_unprepare,
	.get_modes = tm5p5_nt35596_get_modes,
};
struct drm_panel_funcs {
	int (*prepare)(struct drm_panel *panel);
	int (*enable)(struct drm_panel *panel);
	int (*disable)(struct drm_panel *panel);
	int (*unprepare)(struct drm_panel *panel);
	int (*get_modes)(struct drm_panel *panel,
			 struct drm_connector *connector);
	enum drm_panel_orientation (*get_orientation)(struct drm_panel *panel);
	int (*get_timings)(struct drm_panel *panel, unsigned int num_timings,
			   struct display_timing *timings);
	void (*debugfs_init)(struct drm_panel *panel, struct dentry *root);
};
  • prepare 一般用于上电时序控制,以及dsi-cmd亮屏命令初始化
  • enable 一般用于控制使用上电亮屏,此屏不涉及使用的ldo供电
  • unprepare 一般用于下电时序控制,以及dsi-cmd灭屏命令的写入
  • disable 一般用于控制使用下电灭屏,此屏不涉及使用的ldo供电
tm5p5_nt35596_create_backlight
复制代码
static struct backlight_device *
tm5p5_nt35596_create_backlight(struct mipi_dsi_device *dsi)
{
	struct device *dev = &dsi->dev;
	const struct backlight_properties props = {
		.type = BACKLIGHT_RAW,
		.brightness = 255,
		.max_brightness = 255,
	};

	return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
					      &tm5p5_nt35596_bl_ops, &props);
}

会调用linux提供的背光注册函数,不过高通和MTK都有自己的解决方案不般不会用这一块。这里只做参数,代码比较简单。将回调注册到背光链表上,后面有使用再进行操作。

源码位置:/kernel/driver/video/backlight/backlight.c

drm_panel_add
复制代码
void drm_panel_add(struct drm_panel *panel)
{
	mutex_lock(&panel_lock);
	list_add_tail(&panel->list, &panel_list);
	mutex_unlock(&panel_lock);
}
mipi_dsi_attach
复制代码
int mipi_dsi_attach(struct mipi_dsi_device *dsi)
{
	const struct mipi_dsi_host_ops *ops = dsi->host->ops;
	int ret;
	if (!ops || !ops->attach)
		return -ENOSYS;
	ret = ops->attach(dsi->host, dsi);
	if (ret)
		return ret;
	dsi->attached = true;
	return 0;
}

调用控制器的回调函数进行绑定,这里回过头来看上面注册的控制器的attach回调函数。

sprd_dsi_host_attach
复制代码
int component_add(struct device *dev, const struct component_ops *ops)
{
	return __component_add(dev, ops, 0);
}





本篇到这里就结束了,后面针对master再进行对应的学习和研究

相关推荐
码银2 小时前
使用VMware安装CentOS7(Linux)操作系统(图文步骤)附vmware安装包/centos.iso镜像文件
linux·运维·centos
似水এ᭄往昔2 小时前
【Linux】--磁盘和文件系统
linux·运维·数据库
hhl_483841042 小时前
上海域格4G模块信号说明
linux·功能测试·物联网·信号处理·tcp
IMPYLH2 小时前
Linux 的 sum 命令
linux·运维·服务器·chrome·python·bash
kaico20182 小时前
Ubuntu系统运维
linux·运维·ubuntu
枳实-叶2 小时前
【Linux驱动开发】第一天:用户态与内核态通俗讲解+最简字符设备驱动实战
linux·驱动开发·学习
计算机安禾3 小时前
【Linux从入门到精通】第23篇:条件判断——让脚本拥有“大脑”
linux·运维·服务器
feng_you_ying_li3 小时前
linu之进程的程序替换与shell基本实现的基本版本
linux
念恒123063 小时前
进程控制---进程程序替换
linux·c语言