Skip to content

Commit d9716ee

Browse files
atseanpauldaeinki
authored andcommitted
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 <[email protected]> Signed-off-by: Inki Dae <[email protected]>
1 parent c37f42c commit d9716ee

File tree

1 file changed

+85
-41
lines changed

1 file changed

+85
-41
lines changed

drivers/gpu/drm/exynos/exynos_hdmi.c

Lines changed: 85 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,8 @@
4545
#include <linux/gpio.h>
4646
#include <media/s5p_hdmi.h>
4747

48-
#define MAX_WIDTH 1920
49-
#define MAX_HEIGHT 1080
5048
#define get_hdmi_display(dev) platform_get_drvdata(to_platform_device(dev))
49+
#define ctx_from_connector(c) container_of(c, struct hdmi_context, connector)
5150

5251
/* AVI header and aspect ratio */
5352
#define HDMI_AVI_VERSION 0x02
@@ -172,6 +171,8 @@ struct hdmi_conf_regs {
172171
struct hdmi_context {
173172
struct device *dev;
174173
struct drm_device *drm_dev;
174+
struct drm_connector connector;
175+
struct drm_encoder *encoder;
175176
bool hpd;
176177
bool powered;
177178
bool dvi_mode;
@@ -790,42 +791,46 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
790791
}
791792
}
792793

793-
static int hdmi_initialize(struct exynos_drm_display *display,
794-
struct drm_device *drm_dev)
794+
static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
795+
bool force)
795796
{
796-
struct hdmi_context *hdata = display->ctx;
797+
struct hdmi_context *hdata = ctx_from_connector(connector);
797798

798-
hdata->drm_dev = drm_dev;
799-
800-
return 0;
799+
return hdata->hpd ? connector_status_connected :
800+
connector_status_disconnected;
801801
}
802802

803-
static bool hdmi_is_connected(struct exynos_drm_display *display)
803+
static void hdmi_connector_destroy(struct drm_connector *connector)
804804
{
805-
struct hdmi_context *hdata = display->ctx;
806-
807-
return hdata->hpd;
808805
}
809806

810-
static struct edid *hdmi_get_edid(struct exynos_drm_display *display,
811-
struct drm_connector *connector)
807+
static struct drm_connector_funcs hdmi_connector_funcs = {
808+
.dpms = drm_helper_connector_dpms,
809+
.fill_modes = drm_helper_probe_single_connector_modes,
810+
.detect = hdmi_detect,
811+
.destroy = hdmi_connector_destroy,
812+
};
813+
814+
static int hdmi_get_modes(struct drm_connector *connector)
812815
{
813-
struct edid *raw_edid;
814-
struct hdmi_context *hdata = display->ctx;
816+
struct hdmi_context *hdata = ctx_from_connector(connector);
817+
struct edid *edid;
815818

816819
if (!hdata->ddc_port)
817-
return ERR_PTR(-ENODEV);
820+
return -ENODEV;
818821

819-
raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
820-
if (!raw_edid)
821-
return ERR_PTR(-ENODEV);
822+
edid = drm_get_edid(connector, hdata->ddc_port->adapter);
823+
if (!edid)
824+
return -ENODEV;
822825

823-
hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
826+
hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
824827
DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
825828
(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
826-
raw_edid->width_cm, raw_edid->height_cm);
829+
edid->width_cm, edid->height_cm);
830+
831+
drm_mode_connector_update_edid_property(connector, edid);
827832

828-
return raw_edid;
833+
return drm_add_edid_modes(connector, edid);
829834
}
830835

831836
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)
850855
return -EINVAL;
851856
}
852857

