Linux内核4.14版本——drm框架分析(12)——DRM_IOCTL_MODE_SETCRTC(drm_mode_setcrtc)

news2025/1/17 22:03:43

目录

1. drm_mode_setcrtc

1.1 根据应用传入的crtc_id找到crtc

1.2 根据应用传入的fb_id,找到对应的drm_framebuffer

1.3  根据应用传入的mode,创建一个drm_display_mode

1.4 根据传入的set_connectors_ptr,找到驱动对应的connector

1.5 将以上信息转为struct drm_mode_set并调用__drm_mode_set_config_internal

1.6 __drm_mode_set_config_internal

2. drm_atomic_helper_set_config

3. 流程图


        本文分析一下drm_mode_setcrtc。

1. drm_mode_setcrtc

1.1 根据应用传入的crtc_id找到crtc

int drm_mode_setcrtc(struct drm_device *dev, void *data,
		     struct drm_file *file_priv)
{
    ......

	crtc = drm_crtc_find(dev, crtc_req->crtc_id);
	if (!crtc) {
		DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
		return -ENOENT;
	}
	DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);

1.2 根据应用传入的fb_id,找到对应的drm_framebuffer

	if (crtc_req->mode_valid) {
		/* If we have a mode we need a framebuffer. */
		/* If we pass -1, set the mode with the currently bound fb */
		if (crtc_req->fb_id == -1) {
			if (!crtc->primary->fb) {
				DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
				ret = -EINVAL;
				goto out;
			}
			fb = crtc->primary->fb;
			/* Make refcounting symmetric with the lookup path. */
			drm_framebuffer_get(fb);
		} else {
			fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
			if (!fb) {
				DRM_DEBUG_KMS("Unknown FB ID%d\n",
						crtc_req->fb_id);
				ret = -ENOENT;
				goto out;
			}

1.3  根据应用传入的mode,创建一个drm_display_mode

		mode = drm_mode_create(dev);
		if (!mode) {
			ret = -ENOMEM;
			goto out;
		}

		ret = drm_mode_convert_umode(mode, &crtc_req->mode);
		if (ret) {
			DRM_DEBUG_KMS("Invalid mode\n");
			goto out;
		}

		/*
		 * Check whether the primary plane supports the fb pixel format.
		 * Drivers not implementing the universal planes API use a
		 * default formats list provided by the DRM core which doesn't
		 * match real hardware capabilities. Skip the check in that
		 * case.
		 */
		if (!crtc->primary->format_default) {
			ret = drm_plane_check_pixel_format(crtc->primary,
							   fb->format->format);
			if (ret) {
				struct drm_format_name_buf format_name;
				DRM_DEBUG_KMS("Invalid pixel format %s\n",
				              drm_get_format_name(fb->format->format,
				                                  &format_name));
				goto out;
			}
		}

		ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
					      mode, fb);
		if (ret)
			goto out;

1.4 根据传入的set_connectors_ptr,找到驱动对应的connector

		for (i = 0; i < crtc_req->count_connectors; i++) {
			connector_set[i] = NULL;
			set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
			if (get_user(out_id, &set_connectors_ptr[i])) {
				ret = -EFAULT;
				goto out;
			}

			connector = drm_connector_lookup(dev, out_id);
			if (!connector) {
				DRM_DEBUG_KMS("Connector id %d unknown\n",
						out_id);
				ret = -ENOENT;
				goto out;
			}
			DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
					connector->base.id,
					connector->name);

			connector_set[i] = connector;
		}

1.5 将以上信息转为struct drm_mode_set并调用__drm_mode_set_config_internal

	set.crtc = crtc;
	set.x = crtc_req->x;
	set.y = crtc_req->y;
	set.mode = mode;
	set.connectors = connector_set;
	set.num_connectors = crtc_req->count_connectors;
	set.fb = fb;
	ret = __drm_mode_set_config_internal(&set, &ctx);

1.6 __drm_mode_set_config_internal


static int __drm_mode_set_config_internal(struct drm_mode_set *set,
					  struct drm_modeset_acquire_ctx *ctx)
{
	struct drm_crtc *crtc = set->crtc;
	struct drm_framebuffer *fb;
	struct drm_crtc *tmp;
	int ret;

	/*
	 * NOTE: ->set_config can also disable other crtcs (if we steal all
	 * connectors from it), hence we need to refcount the fbs across all
	 * crtcs. Atomic modeset will have saner semantics ...
	 */
	drm_for_each_crtc(tmp, crtc->dev)
		tmp->primary->old_fb = tmp->primary->fb;

	fb = set->fb;

	ret = crtc->funcs->set_config(set, ctx);
	if (ret == 0) {
		crtc->primary->crtc = crtc;
		crtc->primary->fb = fb;
	}

	drm_for_each_crtc(tmp, crtc->dev) {
		if (tmp->primary->fb)
			drm_framebuffer_get(tmp->primary->fb);
		if (tmp->primary->old_fb)
			drm_framebuffer_put(tmp->primary->old_fb);
		tmp->primary->old_fb = NULL;
	}

