To allows the userspace to test many hardware configuration, introduce a new interface to configure the available formats per planes. VKMS supports many formats, so the userspace can choose any combination of them. The supported formats are configured by writing in the file supported_formats: - `+*` - Add all available formats - `-*` - Remove all formats - `+<fourcc>` - Add the format (for example `+AR24` to add ARGB8888 format) - `-<FOURCC>` - Remove the format The current interface is: /config/vkms DEVICE_1 ┣━ enable ┗━ planes ┗━ PLANE_1 ┗━ supported_formats Signed-off-by: Louis Chauvet <louis.chauvet@xxxxxxxxxxx> --- drivers/gpu/drm/vkms/vkms_configfs.c | 75 ++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c index 5f416260f209fc98939f8addd175e5c3b8e35353..eeb0c1e1b225f2a1a35ac6deb9457b90ba6542e5 100644 --- a/drivers/gpu/drm/vkms/vkms_configfs.c +++ b/drivers/gpu/drm/vkms/vkms_configfs.c @@ -153,14 +153,89 @@ static ssize_t plane_default_rotation_store(struct config_item *item, return count; } +static ssize_t plane_supported_formats_show(struct config_item *item, char *page) +{ + struct vkms_config_plane *plane = plane_item_to_vkms_configfs_plane(item)->vkms_config_plane; + struct vkms_configfs_device *vkms_configfs = plane_item_to_vkms_configfs_device(item); + + page[0] = '\0'; + + scoped_guard(mutex, &vkms_configfs->lock) + { + for (int i = 0; i < plane->supported_formats_count; i++) { + char tmp[6] = { 0 }; + const ssize_t ret = snprintf(tmp, ARRAY_SIZE(tmp), "%.*s\n", + (int)sizeof(plane->supported_formats[i]), + (char *)&plane->supported_formats[i]); + if (ret < 0) + return ret; + /* Limitation of ConfigFS attributes, an attribute can't be bigger than PAGE_SIZE */ + if (ret + strlen(page) > PAGE_SIZE - 1) + return -ENOMEM; + strncat(page, tmp, ARRAY_SIZE(tmp)); + } + } + + return strlen(page); +} + +static ssize_t plane_supported_formats_store(struct config_item *item, + const char *page, size_t count) +{ + struct vkms_config_plane *plane = plane_item_to_vkms_configfs_plane(item)->vkms_config_plane; + struct vkms_configfs_device *vkms_configfs = plane_item_to_vkms_configfs_device(item); + int ret = 0; + int ptr = 0; + + scoped_guard(mutex, &vkms_configfs->lock) + { + while (ptr < count) { + if (page[ptr] == '+') { + char tmp[4] = { ' ', ' ', ' ', ' ' }; + + memcpy(tmp, &page[ptr + 1], min(sizeof(tmp), count - (ptr + 1))); + if (tmp[0] == '*') { + ret = vkms_config_plane_add_all_formats(plane); + if (ret) + return ret; + ptr += 1; + } else { + ret = vkms_config_plane_add_format(plane, *(int *)tmp); + if (ret) + return ret; + ptr += 4; + } + } else if (page[ptr] == '-') { + char tmp[4] = { ' ', ' ', ' ', ' ' }; + + memcpy(tmp, &page[ptr + 1], min(sizeof(tmp), count - (ptr + 1))); + if (tmp[0] == '*') { + vkms_config_plane_remove_all_formats(plane); + ptr += 1; + } else { + vkms_config_plane_remove_format(plane, *(int *)tmp); + + ptr += 4; + } + } + /* Skip anything that is not a + or a - */ + ptr += 1; + } + } + + return count; +} + CONFIGFS_ATTR(plane_, type); CONFIGFS_ATTR(plane_, supported_rotations); CONFIGFS_ATTR(plane_, default_rotation); +CONFIGFS_ATTR(plane_, supported_formats); static struct configfs_attribute *plane_attrs[] = { &plane_attr_type, &plane_attr_supported_rotations, &plane_attr_default_rotation, + &plane_attr_supported_formats, NULL, }; -- 2.47.1