853-
static int hdmi_check_mode(struct exynos_drm_display *display,
858+
static int hdmi_mode_valid(struct drm_connector *connector,
854859
struct drm_display_mode *mode)
855860
{
856-
struct hdmi_context *hdata = display->ctx;
861+
struct hdmi_context *hdata = ctx_from_connector(connector);
857862
int ret;
858863

859864
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,
863868

864869
ret = mixer_check_mode(mode);
865870
if (ret)
866-
return ret;
871+
return MODE_BAD;
867872

868873
ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
869874
if (ret < 0)
875+
return MODE_BAD;
876+
877+
return MODE_OK;
878+
}
879+
880+
static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
881+
{
882+
struct hdmi_context *hdata = ctx_from_connector(connector);
883+
884+
return hdata->encoder;
885+
}
886+
887+
static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
888+
.get_modes = hdmi_get_modes,
889+
.mode_valid = hdmi_mode_valid,
890+
.best_encoder = hdmi_best_encoder,
891+
};
892+
893+
static int hdmi_create_connector(struct exynos_drm_display *display,
894+
struct drm_encoder *encoder)
895+
{
896+
struct hdmi_context *hdata = display->ctx;
897+
struct drm_connector *connector = &hdata->connector;
898+
int ret;
899+
900+
hdata->encoder = encoder;
901+
connector->interlace_allowed = true;
902+
connector->polled = DRM_CONNECTOR_POLL_HPD;
903+
904+
ret = drm_connector_init(hdata->drm_dev, connector,
905+
&hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
906+
if (ret) {
907+
DRM_ERROR("Failed to initialize connector with drm\n");
870908
return ret;
909+
}
910+
911+
drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
912+
drm_sysfs_connector_add(connector);
913+
drm_mode_connector_attach_encoder(connector, encoder);
914+
915+
return 0;
916+
}
917+
918+
static int hdmi_initialize(struct exynos_drm_display *display,
919+
struct drm_device *drm_dev)
920+
{
921+
struct hdmi_context *hdata = display->ctx;
922+
923+
hdata->drm_dev = drm_dev;
924+
871925
return 0;
872926
}
873927

@@ -883,20 +937,20 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display,
883937

884938
drm_mode_set_crtcinfo(adjusted_mode, 0);
885939

886-
mode_ok = hdmi_check_mode(display, adjusted_mode);
940+
mode_ok = hdmi_mode_valid(connector, adjusted_mode);
887941

888942
/* just return if user desired mode exists. */
889-
if (mode_ok == 0)
943+
if (mode_ok == MODE_OK)
890944
return;
891945

892946
/*
893947
* otherwise, find the most suitable mode among modes and change it
894948
* to adjusted_mode.
895949
*/
896950
list_for_each_entry(m, &connector->modes, head) {
897-
mode_ok = hdmi_check_mode(display, m);
951+
mode_ok = hdmi_mode_valid(connector, m);
898952

899-
if (mode_ok == 0) {
953+
if (mode_ok == MODE_OK) {
900954
DRM_INFO("desired mode doesn't exist so\n");
901955
DRM_INFO("use the most suitable mode among modes.\n");
902956

@@ -1753,13 +1807,6 @@ static void hdmi_mode_set(struct exynos_drm_display *display,
17531807
hdmi_v14_mode_set(hdata, mode);
17541808
}
17551809

1756-
static void hdmi_get_max_resol(struct exynos_drm_display *display,
1757-
unsigned int *width, unsigned int *height)
1758-
{
1759-
*width = MAX_WIDTH;
1760-
*height = MAX_HEIGHT;
1761-
}
1762-
17631810
static void hdmi_commit(struct exynos_drm_display *display)
17641811
{
17651812
struct hdmi_context *hdata = display->ctx;
@@ -1854,10 +1901,7 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode)
18541901

18551902
static struct exynos_drm_display_ops hdmi_display_ops = {
18561903
.initialize = hdmi_initialize,
1857-
.is_connected = hdmi_is_connected,
1858-
.get_max_resol = hdmi_get_max_resol,
1859-
.get_edid = hdmi_get_edid,
1860-
.check_mode = hdmi_check_mode,
1904+
.create_connector = hdmi_create_connector,
18611905
.mode_fixup = hdmi_mode_fixup,
18621906
.mode_set = hdmi_mode_set,
18631907
.dpms = hdmi_dpms,

0 commit comments

Comments
 (0)