summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/exynos/Kconfig1
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c47
2 files changed, 48 insertions, 0 deletions
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 26ee29254696..89d9371d1923 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -65,6 +65,7 @@ config DRM_EXYNOS_DP
config DRM_EXYNOS_HDMI
bool "Exynos DRM HDMI"
depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV
+ select EXTCON
help
Choose this option if you want to use Exynos HDMI for DRM.
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 591ce56d9c64..06f8d9efbfaf 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -40,6 +40,7 @@
#include <linux/component.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
+#include <linux/extcon.h>
#include <drm/exynos_drm.h>
@@ -124,6 +125,7 @@ struct hdmi_context {
struct delayed_work hotplug_work;
struct drm_display_mode current_mode;
const struct hdmi_driver_data *drv_data;
+ struct extcon_dev *edev;
void __iomem *regs;
void __iomem *regs_hdmiphy;
@@ -140,6 +142,11 @@ struct hdmi_context {
struct exynos_drm_clk phy_clk;
};
+static const char *extcon_cable_list[] = {
+ "HDMI",
+ NULL,
+};
+
static inline struct hdmi_context *display_to_hdmi(struct exynos_drm_display *d)
{
return container_of(d, struct hdmi_context, display);
@@ -1686,12 +1693,29 @@ static struct exynos_drm_display_ops hdmi_display_ops = {
.commit = hdmi_commit,
};
+static void hdmi_extcon_notify(struct hdmi_context *hdata)
+{
+ enum drm_connector_status plug;
+
+ if (!hdata->edev)
+ return;
+
+ plug = hdmi_detect(&hdata->connector, false);
+
+ if (plug == connector_status_connected)
+ extcon_set_cable_state(hdata->edev, "HDMI", 1);
+ else if (plug == connector_status_disconnected)
+ extcon_set_cable_state(hdata->edev, "HDMI", 0);
+}
+
static void hdmi_hotplug_work_func(struct work_struct *work)
{
struct hdmi_context *hdata;
hdata = container_of(work, struct hdmi_context, hotplug_work.work);
+ hdmi_extcon_notify(hdata);
+
if (hdata->drm_dev)
drm_helper_hpd_irq_event(hdata->drm_dev);
}
@@ -1960,6 +1984,25 @@ out:
return ret;
}
+static int hdmi_extcon_init(struct hdmi_context *hdata)
+{
+ struct device *dev = hdata->dev;
+ struct extcon_dev *edev;
+ int ret;
+
+ edev = devm_extcon_dev_allocate(dev, extcon_cable_list);
+ if (IS_ERR(edev))
+ return PTR_ERR(edev);
+
+ ret = devm_extcon_dev_register(dev, edev);
+ if (ret)
+ return ret;
+
+ hdata->edev = edev;
+
+ return 0;
+}
+
static int hdmi_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
@@ -2001,6 +2044,10 @@ static int hdmi_probe(struct platform_device *pdev)
return ret;
}
+ ret = hdmi_extcon_init(hdata);
+ if (ret)
+ DRM_INFO("extcon notify won't be supported due to init. fail");
+
ret = hdmi_get_ddc_adapter(hdata);
if (ret)
return ret;