上节聊到应用传下来的参数均被存到对应的state。为了使驱动的容错能力比较强,在更新到硬件寄存器之前还需要进行一系列的参数检查,比如要显示图像的大小是否会超过支持分辨率,如果超过了显示的硬件可能会异常;再比如应用需要硬件进行缩放图像但是硬件不支持,强制配置到硬件上面即使不出错也肯定达不到预期的效果,等等场景,一起看下drm驱动中是如何进行处理的。

驱动错误检查的入口为drm_atomic_check_only

int drm_atomic_check_only(struct drm_atomic_state *state)
{struct drm_device *dev = state->dev;struct drm_mode_config *config = &dev->mode_config;struct drm_plane *plane;struct drm_plane_state *plane_state;struct drm_crtc *crtc;struct drm_crtc_state *crtc_state;for_each_plane_in_state(state, plane, plane_state, i) {ret = drm_atomic_plane_check(plane, plane_state);if (ret) {return ret;}}for_each_crtc_in_state(state, crtc, crtc_state, i) {ret = drm_atomic_crtc_check(crtc, crtc_state);if (ret) {return ret;}}if (config->funcs->atomic_check)ret = config->funcs->atomic_check(state->dev, state);if (!state->allow_modeset) {for_each_crtc_in_state(state, crtc, crtc_state, i) {if (crtc_state->mode_changed ||crtc_state->active_changed) {return -EINVAL;}}}return ret;
}

这里主要调用了三个函数

drm_atomic_plane_check:用来check plane state的相关参数

drm_atomic_crtc_check:用来check crtc state的相关参数

config->funcs->atomic_check:此函数是可选的,可以不实现,也可以由drm驱动实现,也可以直接使用drm_atomic_helper_check

比如rockchip

drm_atomic_plane_check

先来看drm_atomic_plane_check做了什么事情

static int drm_atomic_plane_check(struct drm_plane *plane,struct drm_plane_state *state)
{unsigned int fb_width, fb_height;int ret;if (WARN_ON(state->crtc && !state->fb)) {return -EINVAL;} else if (WARN_ON(state->fb && !state->crtc)) {return -EINVAL;}if (!state->crtc)return 0;/* Check whether this plane is usable on this CRTC */if (!(plane->possible_crtcs & drm_crtc_mask(state->crtc))) {return -EINVAL;}/* Check whether this plane supports the fb pixel format. */ret = drm_plane_check_pixel_format(plane, state->fb->format->format);if (ret) {struct drm_format_name_buf format_name;return ret;}/* Give drivers some help against integer overflows */if (state->crtc_w > INT_MAX ||state->crtc_x > INT_MAX - (int32_t) state->crtc_w ||state->crtc_h > INT_MAX ||state->crtc_y > INT_MAX - (int32_t) state->crtc_h) {return -ERANGE;}fb_width = state->fb->width << 16;fb_height = state->fb->height << 16;/* Make sure source coordinates are inside the fb. */if (state->src_w > fb_width ||state->src_x > fb_width - state->src_w ||state->src_h > fb_height ||state->src_y > fb_height - state->src_h) {state->src_w >> 16, ((state->src_w & 0xffff) * 15625) >> 10,state->src_h >> 16, ((state->src_h & 0xffff) * 15625) >> 10,state->src_x >> 16, ((state->src_x & 0xffff) * 15625) >> 10,state->src_y >> 16, ((state->src_y & 0xffff) * 15625) >> 10);return -ENOSPC;}return 0;
}
  1. 对指针进行判断,如果传下来的指针不存在,后面的一切都没有意义
  2. check plane是否支持当前要显示的format

drm_plane_check_pixel_format的实现非常简单,遍历所有plane支持的format,找到返回0,找不到返回错误。

int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format)
{unsigned int i;for (i = 0; i < plane->format_count; i++) {if (format == plane->format_types[i])return 0;}return -EINVAL;
}

plane->format_types是在plane创建的时候指定的,可以详细看下drm_universal_plane_init这里贴出来部分代码

drm_universal_plane_init(... ...const uint32_t *formats, unsigned int format_count,.)
{... ...plane->format_types = kmalloc_array(format_count, sizeof(uint32_t),GFP_KERNEL);memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));plane->format_count = format_count;... ...
}
  1. check要显示的区域是否越界
  2. check显示区域是否超过内存大小

state->fb->width和state->fb->height可以认为是在内存中的图像大小,如果应用想要显示的部分超过显存肯定是不对的,龙哥在最简单的DRM应用程序 (plane-test)_何小龙的博客-CSDN博客的一张图片画的非常清楚,我引用一下

drm_atomic_crtc_check

主要检查crtc 状态逻辑是否正常;正如注释里提到的这里只进行通用的状态检查,厂商之间的硬件差异由crtc->atomic_check()来进行处理(稍后会介绍到在哪里调用)

For hw that does not, it should be checked in driver's crtc->atomic_check() vfunc;Add generic modeset state checks once we support those.