	return ret;
}

        只要是调用ret = crtc->funcs->set_config(set, ctx),即drm_atomic_helper_set_config,

static const struct drm_crtc_funcs malidp_crtc_funcs = {
	.gamma_set = drm_atomic_helper_legacy_gamma_set,
	.destroy = drm_crtc_cleanup,
	.set_config = drm_atomic_helper_set_config,
	.page_flip = drm_atomic_helper_page_flip,
	.reset = malidp_crtc_reset,
	.atomic_duplicate_state = malidp_crtc_duplicate_state,
	.atomic_destroy_state = malidp_crtc_destroy_state,
	.enable_vblank = malidp_crtc_enable_vblank,
	.disable_vblank = malidp_crtc_disable_vblank,
};

2. drm_atomic_helper_set_config

int drm_atomic_helper_set_config(struct drm_mode_set *set,
				 struct drm_modeset_acquire_ctx *ctx)
{
	struct drm_atomic_state *state;
	struct drm_crtc *crtc = set->crtc;
	int ret = 0;

	state = drm_atomic_state_alloc(crtc->dev);
	if (!state)
		return -ENOMEM;

	state->acquire_ctx = ctx;
	ret = __drm_atomic_helper_set_config(set, state);
	if (ret != 0)
		goto fail;

	ret = handle_conflicting_encoders(state, true);
	if (ret)
		goto fail;

	ret = drm_atomic_commit(state);

fail:
	drm_atomic_state_put(state);
	return ret;
}

        drm_atomic_helper_set_config主要涉及到结构体struct drm_atomic_state和drm_atomic_commit函数,我们后面会单独讨论这2个。

3. 流程图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1008079.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【题解】2596. 检查骑士巡视方案

题解&#xff1a; class Solution {int n,m;bool st[100][100];int flag;int dx[8]{-1,-2,-2,-1,1,2,2,1};int dy[8]{-2,-1,1,2,2,1,-1,-2}; public:bool checkValidGrid(vector<vector<int>>& grid) {m grid.size();n grid[0].size();dfs(grid,0,0,0);ret…

第二章 进程与线程 三、进程控制

目录 一、定义 二、实现方式&#xff08;用原语实现&#xff09; 注意&#xff1a; 1、原语是什么 2、如何实现原语的原子性 3、关中断指令和开中断指令是什么 三、进程控制的相关原语 1、进程的创建 ​编辑 2、进程的终止 3、进程的阻塞与唤醒&#xff08;阻塞和唤醒…

明星翻包视频的流行:背后的动机和原因

现如今&#xff0c;明星翻包视频正风靡社交媒体&#xff0c;引发了广泛的关注和讨论。这种趋势引发了一个问题&#xff1a;为什么现在的明星都喜欢翻包呢&#xff1f;要理解这一现象&#xff0c;我们需要深入探讨背后的动机和原因。在社交媒体的兴起和品牌合作的崭露头角的背景…

.360勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复

导言&#xff1a; 在当今数字时代&#xff0c;随着我们对计算机和互联网的依赖不断增加&#xff0c;威胁网络安全的因素也日益猖獗。其中&#xff0c; 360 勒索病毒是一股咄咄逼人的黑暗力量&#xff0c;它能够迅速加密您的数据文件&#xff0c;并以比特币等加密货币的形式勒索…

加密资产托管:迈向安全与合规的未来!

在当今数字化时代&#xff0c;加密货币正逐渐走进人们的视野&#xff0c;并成为越来越多投资者和机构的关注焦点。然而&#xff0c;加密领域仍存在一个主要问题&#xff1a;如果丢失了密钥&#xff0c;就会导致无法访问资产。为了解决这一问题&#xff0c;加密货币行业正在向资…

在Visual Studio Code中安装JetBrains Mono字体

让我们面对现实吧&#xff0c;JetBrain的Mono是一种漂亮的单行线字体&#xff0c;对于在IDE中展示代码和处理代码都很有用。它有一个增加的X高度&#xff0c;以获得更好的阅读体验&#xff0c;有更好的形状以看到字母列&#xff0c;还有一个开发者友好的各种连接词&#xff0c;…

【深度学习】对比学习

1.什么是对比学习 对比学习有的paper中称之为自监督学习&#xff0c;有的paper称之为无监督学习&#xff0c;自监督学习是无监督学习的一种形式&#xff0c;现有的文献中没有正式的对两者进行区分定义&#xff0c;这两种称呼都可以用。其主要思想是模型能够更加重新的学习到编码…

IIC总线上拉电阻计算

IIC总线上拉电阻计算 1. 概述2. 上拉电阻计算3. 总线传输速度与功率4. 实例计算 1. 概述 IIC&#xff08;Inter-Integrated Circuit&#xff09;其实是IICBus简称&#xff0c;所以中文应该叫集成电路总线&#xff0c;它是一种串行通信总线&#xff0c;使用多主从架构&#xff…

