From 679ca523843004bd656a712e703489e15be992c8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 30 May 2024 13:01:52 +0300 Subject: [PATCH 1/3] drm/exynos/vidi: use drm_edid_duplicate() Don't open code drm_edid_duplicate(). While at it, drop the error message on allocation failure. Signed-off-by: Jani Nikula Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 11a720fef32b..f613df719a02 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -308,7 +308,6 @@ static int vidi_get_modes(struct drm_connector *connector) { struct vidi_context *ctx = ctx_from_connector(connector); struct edid *edid; - int edid_len; int count; /* @@ -320,12 +319,9 @@ static int vidi_get_modes(struct drm_connector *connector) return 0; } - edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; - edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL); - if (!edid) { - DRM_DEV_DEBUG_KMS(ctx->dev, "failed to allocate edid\n"); + edid = drm_edid_duplicate(ctx->raw_edid); + if (!edid) return 0; - } drm_connector_update_edid_property(connector, edid); From 10b566f21beaba03bcc519055ff03b515d3c4137 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 30 May 2024 13:01:53 +0300 Subject: [PATCH 2/3] drm/exynos/vidi: simplify fake edid handling Avoid assigning fake_edid_info to ctx->raw_edid. Always keep ctx->raw_edid either an allocated pointer or NULL. Defer fake_edid_info handling to .get_modes(). This should be functionally equivalent but slightly easier to follow. Signed-off-by: Jani Nikula Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 40 +++++++----------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index f613df719a02..d93801ace79a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -195,12 +195,11 @@ static ssize_t vidi_store_connection(struct device *dev, if (ctx->connected > 1) return -EINVAL; - /* use fake edid data for test. */ - if (!ctx->raw_edid) - ctx->raw_edid = (struct edid *)fake_edid_info; - - /* if raw_edid isn't same as fake data then it can't be tested. */ - if (ctx->raw_edid != (struct edid *)fake_edid_info) { + /* + * Use fake edid data for test. If raw_edid is set then it can't be + * tested. + */ + if (ctx->raw_edid) { DRM_DEV_DEBUG_KMS(dev, "edid data is not fake data.\n"); return -EINVAL; } @@ -261,15 +260,9 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, return -ENOMEM; } } else { - /* - * with connection = 0, free raw_edid - * only if raw edid data isn't same as fake data. - */ - if (ctx->raw_edid && ctx->raw_edid != - (struct edid *)fake_edid_info) { - kfree(ctx->raw_edid); - ctx->raw_edid = NULL; - } + /* with connection = 0, free raw_edid */ + kfree(ctx->raw_edid); + ctx->raw_edid = NULL; } ctx->connected = vidi->connection; @@ -310,16 +303,7 @@ static int vidi_get_modes(struct drm_connector *connector) struct edid *edid; int count; - /* - * the edid data comes from user side and it would be set - * to ctx->raw_edid through specific ioctl. - */ - if (!ctx->raw_edid) { - DRM_DEV_DEBUG_KMS(ctx->dev, "raw_edid is null.\n"); - return 0; - } - - edid = drm_edid_duplicate(ctx->raw_edid); + edid = drm_edid_duplicate(ctx->raw_edid ?: fake_edid_info); if (!edid) return 0; @@ -467,10 +451,8 @@ static void vidi_remove(struct platform_device *pdev) { struct vidi_context *ctx = platform_get_drvdata(pdev); - if (ctx->raw_edid != (struct edid *)fake_edid_info) { - kfree(ctx->raw_edid); - ctx->raw_edid = NULL; - } + kfree(ctx->raw_edid); + ctx->raw_edid = NULL; component_del(&pdev->dev, &vidi_component_ops); } From 2210093478443cd57cff5950379fec31ee8a5f79 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 30 May 2024 13:01:54 +0300 Subject: [PATCH 3/3] drm/exynos/vidi: convert to struct drm_edid Prefer the struct drm_edid based functions for storing the EDID and updating the connector. It would be better if the vidi connection ioctl passed in the EDID size separately instead of relying on the extension count specified in the EDID, but that's what we have to rely on. Signed-off-by: Jani Nikula Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 44 ++++++++++++++---------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index d93801ace79a..6de0cced6c9d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -41,7 +41,7 @@ struct vidi_context { struct exynos_drm_crtc *crtc; struct drm_connector connector; struct exynos_drm_plane planes[WINDOWS_NR]; - struct edid *raw_edid; + const struct drm_edid *raw_edid; unsigned int clkdiv; unsigned int connected; bool suspended; @@ -245,23 +245,27 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, } if (vidi->connection) { - struct edid *raw_edid; + const struct drm_edid *drm_edid; + const struct edid *raw_edid; + size_t size; - raw_edid = (struct edid *)(unsigned long)vidi->edid; - if (!drm_edid_is_valid(raw_edid)) { + raw_edid = (const struct edid *)(unsigned long)vidi->edid; + size = (raw_edid->extensions + 1) * EDID_LENGTH; + + drm_edid = drm_edid_alloc(raw_edid, size); + if (!drm_edid) + return -ENOMEM; + + if (!drm_edid_valid(drm_edid)) { + drm_edid_free(drm_edid); DRM_DEV_DEBUG_KMS(ctx->dev, "edid data is invalid.\n"); return -EINVAL; } - ctx->raw_edid = drm_edid_duplicate(raw_edid); - if (!ctx->raw_edid) { - DRM_DEV_DEBUG_KMS(ctx->dev, - "failed to allocate raw_edid.\n"); - return -ENOMEM; - } + ctx->raw_edid = drm_edid; } else { /* with connection = 0, free raw_edid */ - kfree(ctx->raw_edid); + drm_edid_free(ctx->raw_edid); ctx->raw_edid = NULL; } @@ -300,18 +304,22 @@ static const struct drm_connector_funcs vidi_connector_funcs = { static int vidi_get_modes(struct drm_connector *connector) { struct vidi_context *ctx = ctx_from_connector(connector); - struct edid *edid; + const struct drm_edid *drm_edid; int count; - edid = drm_edid_duplicate(ctx->raw_edid ?: fake_edid_info); - if (!edid) + if (ctx->raw_edid) + drm_edid = drm_edid_dup(ctx->raw_edid); + else + drm_edid = drm_edid_alloc(fake_edid_info, sizeof(fake_edid_info)); + + if (!drm_edid) return 0; - drm_connector_update_edid_property(connector, edid); + drm_edid_connector_update(connector, drm_edid); - count = drm_add_edid_modes(connector, edid); + count = drm_edid_connector_add_modes(connector); - kfree(edid); + drm_edid_free(drm_edid); return count; } @@ -451,7 +459,7 @@ static void vidi_remove(struct platform_device *pdev) { struct vidi_context *ctx = platform_get_drvdata(pdev); - kfree(ctx->raw_edid); + drm_edid_free(ctx->raw_edid); ctx->raw_edid = NULL; component_del(&pdev->dev, &vidi_component_ops);