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: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
This commit is contained in:
Sean Paul 2014-01-30 16:19:29 -05:00 committed by Inki Dae
parent c37f42cd18
commit d9716ee33a
1 changed files with 85 additions and 41 deletions

View File

@ -45,9 +45,8 @@
#include <linux/gpio.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 ctx_from_connector(c) container_of(c, struct hdmi_context, connector)
/* AVI header and aspect ratio */
#define HDMI_AVI_VERSION 0x02
@ -172,6 +171,8 @@ struct hdmi_conf_regs {
struct hdmi_context {
struct device *dev;
struct drm_device *drm_dev;
struct drm_connector connector;
struct drm_encoder *encoder;
bool hpd;
bool powered;
bool dvi_mode;
@ -790,42 +791,46 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
}
}
static int hdmi_initialize(struct exynos_drm_display *display,
struct drm_device *drm_dev)
static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
bool force)
{
struct hdmi_context *hdata = display->ctx;
struct hdmi_context *hdata = ctx_from_connector(connector);
hdata->drm_dev = drm_dev;
return 0;
return hdata->hpd ? connector_status_connected :
connector_status_disconnected;
}
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,
struct drm_connector *connector)
static struct drm_connector_funcs hdmi_connector_funcs = {
.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 = display->ctx;
struct hdmi_context *hdata = ctx_from_connector(connector);
struct edid *edid;
if (!hdata->ddc_port)
return ERR_PTR(-ENODEV);
return -ENODEV;
raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
if (!raw_edid)
return ERR_PTR(-ENODEV);
edid = drm_get_edid(connector, hdata->ddc_port->adapter);
if (!edid)
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",
(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
raw_edid->width_cm, raw_edid->height_cm);
edid->width_cm, edid->height_cm);
return raw_edid;
drm_mode_connector_update_edid_property(connector, edid);
return drm_add_edid_modes(connector, edid);
}
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;
}
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 hdmi_context *hdata = display->ctx;
struct hdmi_context *hdata = ctx_from_connector(connector);
int ret;
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,
ret = mixer_check_mode(mode);
if (ret)
return ret;
return MODE_BAD;
ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
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;
}
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;
}
@ -883,10 +937,10 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display,
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. */
if (mode_ok == 0)
if (mode_ok == MODE_OK)
return;
/*
@ -894,9 +948,9 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display,
* to adjusted_mode.
*/
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("use the most suitable mode among modes.\n");
@ -1753,13 +1807,6 @@ static void hdmi_mode_set(struct exynos_drm_display *display,
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)
{
struct hdmi_context *hdata = display->ctx;
@ -1854,10 +1901,7 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode)
static struct exynos_drm_display_ops hdmi_display_ops = {
.initialize = hdmi_initialize,
.is_connected = hdmi_is_connected,
.get_max_resol = hdmi_get_max_resol,
.get_edid = hdmi_get_edid,
.check_mode = hdmi_check_mode,
.create_connector = hdmi_create_connector,
.mode_fixup = hdmi_mode_fixup,
.mode_set = hdmi_mode_set,
.dpms = hdmi_dpms,