diff options
-rw-r--r-- | drivers/gpu/drm/exynos/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_hdmi.c | 47 |
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; |