[PATCH v3] drm/gud: move format init from gud_probe()

From: Ruben Wauters

Date: Mon Oct 26 2026 - 17:01:41 EST


As part of the cleanup of gud_probe(), this patch splits off format init
code from gud_probe into it's own function. This makes the code more
compartmentalised and easier to follow, and makes gud_probe() smaller
and also easier to read.

Signed-off-by: Ruben Wauters <rubenru09@xxxxxxx>
---
V1 -> V2:
- Removed output parameters for gud_get_formats()
- Added gud_get_max_buffer_size() helper function

Apologies this v2 took so long

V2 -> V3:
- Fix potential num_formats underflow
- Skip XRGB8888 in size calculations if emulated
- Remove redundant r1 and XRGB1111 size calculations
---
---
drivers/gpu/drm/gud/gud_drv.c | 185 ++++++++++++++++++++--------------
1 file changed, 111 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index 680447f426f3..36adf2e2b6a2 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -435,11 +435,115 @@ static void gud_free_buffers_and_mutex(void *data)
mutex_destroy(&gdrm->ctrl_lock);
}

-static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static size_t gud_get_max_buffer_size(struct gud_device *gdrm, u32 *formats, u32 num_formats)
+{
+ struct drm_device *drm = &gdrm->drm;
+ size_t max_buffer_size = 0;
+ size_t fmt_buf_size;
+ int i;
+
+ for (i = 0; i < num_formats; i++) {
+ const struct drm_format_info *info = drm_format_info(formats[i]);
+
+ /* Skip over emulated XRGB8888 */
+ if (formats[i] == DRM_FORMAT_XRGB8888 && gdrm->xrgb8888_emulation_format)
+ continue;
+
+ fmt_buf_size = drm_format_info_min_pitch(info, 0, drm->mode_config.max_width) *
+ drm->mode_config.max_height;
+ max_buffer_size = max(max_buffer_size, fmt_buf_size);
+ }
+
+ return max_buffer_size;
+}
+
+static int gud_get_formats(struct gud_device *gdrm, u32 *formats)
{
const struct drm_format_info *xrgb8888_emulation_format = NULL;
bool rgb565_supported = false, xrgb8888_supported = false;
unsigned int num_formats_dev, num_formats = 0;
+ u8 *formats_dev;
+ struct drm_device *drm = &gdrm->drm;
+ struct device *usb_device = gdrm->drm.dev;
+ int ret, i;
+
+ formats_dev = devm_kmalloc(usb_device, GUD_FORMATS_MAX_NUM, GFP_KERNEL);
+ if (!formats_dev)
+ return -ENOMEM;
+
+ ret = gud_usb_get(gdrm, GUD_REQ_GET_FORMATS, 0, formats_dev, GUD_FORMATS_MAX_NUM);
+ if (ret < 0)
+ return ret;
+
+ num_formats_dev = ret;
+ for (i = 0; i < num_formats_dev; i++) {
+ const struct drm_format_info *info;
+ u32 format;
+
+ format = gud_to_fourcc(formats_dev[i]);
+ if (!format) {
+ drm_dbg(drm, "Unsupported format: 0x%02x\n", formats_dev[i]);
+ continue;
+ }
+
+ if (format == GUD_DRM_FORMAT_R1)
+ info = &gud_drm_format_r1;
+ else if (format == GUD_DRM_FORMAT_XRGB1111)
+ info = &gud_drm_format_xrgb1111;
+ else
+ info = drm_format_info(format);
+
+ switch (format) {
+ case GUD_DRM_FORMAT_R1:
+ fallthrough;
+ case DRM_FORMAT_R8:
+ fallthrough;
+ case GUD_DRM_FORMAT_XRGB1111:
+ fallthrough;
+ case DRM_FORMAT_RGB332:
+ fallthrough;
+ case DRM_FORMAT_RGB888:
+ if (!xrgb8888_emulation_format)
+ xrgb8888_emulation_format = info;
+ break;
+ case DRM_FORMAT_RGB565:
+ rgb565_supported = true;
+ if (!xrgb8888_emulation_format)
+ xrgb8888_emulation_format = info;
+ break;
+ case DRM_FORMAT_XRGB8888:
+ xrgb8888_supported = true;
+ break;
+ }
+
+ if (format == GUD_DRM_FORMAT_R1 || format == GUD_DRM_FORMAT_XRGB1111)
+ continue; /* Internal not for userspace */
+
+ formats[num_formats++] = format;
+ }
+
+ if (!num_formats && !xrgb8888_emulation_format) {
+ dev_err(usb_device, "No supported pixel formats found\n");
+ return -EINVAL;
+ }
+
+ /* Prefer speed over color depth */
+ if (rgb565_supported)
+ drm->mode_config.preferred_depth = 16;
+
+ if (!xrgb8888_supported && xrgb8888_emulation_format) {
+ gdrm->xrgb8888_emulation_format = xrgb8888_emulation_format;
+ formats[num_formats++] = DRM_FORMAT_XRGB8888;
+ }
+
+ devm_kfree(usb_device, formats_dev);
+
+ return num_formats;
+}
+
+static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ int num_formats = 0;
struct usb_endpoint_descriptor *bulk_out;
struct gud_display_descriptor_req desc;
struct device *dev = &intf->dev;
@@ -447,9 +551,8 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct gud_device *gdrm;
struct drm_device *drm;
struct device *dma_dev;
- u8 *formats_dev;
u32 *formats;
- int ret, i;
+ int ret;