嵌入式Linux驱动开发(I2C专题)(三)

无需编写驱动直接访问设备_I2C-Tools介绍 参考资料&#xff1a; Linux驱动程序: drivers/i2c/i2c-dev.cI2C-Tools-4.2: https://mirrors.edge.kernel.org/pub/software/utils/i2c-tools/AP3216C&#xff1a; git clone https://e.coding.net/weidongshan/01_all_series_quick…

没出息的项目经理的5大表现

大家好&#xff0c;我是老原。 都说&#xff0c;30岁的项目经理凶猛如狼&#xff0c;40岁的项目经理狡猾如狐。 实际上&#xff0c;又有多少项目经理能做到这般。 有多少项目经理&#xff0c;兢兢业业工作个几年&#xff0c;最后还是守着一亩三分地&#xff0c;既没有升职加…

JSON注解和异常处理的使用

一、JSON数据返回 1.1.前言 JSON是一种轻量级的数据交换格式&#xff0c;易于阅读和编写&#xff0c;同时也易于机器解析和生成。JSON的常用场景包括&#xff1a; 前后端分离的项目中&#xff0c;后端向前端传送数据时 。 Ajax异步访问数据。RPC远程调用。 除了JSON&#x…

爽文式的带你快速理解Nginx

1 引入nginx的概念 Nginx是一个开源的Web服务器和反向代理服务器&#xff0c;它可以用来处理大量的网络请求和响应。Nginx使用事件驱动的非阻塞I/O模型&#xff0c;使其能够处理大量的并发连接。它还可以作为HTTP、HTTPS、SMTP、POP3和IMAP等协议的代理服务器&#xff0c;以及…

PM2 | NodeJS应用进程管理工具—PM2的基本使用

目录 1. pm2 简介 2. pm2的主要特性 3. 常用命令 3.1 pm2的安装与更新 3.1.1 pm2安装 3.1.2 pm2更新 3.2 pm2 启动运行指定的程序 3.2.1 正常启动应用程序 3.2.2 启动应用程序时并设置name 3.3 pm2 停止指定运行的程序 3.3.1 停止特定的应用 3.3.2 停止所有的应用 …

SpringMVC之JSON数据返回与异常处理机制---全方面讲解

一&#xff0c;JSON数据返回的理解 在Spring MVC中&#xff0c;当需要将数据以JSON格式返回给客户端时&#xff0c;可以使用ResponseBody注解或RestController注解将Controller方法的返回值直接转化为JSON格式并返回。这使得开发者可以方便地将Java对象转换为JSON&#xff0c;并…

【AIGC】斯坦福小镇升级版——AI-Town源码解读

写在前面的话&#xff1a; 接上一篇斯坦福小镇升级版——AI-Town搭建指南&#xff0c;本本篇将解读 AI-Town 使用的技术栈、代码架构、与LLM的交互&#xff0c;以及与斯坦福AI小镇的对比结果&#xff08;如想直接看结论可跳到文章最后&#xff09; 整体架构 技术栈 AI-Town 使…

“金钥匙”转动!安全狗成功护航第二十三届中国国际投资贸易洽谈会举办

9月8日至9月11日&#xff0c;为期4天的第二十三届中国国际投资贸易洽谈会在厦门顺利举办。 作为国内云原生安全领导厂商&#xff0c;安全狗凭借突出的安全综合实力&#xff0c;受委托并担任此次会议网络安保技术支撑单位。 厦门服云信息科技有限公司&#xff08;品牌名&#xf…

第一章 JAVA入门

文章目录 1.2 Java 的特点1.2.1 简单1.2.2 面向对象1.2.3 与平台无关① 平台与机器指令② C/C程序依赖平台③ Java 虚拟机与字节码1.2.4 多线程1.2.5 动态1.30安装 JDK1.3.1 平台简介0 Java SE②Java EE1.4 Java 程序的开发步骤②保存源文件1.5.2 编译1.8 Java之父-James Gosli…

spring boot+redis整合基础入门

文章目录 前言准备依赖项配置文件redis模板类注入设置序列化方式 实施基础字符串操作、超时设置Hash操作hash的使用场景以及优缺点 列表操作列表操作的应用场景以及优缺点 Set的基础操作Set类型的业务场景以及优缺点Demo地址 总结 前言 最近项目中有用到redis进行一些数据的缓…

【Linux】编译器 gcc/g++

1、背景知识 &#xff08;1&#xff09;[LMYhecs-38755 ~]$ gcc code.c -o code.exe -stdc99【-o 生成指定名字的可执行文件&#xff0c;-stdc99 以 C99 的标准执行程序】 &#xff08;2&#xff09;安装 g&#xff0c;yum install gcc-c 2、gcc如何完成 &#xff08;1&#x…

如何使用 Node.js和Express搭建服务器?

如何使用NodeJs搭建服务器 1. 准备工作1.1 安装Node.js 2. 安装express2.1 初始化package.json2.2 安装express2.3 Express 应用程序生成器 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段…