因此此函数做的工作比较少,逻辑也比较清楚,不做解释。

static int drm_atomic_crtc_check(struct drm_crtc *crtc,struct drm_crtc_state *state)
{/* NOTE: we explicitly don't enforce constraints such as primary* layer covering entire screen, since that is something we want* to allow (on hw that supports it).  For hw that does not, it* should be checked in driver's crtc->atomic_check() vfunc.** TODO: Add generic modeset state checks once we support those.*/if (state->active && !state->enable) {DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active without enabled\n",crtc->base.id, crtc->name);return -EINVAL;}if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&WARN_ON(state->enable && !state->mode_blob)) {DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled without mode blob\n",crtc->base.id, crtc->name);return -EINVAL;}if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&WARN_ON(!state->enable && state->mode_blob)) {DRM_DEBUG_ATOMIC("[CRTC:%d:%s] disabled with mode blob\n",crtc->base.id, crtc->name);return -EINVAL;}if (state->event && !state->active && !crtc->state->active) {DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requesting event but off\n",crtc->base.id, crtc->name);return -EINVAL;}return 0;
}

上面两个函数主要是基本的,通用的参数检查,而不同的soc厂商的显示硬件支持的功能是不同的;这些差异化功能的check就需要由各个厂商自己来实现,接着看第三个函数指针的调用

config->funcs->atomic_check

此回调是在驱动初始化的时候配置的,一般使用drm_atomic_helper_check也可以自己实现,但基本思想都一样——调用drm驱动各组件的atomic_check回调;另外还有一些标记位的置位,mode_changed,active_changed等

int drm_atomic_helper_check(struct drm_device *dev,struct drm_atomic_state *state)
{int ret;ret = drm_atomic_helper_check_modeset(dev, state);if (ret)return ret;ret = drm_atomic_helper_check_planes(dev, state);if (ret)return ret;if (state->legacy_cursor_update)state->async_update = !drm_atomic_helper_async_check(dev, state);return ret;
}

心心念念由驱动实现的plane->helper_private->atomic_check和crtc->helper_private->atomic_check它终于来了

int drm_atomic_helper_check_modeset(struct drm_device *dev,struct drm_atomic_state *state)
{for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {bool has_connectors = !!new_crtc_state->connector_mask;WARN_ON(!drm_modeset_is_locked(&crtc->mutex));if (!drm_mode_equal(&old_crtc_state->mode, &new_crtc_state->mode)) {new_crtc_state->mode_changed = true;}if (old_crtc_state->enable != new_crtc_state->enable) {new_crtc_state->mode_changed = true;new_crtc_state->connectors_changed = true;}if (old_crtc_state->active != new_crtc_state->active) {new_crtc_state->active_changed = true;}if (new_crtc_state->enable != has_connectors) {return -EINVAL;}}for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) {const struct drm_connector_helper_funcs *funcs = connector->helper_private;if (funcs->atomic_check)ret = funcs->atomic_check(connector, new_connector_state);if (ret)return ret;connectors_mask += BIT(i);}
}

可能看到这里还是会有疑惑,回调里的atomic_check到底做了什么事情。如果不了解显示硬件不是很容易理解,我们先看下别人家的驱动是怎么实现的,以开源的rockchip的vop_plane_atomic_check为例,代码在rockchip_drm_vop.c

vop_plane_atomic_check的主要工作

  1. 检查缩放参数配置是不是符合要求
  2. 将drm_format转换成rockchip自己的format看自己是否支持
  3. yuv格式是否2pixel对齐(硬件上的限制?)
static int vop_plane_atomic_check(struct drm_plane *plane,struct drm_plane_state *state)
{struct drm_crtc *crtc = state->crtc;struct drm_crtc_state *crtc_state;struct drm_framebuffer *fb = state->fb;struct vop_win *vop_win = to_vop_win(plane);const struct vop_win_data *win = vop_win->data;int ret;struct drm_rect clip;int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :DRM_PLANE_HELPER_NO_SCALING;int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :DRM_PLANE_HELPER_NO_SCALING;if (!crtc || !fb)return 0;crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);if (WARN_ON(!crtc_state))return -EINVAL;clip.x1 = 0;clip.y1 = 0;clip.x2 = crtc_state->adjusted_mode.hdisplay;clip.y2 = crtc_state->adjusted_mode.vdisplay;ret = drm_plane_helper_check_state(state, &clip,min_scale, max_scale,true, true);if (ret)return ret;if (!state->visible)return 0;ret = vop_convert_format(fb->format->format);if (ret < 0)return ret;/** Src.x1 can be odd when do clip, but yuv plane start point* need align with 2 pixel.*/if (is_yuv_support(fb->format->format) && ((state->src.x1 >> 16) % 2)) {DRM_ERROR("Invalid Source: Yuv format not support odd xpos\n");return -EINVAL;}return 0;
}

