本文主要是介绍drm 和 sysfs,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
DRM 全称是Direct Rendering Manager,进行显示输出管理、buffer 分配、帧缓冲。对应userspace 库为libdrm,libdrm 库提供了一系列友好的控制封装,使用户可以方便的进行显示的控制和buffer 申请。
DRM的设备节点为"/dev/dri/cardX", X 为0-15 的数值,默认使用的是/dev/dri/card0。
CRTC | 显示控制器,在rockchip 平台是SOC 内部VOP(部分文档也称为LCDC)模块的抽象 |
Plane | 图层,在rockchip 平台是SOC 内部VOP(LCDC)模块win 图层的抽象 |
Encoder | 输出转换器,指RGB、LVDS、DSI、eDP、HDMI、CVBS、VGA 等显示接口 |
Connector | 连接器,指encoder 和panel 之间交互的接口部分 |
Bridge | 桥接设备,一般用于注册encoder 后面另外再接的转换芯片,如DSI2HDMI 转换芯片 |
Panel | 泛指屏,各种LCD、HDMI 等显示设备的抽象 |
GEM | buffer 管理和分配,类似android 下的ion |
drm sysfs 初始化
/*** drm_sysfs_init - initialize sysfs helpers** This is used to create the DRM class, which is the implicit parent of any* other top-level DRM sysfs objects.** You must call drm_sysfs_destroy() to release the allocated resources.** Return: 0 on success, negative error code on failure.*/
int drm_sysfs_init(void)
{int err;drm_class = class_create(THIS_MODULE, "drm");//sys/class/drmif (IS_ERR(drm_class))return PTR_ERR(drm_class);err = class_create_file(drm_class, &class_attr_version.attr);if (err) {class_destroy(drm_class);drm_class = NULL;return err;}drm_class->devnode = drm_devnode;drm_setup_hdcp_srm(drm_class);return 0;
}
connector 注册的时候会注册进去
static DEVICE_ATTR_RW(status);//显示器的连接状态
static DEVICE_ATTR_RO(enabled);//使能
static DEVICE_ATTR_RO(dpms);//dpms
static DEVICE_ATTR_RO(modes);//分辨率static struct attribute *connector_dev_attrs[] = {&dev_attr_status.attr,&dev_attr_enabled.attr,&dev_attr_dpms.attr,&dev_attr_modes.attr,NULL
};static struct bin_attribute edid_attr = {.attr.name = "edid",.attr.mode = 0444,.size = 0,.read = edid_show,
};static struct bin_attribute *connector_bin_attrs[] = {&edid_attr,NULL
};static const struct attribute_group connector_dev_group = {.attrs = connector_dev_attrs,.bin_attrs = connector_bin_attrs,
};static const struct attribute_group *connector_dev_groups[] = {&connector_dev_group,NULL
};
int drm_sysfs_connector_add(struct drm_connector *connector)
{struct drm_device *dev = connector->dev;if (connector->kdev)return 0;connector->kdev =device_create_with_groups(drm_class, dev->primary->kdev, 0,connector, connector_dev_groups,"card%d-%s", dev->primary->index,connector->name);DRM_DEBUG("adding \"%s\" to sysfs\n",connector->name);if (IS_ERR(connector->kdev)) {DRM_ERROR("failed to register connector device: %ld\n", PTR_ERR(connector->kdev));return PTR_ERR(connector->kdev);}if (connector->ddc)return sysfs_create_link(&connector->kdev->kobj,&connector->ddc->dev.kobj, "ddc");return 0;
}
重要的2个show函数如下,显示器的edid和modes
static ssize_t modes_show(struct device *device,struct device_attribute *attr,char *buf)
{struct drm_connector *connector = to_drm_connector(device);struct drm_display_mode *mode;int written = 0;mutex_lock(&connector->dev->mode_config.mutex);list_for_each_entry(mode, &connector->modes, head) {written += snprintf(buf + written, PAGE_SIZE - written, "%s\n",mode->name);}mutex_unlock(&connector->dev->mode_config.mutex);return written;
}
static ssize_t edid_show(struct file *filp, struct kobject *kobj,struct bin_attribute *attr, char *buf, loff_t off,size_t count)
{struct device *connector_dev = kobj_to_dev(kobj);struct drm_connector *connector = to_drm_connector(connector_dev);unsigned char *edid;size_t size;ssize_t ret = 0;mutex_lock(&connector->dev->mode_config.mutex);if (!connector->edid_blob_ptr)goto unlock;edid = connector->edid_blob_ptr->data;size = connector->edid_blob_ptr->length;if (!edid)goto unlock;if (off >= size)goto unlock;if (off + count > size)count = size - off;memcpy(buf, edid + off, count);ret = count;
unlock:mutex_unlock(&connector->dev->mode_config.mutex);return ret;
}
这篇关于drm 和 sysfs的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!