aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c126
1 files changed, 85 insertions, 41 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 1a06a54a901f..0097032cd350 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -45,9 +45,8 @@
45#include <linux/gpio.h> 45#include <linux/gpio.h>
46#include <media/s5p_hdmi.h> 46#include <media/s5p_hdmi.h>
47 47
48#define MAX_WIDTH 1920
49#define MAX_HEIGHT 1080
50#define get_hdmi_display(dev) platform_get_drvdata(to_platform_device(dev)) 48#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)
51 50
52/* AVI header and aspect ratio */ 51/* AVI header and aspect ratio */
53#define HDMI_AVI_VERSION 0x02 52#define HDMI_AVI_VERSION 0x02
@@ -172,6 +171,8 @@ struct hdmi_conf_regs {
172struct hdmi_context { 171struct hdmi_context {
173 struct device *dev; 172 struct device *dev;
174 struct drm_device *drm_dev; 173 struct drm_device *drm_dev;
174 struct drm_connector connector;
175 struct drm_encoder *encoder;
175 bool hpd; 176 bool hpd;
176 bool powered; 177 bool powered;
177 bool dvi_mode; 178 bool dvi_mode;
@@ -790,42 +791,46 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
790 } 791 }
791} 792}
792 793
793static int hdmi_initialize(struct exynos_drm_display *display, 794static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
794 struct drm_device *drm_dev) 795 bool force)
795{ 796{
796 struct hdmi_context *hdata = display->ctx; 797 struct hdmi_context *hdata = ctx_from_connector(connector);
797 798
798 hdata->drm_dev = drm_dev; 799 return hdata->hpd ? connector_status_connected :
799 800 connector_status_disconnected;
800 return 0;
801} 801}
802 802
803static bool hdmi_is_connected(struct exynos_drm_display *display) 803static void hdmi_connector_destroy(struct drm_connector *connector)
804{ 804{
805 struct hdmi_context *hdata = display->ctx;
806
807 return hdata->hpd;
808} 805}
809 806
810static struct edid *hdmi_get_edid(struct exynos_drm_display *display, 807static struct drm_connector_funcs hdmi_connector_funcs = {
811 struct drm_connector *connector) 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
814static int hdmi_get_modes(struct drm_connector *connector)
812{ 815{
813 struct edid *raw_edid; 816 struct hdmi_context *hdata = ctx_from_connector(connector);
814 struct hdmi_context *hdata = display->ctx; 817 struct edid *edid;
815 818
816 if (!hdata->ddc_port) 819 if (!hdata->ddc_port)
817 return ERR_PTR(-ENODEV); 820 return -ENODEV;
818 821
819 raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); 822 edid = drm_get_edid(connector, hdata->ddc_port->adapter);
820 if (!raw_edid) 823 if (!edid)
821 return ERR_PTR(-ENODEV); 824 return -ENODEV;
822 825
823 hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); 826 hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
824 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", 827 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
825 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), 828 (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);
827 832
828 return raw_edid; 833 return drm_add_edid_modes(connector, edid);
829} 834}
830 835
831static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) 836static 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 return -EINVAL; 855 return -EINVAL;
851} 856}
852 857
853static int hdmi_check_mode(struct exynos_drm_display *display, 858static int hdmi_mode_valid(struct drm_connector *connector,
854 struct drm_display_mode *mode) 859 struct drm_display_mode *mode)
855{ 860{
856 struct hdmi_context *hdata = display->ctx; 861 struct hdmi_context *hdata = ctx_from_connector(connector);
857 int ret; 862 int ret;
858 863
859 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n", 864 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 868
864 ret = mixer_check_mode(mode); 869 ret = mixer_check_mode(mode);
865 if (ret) 870 if (ret)
866 return ret; 871 return MODE_BAD;
867 872
868 ret = hdmi_find_phy_conf(hdata, mode->clock * 1000); 873 ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
869 if (ret < 0) 874 if (ret < 0)
875 return MODE_BAD;
876
877 return MODE_OK;
878}
879
880static 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
887static 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
893static 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");
870 return ret; 908 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
918static 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
871 return 0; 925 return 0;
872} 926}
873 927
@@ -883,10 +937,10 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display,
883 937
884 drm_mode_set_crtcinfo(adjusted_mode, 0); 938 drm_mode_set_crtcinfo(adjusted_mode, 0);
885 939
886 mode_ok = hdmi_check_mode(display, adjusted_mode); 940 mode_ok = hdmi_mode_valid(connector, adjusted_mode);
887 941
888 /* just return if user desired mode exists. */ 942 /* just return if user desired mode exists. */
889 if (mode_ok == 0) 943 if (mode_ok == MODE_OK)
890 return; 944 return;
891 945
892 /* 946 /*
@@ -894,9 +948,9 @@ static void hdmi_mode_fixup(struct exynos_drm_display *display,
894 * to adjusted_mode. 948 * to adjusted_mode.
895 */ 949 */
896 list_for_each_entry(m, &connector->modes, head) { 950 list_for_each_entry(m, &connector->modes, head) {
897 mode_ok = hdmi_check_mode(display, m); 951 mode_ok = hdmi_mode_valid(connector, m);
898 952
899 if (mode_ok == 0) { 953 if (mode_ok == MODE_OK) {
900 DRM_INFO("desired mode doesn't exist so\n"); 954 DRM_INFO("desired mode doesn't exist so\n");
901 DRM_INFO("use the most suitable mode among modes.\n"); 955 DRM_INFO("use the most suitable mode among modes.\n");
902 956
@@ -1753,13 +1807,6 @@ static void hdmi_mode_set(struct exynos_drm_display *display,
1753 hdmi_v14_mode_set(hdata, mode); 1807 hdmi_v14_mode_set(hdata, mode);
1754} 1808}
1755 1809
1756static 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
1763static void hdmi_commit(struct exynos_drm_display *display) 1810static void hdmi_commit(struct exynos_drm_display *display)
1764{ 1811{
1765 struct hdmi_context *hdata = display->ctx; 1812 struct hdmi_context *hdata = display->ctx;
@@ -1854,10 +1901,7 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode)
1854 1901
1855static struct exynos_drm_display_ops hdmi_display_ops = { 1902static struct exynos_drm_display_ops hdmi_display_ops = {
1856 .initialize = hdmi_initialize, 1903 .initialize = hdmi_initialize,
1857 .is_connected = hdmi_is_connected, 1904 .create_connector = hdmi_create_connector,
1858 .get_max_resol = hdmi_get_max_resol,
1859 .get_edid = hdmi_get_edid,
1860 .check_mode = hdmi_check_mode,
1861 .mode_fixup = hdmi_mode_fixup, 1905 .mode_fixup = hdmi_mode_fixup,
1862 .mode_set = hdmi_mode_set, 1906 .mode_set = hdmi_mode_set,
1863 .dpms = hdmi_dpms, 1907 .dpms = hdmi_dpms,