提交 9c08e4ba 编写于 作者: R Rahul Sharma 提交者: Inki Dae

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.

v4:
- removed error check for drm_mode_connector_update_edid_property
which is expected to fail for Virtual Connectors like VIDI.
Thanks to Seung-Woo Kim.

v3:
- removed MAX_EDID as it is not used anymore.

v2:
- changed vidi_get_edid callback inside vidi driver.
Signed-off-by: NSean Paul <seanpaul@chromium.org>
Signed-off-by: NRahul Sharma <rahul.sharma@samsung.com>
Signed-off-by: NSeung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: NInki Dae <inki.dae@samsung.com>
上级 4af6924b
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_encoder.h" #include "exynos_drm_encoder.h"
#define MAX_EDID 256
#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\ #define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\
drm_connector) drm_connector)
...@@ -96,7 +95,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) ...@@ -96,7 +95,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
to_exynos_connector(connector); to_exynos_connector(connector);
struct exynos_drm_manager *manager = exynos_connector->manager; struct exynos_drm_manager *manager = exynos_connector->manager;
struct exynos_drm_display_ops *display_ops = manager->display_ops; struct exynos_drm_display_ops *display_ops = manager->display_ops;
unsigned int count; struct edid *edid = NULL;
unsigned int count = 0;
int ret;
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
...@@ -114,27 +115,21 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) ...@@ -114,27 +115,21 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
* because lcd panel has only one mode. * because lcd panel has only one mode.
*/ */
if (display_ops->get_edid) { if (display_ops->get_edid) {
int ret; edid = display_ops->get_edid(manager->dev, connector);
void *edid; if (IS_ERR_OR_NULL(edid)) {
ret = PTR_ERR(edid);
edid = kzalloc(MAX_EDID, GFP_KERNEL); edid = NULL;
if (!edid) { DRM_ERROR("Panel operation get_edid failed %d\n", ret);
DRM_ERROR("failed to allocate edid\n"); goto out;
return 0;
} }
ret = display_ops->get_edid(manager->dev, connector, count = drm_add_edid_modes(connector, edid);
edid, MAX_EDID); if (count < 0) {
if (ret < 0) { DRM_ERROR("Add edid modes failed %d\n", count);
DRM_ERROR("failed to get edid data.\n"); goto out;
kfree(edid);
edid = NULL;
return 0;
} }
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
count = drm_add_edid_modes(connector, edid);
kfree(edid);
} else { } else {
struct exynos_drm_panel_info *panel; struct exynos_drm_panel_info *panel;
struct drm_display_mode *mode = drm_mode_create(connector->dev); struct drm_display_mode *mode = drm_mode_create(connector->dev);
...@@ -161,6 +156,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) ...@@ -161,6 +156,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
count = 1; count = 1;
} }
out:
kfree(edid);
return count; return count;
} }
......
...@@ -148,8 +148,8 @@ struct exynos_drm_overlay { ...@@ -148,8 +148,8 @@ struct exynos_drm_overlay {
struct exynos_drm_display_ops { struct exynos_drm_display_ops {
enum exynos_drm_output_type type; enum exynos_drm_output_type type;
bool (*is_connected)(struct device *dev); bool (*is_connected)(struct device *dev);
int (*get_edid)(struct device *dev, struct drm_connector *connector, struct edid *(*get_edid)(struct device *dev,
u8 *edid, int len); struct drm_connector *connector);
void *(*get_panel)(struct device *dev); void *(*get_panel)(struct device *dev);
int (*check_timing)(struct device *dev, void *timing); int (*check_timing)(struct device *dev, void *timing);
int (*power_on)(struct device *dev, int mode); int (*power_on)(struct device *dev, int mode);
......
...@@ -108,18 +108,17 @@ static bool drm_hdmi_is_connected(struct device *dev) ...@@ -108,18 +108,17 @@ static bool drm_hdmi_is_connected(struct device *dev)
return false; return false;
} }
static int drm_hdmi_get_edid(struct device *dev, struct edid *drm_hdmi_get_edid(struct device *dev,
struct drm_connector *connector, u8 *edid, int len) struct drm_connector *connector)
{ {
struct drm_hdmi_context *ctx = to_context(dev); struct drm_hdmi_context *ctx = to_context(dev);
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
if (hdmi_ops && hdmi_ops->get_edid) if (hdmi_ops && hdmi_ops->get_edid)
return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid, return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
len);
return 0; return NULL;
} }
static int drm_hdmi_check_timing(struct device *dev, void *timing) static int drm_hdmi_check_timing(struct device *dev, void *timing)
......
...@@ -30,8 +30,8 @@ struct exynos_drm_hdmi_context { ...@@ -30,8 +30,8 @@ struct exynos_drm_hdmi_context {
struct exynos_hdmi_ops { struct exynos_hdmi_ops {
/* display */ /* display */
bool (*is_connected)(void *ctx); bool (*is_connected)(void *ctx);
int (*get_edid)(void *ctx, struct drm_connector *connector, struct edid *(*get_edid)(void *ctx,
u8 *edid, int len); struct drm_connector *connector);
int (*check_timing)(void *ctx, void *timing); int (*check_timing)(void *ctx, void *timing);
int (*power_on)(void *ctx, int mode); int (*power_on)(void *ctx, int mode);
......
...@@ -98,10 +98,12 @@ static bool vidi_display_is_connected(struct device *dev) ...@@ -98,10 +98,12 @@ static bool vidi_display_is_connected(struct device *dev)
return ctx->connected ? true : false; return ctx->connected ? true : false;
} }
static int vidi_get_edid(struct device *dev, struct drm_connector *connector, static struct edid *vidi_get_edid(struct device *dev,
u8 *edid, int len) struct drm_connector *connector)
{ {
struct vidi_context *ctx = get_vidi_context(dev); struct vidi_context *ctx = get_vidi_context(dev);
struct edid *edid;
int edid_len;
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
...@@ -111,13 +113,18 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector, ...@@ -111,13 +113,18 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector,
*/ */
if (!ctx->raw_edid) { if (!ctx->raw_edid) {
DRM_DEBUG_KMS("raw_edid is null.\n"); DRM_DEBUG_KMS("raw_edid is null.\n");
return -EFAULT; return ERR_PTR(-EFAULT);
} }
memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions) edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
* EDID_LENGTH, len)); edid = kzalloc(edid_len, GFP_KERNEL);
if (!edid) {
DRM_DEBUG_KMS("failed to allocate edid\n");
return ERR_PTR(-ENOMEM);
}
return 0; memcpy(edid, ctx->raw_edid, edid_len);
return edid;
} }
static void *vidi_get_panel(struct device *dev) static void *vidi_get_panel(struct device *dev)
......
...@@ -1391,8 +1391,7 @@ static bool hdmi_is_connected(void *ctx) ...@@ -1391,8 +1391,7 @@ static bool hdmi_is_connected(void *ctx)
return hdata->hpd; return hdata->hpd;
} }
static int hdmi_get_edid(void *ctx, struct drm_connector *connector, static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
u8 *edid, int len)
{ {
struct edid *raw_edid; struct edid *raw_edid;
struct hdmi_context *hdata = ctx; struct hdmi_context *hdata = ctx;
...@@ -1400,22 +1399,18 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector, ...@@ -1400,22 +1399,18 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
if (!hdata->ddc_port) if (!hdata->ddc_port)
return -ENODEV; return ERR_PTR(-ENODEV);
raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
if (raw_edid) { if (!raw_edid)
hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); return ERR_PTR(-ENODEV);
memcpy(edid, raw_edid, min((1 + raw_edid->extensions)
* EDID_LENGTH, len));
DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
raw_edid->width_cm, raw_edid->height_cm);
kfree(raw_edid);
} else {
return -ENODEV;
}
return 0; hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
raw_edid->width_cm, raw_edid->height_cm);
return raw_edid;
} }
static int hdmi_v13_check_timing(struct fb_videomode *check_timing) static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册