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: Sean Paul <seanpaul@chromium.org> Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com> Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
This commit is contained in:
parent
4af6924b8a
commit
9c08e4ba81
|
@ -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)
|
||||||
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)
|
||||||
* 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)
|
||||||
count = 1;
|
count = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
kfree(edid);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
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 {
|
||||||
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)
|
||||||
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,
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
|
hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
|
||||||
memcpy(edid, raw_edid, min((1 + raw_edid->extensions)
|
|
||||||
* EDID_LENGTH, len));
|
|
||||||
DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
|
DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
|
||||||
(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
|
(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
|
||||||
raw_edid->width_cm, raw_edid->height_cm);
|
raw_edid->width_cm, raw_edid->height_cm);
|
||||||
kfree(raw_edid);
|
|
||||||
} else {
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
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)
|
||||||
|
|
Loading…
Reference in New Issue