From b2c448da5ceba52714a073d3018b8f664aecf0bf Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Tue, 20 Nov 2012 14:19:00 -0500 Subject: [PATCH] drm/exynos: Let drm handle edid allocations There's no need to allocate edid twice and do a memcpy when drm helpers exist to do just that. This patch cleans that interaction up, and doesn't keep the edid hanging around in the connector. BUG=chromium-os:36513 TEST=Tested on snow boot/hotplug/idle suspend/lid suspend Change-Id: Ifb971a7a6c6ae66ce431b9a256886d9699adbd09 Signed-off-by: Sean Paul Reviewed-on: https://gerrit.chromium.org/gerrit/38406 --- drivers/gpu/drm/exynos/exynos_drm_connector.c | 29 +++++++------------ drivers/gpu/drm/exynos/exynos_drm_display.h | 5 ++-- drivers/gpu/drm/exynos/exynos_hdmi.c | 29 ++++++++----------- 3 files changed, 24 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index 24065fe2b0be..86349e1bdd1c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -114,42 +114,33 @@ static int exynos_drm_connector_get_edid(struct drm_connector *connector) { struct exynos_drm_display *display = display_from_connector(connector); int ret; - void *edid; + struct edid *edid; if (!display->panel_ops->get_edid) return -EINVAL; - edid = kzalloc(MAX_EDID, GFP_KERNEL); - if (!edid) { - DRM_ERROR("failed to allocate edid\n"); - return -ENOMEM; - } - - ret = display->panel_ops->get_edid(display->panel_ctx, - connector, edid, MAX_EDID); - if (ret) { + edid = display->panel_ops->get_edid(display->panel_ctx, connector); + if (IS_ERR_OR_NULL(edid)) { + ret = PTR_ERR(edid); + edid = NULL; DRM_ERROR("Panel operation get_edid failed %d\n", ret); - goto err; + goto out; } ret = drm_mode_connector_update_edid_property(connector, edid); if (ret) { DRM_ERROR("update edid property failed(%d)\n", ret); - goto err; + goto out; } ret = drm_add_edid_modes(connector, edid); if (ret < 0) { DRM_ERROR("Add edid modes failed %d\n", ret); - goto err; + goto out; } - kfree(connector->display_info.raw_edid); - connector->display_info.raw_edid = edid; - - return ret; - -err: +out: + connector->display_info.raw_edid = NULL; kfree(edid); return ret; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_display.h b/drivers/gpu/drm/exynos/exynos_drm_display.h index 8cc52836f316..d4bf3b098a88 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_display.h +++ b/drivers/gpu/drm/exynos/exynos_drm_display.h @@ -19,7 +19,7 @@ * * @subdrv_probe: Used to associate drm_dev with panel context * @is_connected: Returns true if the panel is connected - * @get_edid: Fills in edid with mode data from the panel + * @get_edid: Returns an edid with mode data from the panel * @check_timing: Returns 0 if the given timing is valid for the panel * @power: Sets the panel's power to mode * @dpms: Same as power, but called in different places. Best to avoid it @@ -32,8 +32,7 @@ struct exynos_panel_ops { int (*subdrv_probe)(void *ctx, struct drm_device *drm_dev); bool (*is_connected)(void *ctx); - int (*get_edid)(void *ctx, struct drm_connector *connector, - u8 *edid, int len); + struct edid *(*get_edid)(void *ctx, struct drm_connector *connector); int (*check_timing)(void *ctx, void *timing); int (*power)(void *ctx, int mode); int (*dpms)(void *ctx, int mode); diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 900d7e1f7bee..8be11bee6524 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -888,34 +888,29 @@ static bool hdmi_is_connected(void *ctx) return true; } -static int hdmi_get_edid(void *ctx, struct drm_connector *connector, - u8 *edid, int len) +static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector) { - struct edid *raw_edid; struct hdmi_context *hdata = ctx; + struct edid *edid; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); if (!hdata->ddc_port) return -ENODEV; - raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); - if (raw_edid) { - /* TODO : Need to call this in exynos_drm_connector.c, do a drm_get_edid + edid = drm_get_edid(connector, hdata->ddc_port->adapter); + if (!edid) + return ERR_PTR(-ENODEV); + + /* + * TODO : Need to call this in exynos_drm_connector.c, do a drm_get_edid * to get the edid and then call drm_detect_hdmi_monitor. */ - hdata->has_hdmi_sink = drm_detect_hdmi_monitor(raw_edid); - hdata->has_hdmi_audio = drm_detect_monitor_audio(raw_edid); - memcpy(edid, raw_edid, min((1 + raw_edid->extensions) - * EDID_LENGTH, len)); - DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", - (hdata->has_hdmi_sink ? "hdmi monitor" : "dvi monitor"), - raw_edid->width_cm, raw_edid->height_cm); - } else { - return -ENODEV; - } + hdata->has_hdmi_sink = drm_detect_hdmi_monitor(edid); + hdata->has_hdmi_audio = drm_detect_monitor_audio(edid); + DRM_DEBUG_KMS("%s monitor\n", hdata->has_hdmi_sink ? "hdmi" : "dvi"); - return 0; + return edid; } static int hdmi_v13_check_timing(struct fb_videomode *check_timing) -- 2.20.1