ret = usb_find_bulk_out_endpoint(intf->cur_altsetting, &bulk_out);
if (ret)
@@ -510,81 +613,16 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
drm->mode_config.helper_private = &gud_mode_config_helpers;

/* Format init */
- formats_dev = devm_kmalloc(dev, GUD_FORMATS_MAX_NUM, GFP_KERNEL);
/* Add room for emulated XRGB8888 */
formats = devm_kmalloc_array(dev, GUD_FORMATS_MAX_NUM + 1, sizeof(*formats), GFP_KERNEL);
- if (!formats_dev || !formats)
+ if (!formats)
return -ENOMEM;

- ret = gud_usb_get(gdrm, GUD_REQ_GET_FORMATS, 0, formats_dev, GUD_FORMATS_MAX_NUM);
- if (ret < 0)
- return ret;
-
- num_formats_dev = ret;
- for (i = 0; i < num_formats_dev; i++) {
- const struct drm_format_info *info;
- size_t fmt_buf_size;
- u32 format;
-
- format = gud_to_fourcc(formats_dev[i]);
- if (!format) {
- drm_dbg(drm, "Unsupported format: 0x%02x\n", formats_dev[i]);
- continue;
- }
-
- if (format == GUD_DRM_FORMAT_R1)
- info = &gud_drm_format_r1;
- else if (format == GUD_DRM_FORMAT_XRGB1111)
- info = &gud_drm_format_xrgb1111;
- else
- info = drm_format_info(format);
-
- switch (format) {
- case GUD_DRM_FORMAT_R1:
- fallthrough;
- case DRM_FORMAT_R8:
- fallthrough;
- case GUD_DRM_FORMAT_XRGB1111:
- fallthrough;
- case DRM_FORMAT_RGB332:
- fallthrough;
- case DRM_FORMAT_RGB888:
- if (!xrgb8888_emulation_format)
- xrgb8888_emulation_format = info;
- break;
- case DRM_FORMAT_RGB565:
- rgb565_supported = true;
- if (!xrgb8888_emulation_format)
- xrgb8888_emulation_format = info;
- break;
- case DRM_FORMAT_XRGB8888:
- xrgb8888_supported = true;
- break;
- }
-
- fmt_buf_size = drm_format_info_min_pitch(info, 0, drm->mode_config.max_width) *
- drm->mode_config.max_height;
- max_buffer_size = max(max_buffer_size, fmt_buf_size);
-
- if (format == GUD_DRM_FORMAT_R1 || format == GUD_DRM_FORMAT_XRGB1111)
- continue; /* Internal not for userspace */
-
- formats[num_formats++] = format;
- }
+ num_formats = gud_get_formats(gdrm, formats);
+ if (num_formats <= 0)
+ return num_formats;

- if (!num_formats && !xrgb8888_emulation_format) {
- dev_err(dev, "No supported pixel formats found\n");
- return -EINVAL;
- }
-
- /* Prefer speed over color depth */
- if (rgb565_supported)
- drm->mode_config.preferred_depth = 16;
-
- if (!xrgb8888_supported && xrgb8888_emulation_format) {
- gdrm->xrgb8888_emulation_format = xrgb8888_emulation_format;
- formats[num_formats++] = DRM_FORMAT_XRGB8888;
- }
+ max_buffer_size = gud_get_max_buffer_size(gdrm, formats, num_formats);

if (desc.max_buffer_size)
max_buffer_size = le32_to_cpu(desc.max_buffer_size);
@@ -650,7 +688,6 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id)
return ret;

devm_kfree(dev, formats);
- devm_kfree(dev, formats_dev);

drm_client_setup(drm, NULL);

--
2.55.0