drm_atomic_helper_async_check是异步刷新相关的,我们先不关心

驱动的实现和硬件能力强相关,我们只需要了解大体框架即可。

至此所有的参数都被检查了,没有问题下一步就是要更新到硬件上了。

扯了那么多总结成一张简单的图

DRM驱动(六)之atomic_check相关推荐

  1. 《DRM 专栏》| 彻底入门 DRM 驱动

    https://cloud.tencent.com/developer/article/2021477 前面的 DRM 应用程序系列文章中,我们学习了如何使用 libdrm 接口编写 DRM 应用程序 ...

  2. DRM驱动代码分析:图层参数更新

    前言: 无业居家,闭门造车.非常欢迎大家帮忙指正. 有些代码流程是看代码分析的,没有去验证是否正确 我对DRM框架的很多东西都不了解,所以有些地方会比较生硬.熟悉学习需要时间,文章一直堆在草稿箱可能会 ...

  3. fb驱动安装linux系统,drm 驱动是如何创建 fb device 的

    drm 驱动是如何创建 fb device 的 什么是 drm? drm 是一个 Linux 内核的显示系统驱动框架,区别于另外一个 DRM数字版权保护 drm 是一个管理 GPU 的显示框架 在内核 ...

  4. DRM驱动(三)之CREATE_DUMB

    上节讲到显示处理器会将一块含有图像数据的memory进行处理后送到下一级.后面几节我会根据龙哥的<最简单的DRM应用程序>一步一步分析用户调用的接口在drm驱动中有怎么样的处理. DRM驱 ...

  5. DRM驱动(二)之DRM驱动模块简介

    上节在<显示处理器介绍>中阐述了显示处理器的大致功能以及要配置的参数:本节将介绍一下DRM驱动中的模块与显示处理器的关系. 做过显示的都知道,目前大多数厂商已经抛弃fb框架,使用drm驱动 ...

  6. DRM驱动(五)之drm_atomic_state

    上节讲到<DRM驱动(四)之ADD_FB>调用drmModeAddFB创建drm_framebuffer.然后通过 drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB ...

  7. DRM框架(vkms)分析(9)----drm驱动创建fbdevice分析(以rockchip_drm_drv为例)

    本文主要介绍DRM框架里的fbdev兼容逻辑 一 framebuffer框架简单介绍 framebuffer框架下fbdev的注册主要三步步: (1)创建fbdev操作函数,以rockchip为例: ...

  8. DRM驱动(一)之显示处理器介绍

    显示处理器是什么 将在内存中的图像数据,转化为电信号送到显示设备称为显示控制器,比如早期的LCDC.后面进行了拓展,可以处理一些简单的图像,比如缩放.旋转.合成等,如瑞芯的vop,高通的sde称为显示 ...

  9. 基于STM32MP157的GPU编程之DRM驱动调试

    linux系统GPU编程之DRM编程 背景: framebuffer大家都知道哈,打开/dev/fb0设备节点,然后开辟一段内存(即显存),再mmap,在吧图形数据填充到这段显存里面.怎么填,比如QT ...

最新文章

  1. 短波通信为何经久不衰?
  2. ⑨ 设计模式的艺术-22.中介者(Mediator)模式
  3. [ZZ]STM32之RCC
  4. No space left on device错误解决
  5. 怎么下载并安装python_怎么下载官网python并安装
  6. 最后一天,特邀小姐姐配音拉票,今日可投28票
  7. 前端学习(1022):jquery学习目标
  8. java list拷贝_深入了解浅拷贝与深拷贝
  9. SpringMVC框架搭建( 使用Jar包搭建)
  10. 基于Vue实现关键词实时搜索高亮显示关键词
  11. 别再问“自媒体怎么做”
  12. jmeter非GUI的运行命令
  13. 华为员工实力炫富,工作六年有房有豪车,存款六十万
  14. 三菱plcascll转换16进制_三菱ASCII码指令
  15. Landsat 8数据介绍
  16. python模拟登录教务系统
  17. 基于HAL库使用cubemx配置,驱动MAX30102血氧传感器基础历程
  18. 写在今年(2022)清明节前
  19. 医学影像处理科研训练
  20. Adobe Camera Raw v15.0.0.1264 增效工具

热门文章

  1. ur机器人编程-程序流程
  2. Hive On Spark
  3. 电容的材质资料/什么cog,x5r y5v等知识
  4. 未转变者rust服务器推荐,你能在这些最佳生存游戏中活多久?
  5. 厉害了,可以不重启JVM就替换掉已经加载的类?
  6. SAP_FI统驭科目
  7. xmp预设怎么导入pr_ACR预设(XMP文件)安装教程(通用篇)
  8. 【T+】畅捷通T+服务管理中,异步任务服务(TPlusPopAsyncTaskService1700)无法启动
  9. mysql2008安装虚拟机_在虚拟机xp系统中安装SQL Server2008的方法
  10. 金融科技对商业银行的挑战与冲击