Commit d9716ee3 authored by Sean Paul's avatar Sean Paul Committed by Inki Dae

drm/exynos: Implement drm_connector in hdmi directly

This patch implements drm_connector in the hdmi driver directly, instead
of using exynos_drm_connector.
Signed-off-by: default avatarSean Paul <seanpaul@chromium.org>
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
parent c37f42cd
...@@ -45,9 +45,8 @@ ...@@ -45,9 +45,8 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <media/s5p_hdmi.h> #include <media/s5p_hdmi.h>
#define MAX_WIDTH 1920
#define MAX_HEIGHT 1080
#define get_hdmi_display(dev) platform_get_drvdata(to_platform_device(dev)) #define get_hdmi_display(dev) platform_get_drvdata(to_platform_device(dev))
#define ctx_from_connector(c) container_of(c, struct hdmi_context, connector)
/* AVI header and aspect ratio */ /* AVI header and aspect ratio */
#define HDMI_AVI_VERSION 0x02 #define HDMI_AVI_VERSION 0x02
...@@ -172,6 +171,8 @@ struct hdmi_conf_regs { ...@@ -172,6 +171,8 @@ struct hdmi_conf_regs {
struct hdmi_context { struct hdmi_context {
struct device *dev; struct device *dev;
struct drm_device *drm_dev; struct drm_device *drm_dev;
struct drm_connector connector;
struct drm_encoder *encoder;
bool hpd; bool hpd;
bool powered; bool powered;
bool dvi_mode; bool dvi_mode;
...@@ -790,42 +791,46 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata, ...@@ -790,42 +791,46 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
} }
} }
static int hdmi_initialize(struct exynos_drm_display *display, static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
struct drm_device *drm_dev) bool force)
{ {
struct hdmi_context *hdata = display->ctx; struct hdmi_context *hdata = ctx_from_connector(connector);
hdata->drm_dev = drm_dev; return hdata->hpd ? connector_status_connected :
connector_status_disconnected;
return 0;
} }
static bool hdmi_is_connected(struct exynos_drm_display *display) static void hdmi_connector_destroy(struct drm_connector *connector)
{ {
struct hdmi_context *hdata = display->ctx;
return hdata->hpd;
} }
static struct edid *hdmi_get_edid(struct exynos_drm_display *display, static struct drm_connector_funcs hdmi_connector_funcs = {
struct drm_connector *connector) .dpms = drm_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
.detect = hdmi_detect,
.destroy = hdmi_connector_destroy,
};
static int hdmi_get_modes(struct drm_connector *connector)
{ {
struct edid *raw_edid; struct hdmi_context *hdata = ctx_from_connector(connector);
struct hdmi_context *hdata = display->ctx; struct edid *edid;
if (!hdata->ddc_port) if (!hdata->ddc_port)
return ERR_PTR(-ENODEV); return -ENODEV;
raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); edid = drm_get_edid(connector, hdata->ddc_port->adapter);
if (!raw_edid) if (!edid)
return ERR_PTR(-ENODEV); return -ENODEV;
hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
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); edid->width_cm, edid->height_cm);
drm_mode_connector_update_edid_property(connector, edid);
return raw_edid; return drm_add_edid_modes(connector, edid);
} }
static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
...@@ -850,10 +855,10 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) ...@@ -850,10 +855,10 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
return -EINVAL; return -EINVAL;
} }
static int hdmi_check_mode(struct exynos_drm_display *display, static int hdmi_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct hdmi_context *hdata = display->ctx; struct hdmi_context *hdata = ctx_from_connector(connector);
int ret; int ret;
DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n", DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
...@@ -863,11 +868,60 @@ static int hdmi_check_mode(struct exynos_drm_display *display, ...@@ -863,11 +868,60 @@ static int hdmi_check_mode(struct exynos_drm_display *display,
ret = mixer_check_mode(mode); ret = mixer_check_mode(mode);
if (ret) if (ret)
return ret; return MODE_BAD;
ret = hdmi_find_phy_conf(hdata, mode->clock * 1000); ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
if (ret < 0) if (ret < 0)
return MODE_BAD;
return MODE_OK;
}
static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
{
struct hdmi_context *hdata = ctx_from_connector(connector);
return hdata->encoder;
}
static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
.get_modes = hdmi_get_modes,
.mode_valid = hdmi_mode_valid,
.best_encoder = hdmi_best_encoder,
};
static int hdmi_create_connector(struct exynos_drm_display *display,
struct drm_encoder *encoder)
{
struct hdmi_context *hdata = display->ctx;
struct drm_connector *connector = &hdata->connector;
int ret;
hdata->encoder = encoder;
connector->interlace_allowed = true;
connector->polled = DRM_CONNECTOR_POLL_HPD;
ret = drm_connector_init(hdata->drm_dev, connector,
&hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
if (ret) {
DRM_ERROR("Failed to initialize connector with drm\n");
return ret; return ret;
}
drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
drm_sysfs_connector_add(connector);
drm_mode_connector_attach_encoder(connector, encoder);
return 0;
}
static int hdmi_initialize(struct exynos_drm_display *display,
struct drm_device *drm_dev)
{
struct hdmi_context *hdata = display->ctx;
hdata->drm_dev = drm_dev;
return 0; return 0;
} }
...@@ -883,10 +937,10 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display, ...@@ -883,10 +937,10 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display,
drm_mode_set_crtcinfo(adjusted_mode, 0); drm_mode_set_crtcinfo(adjusted_mode, 0);
mode_ok = hdmi_check_mode(display, adjusted_mode); mode_ok = hdmi_mode_valid(connector, adjusted_mode);
/* just return if user desired mode exists. */ /* just return if user desired mode exists. */
if (mode_ok == 0) if (mode_ok == MODE_OK)
return; return;
/* /*
...@@ -894,9 +948,9 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display, ...@@ -894,9 +948,9 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display,
* to adjusted_mode. * to adjusted_mode.
*/ */
list_for_each_entry(m, &connector->modes, head) { list_for_each_entry(m, &connector->modes, head) {
mode_ok = hdmi_check_mode(display, m); mode_ok = hdmi_mode_valid(connector, m);
if (mode_ok == 0) { if (mode_ok == MODE_OK) {
DRM_INFO("desired mode doesn't exist so\n"); DRM_INFO("desired mode doesn't exist so\n");
DRM_INFO("use the most suitable mode among modes.\n"); DRM_INFO("use the most suitable mode among modes.\n");
...@@ -1753,13 +1807,6 @@ static void hdmi_mode_set(struct exynos_drm_display *display, ...@@ -1753,13 +1807,6 @@ static void hdmi_mode_set(struct exynos_drm_display *display,
hdmi_v14_mode_set(hdata, mode); hdmi_v14_mode_set(hdata, mode);
} }
static void hdmi_get_max_resol(struct exynos_drm_display *display,
unsigned int *width, unsigned int *height)
{
*width = MAX_WIDTH;
*height = MAX_HEIGHT;
}
static void hdmi_commit(struct exynos_drm_display *display) static void hdmi_commit(struct exynos_drm_display *display)
{ {
struct hdmi_context *hdata = display->ctx; struct hdmi_context *hdata = display->ctx;
...@@ -1854,10 +1901,7 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode) ...@@ -1854,10 +1901,7 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode)
static struct exynos_drm_display_ops hdmi_display_ops = { static struct exynos_drm_display_ops hdmi_display_ops = {
.initialize = hdmi_initialize, .initialize = hdmi_initialize,
.is_connected = hdmi_is_connected, .create_connector = hdmi_create_connector,
.get_max_resol = hdmi_get_max_resol,
.get_edid = hdmi_get_edid,
.check_mode = hdmi_check_mode,
.mode_fixup = hdmi_mode_fixup, .mode_fixup = hdmi_mode_fixup,
.mode_set = hdmi_mode_set, .mode_set = hdmi_mode_set,
.dpms = hdmi_dpms, .dpms = hdmi_dpms,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment