summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Agner <stefan.agner@toradex.com>2018-02-16 16:07:24 +0100
committerStefan Agner <stefan.agner@toradex.com>2018-02-16 16:07:24 +0100
commitd8868d38dc929cc5c4591f583489cdc57e93e9f2 (patch)
treed00a6299e6cf27451204630be07317cdce909e07
parent9fe8e87ad955c087d2fa6a35fda3287aa5dccbd7 (diff)
drm/imx/hdp: add HDMI CTRL GPIO support
Add support to control HDMI levels using a GPIO. The driver simply sets the GPIO high for HDMI and low for DisplayPort. Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
-rw-r--r--drivers/gpu/drm/imx/hdp/imx-hdp.c29
-rw-r--r--drivers/gpu/drm/imx/hdp/imx-hdp.h2
2 files changed, 28 insertions, 3 deletions
diff --git a/drivers/gpu/drm/imx/hdp/imx-hdp.c b/drivers/gpu/drm/imx/hdp/imx-hdp.c
index 0a998e5487cf..098cc6de87e1 100644
--- a/drivers/gpu/drm/imx/hdp/imx-hdp.c
+++ b/drivers/gpu/drm/imx/hdp/imx-hdp.c
@@ -20,6 +20,7 @@
#include <linux/of.h>
#include <linux/irq.h>
#include <linux/of_device.h>
+#include <linux/of_gpio.h>
#include "imx-hdp.h"
#include "imx-hdmi.h"
@@ -934,6 +935,7 @@ static struct hdp_ops imx8qm_hdmi_ops = {
static struct hdp_devtype imx8qm_dp_devtype = {
.is_edid = false,
.is_4kp60 = false,
+ .is_hdmi_level = false,
.audio_type = CDN_DPTX,
.ops = &imx8qm_dp_ops,
.rw = &imx8qm_rw,
@@ -942,6 +944,7 @@ static struct hdp_devtype imx8qm_dp_devtype = {
static struct hdp_devtype imx8qm_hdmi_devtype = {
.is_edid = false,
.is_4kp60 = false,
+ .is_hdmi_level = true,
.audio_type = CDN_HDMITX_TYPHOON,
.ops = &imx8qm_hdmi_ops,
.rw = &imx8qm_rw,
@@ -964,6 +967,7 @@ static struct hdp_ops imx8mq_ops = {
static struct hdp_devtype imx8mq_hdmi_devtype = {
.is_edid = false,
.is_4kp60 = true,
+ .is_hdmi_level = true,
.audio_type = CDN_HDMITX_KIRAN,
.ops = &imx8mq_ops,
.rw = &imx8mq_rw,
@@ -1159,6 +1163,18 @@ static int imx_hdp_imx_bind(struct device *dev, struct device *master,
INIT_DELAYED_WORK(&hdp->hotplug_work, hotplug_work_func);
+ hdp->hdmi_ctrl_gpio = of_get_named_gpio(dev->of_node, "hdmi-ctrl-gpios", 0);
+ if (gpio_is_valid(hdp->hdmi_ctrl_gpio)) {
+ ret = gpio_request(hdp->hdmi_ctrl_gpio, "HDMI_CTRL");
+ if (ret < 0) {
+ dev_err(dev, "request HDMI CTRL GPIO failed: %d\n", ret);
+ goto err_cleanup_encoder;
+ }
+
+ /* Set signals depending on HDP device type */
+ gpio_direction_output(hdp->hdmi_ctrl_gpio, devtype->is_hdmi_level);
+ }
+
/* Check cable states before enable irq */
imx_hdp_call(hdp, get_hpd_state, &hdp->state, &hpd);
@@ -1171,7 +1187,7 @@ static int imx_hdp_imx_bind(struct device *dev, struct device *master,
if (ret) {
dev_err(&pdev->dev, "can't claim irq %d\n",
hdp->irq[HPD_IRQ_IN]);
- goto err_irq;
+ goto err_free_hdmi_gpio;
}
/* Cable Disconnedted, enable Plug in IRQ */
if (hpd == 0)
@@ -1185,7 +1201,7 @@ static int imx_hdp_imx_bind(struct device *dev, struct device *master,
if (ret) {
dev_err(&pdev->dev, "can't claim irq %d\n",
hdp->irq[HPD_IRQ_OUT]);
- goto err_irq;
+ goto err_free_hdmi_gpio;
}
/* Cable Connected, enable Plug out IRQ */
if (hpd == 1)
@@ -1193,7 +1209,11 @@ static int imx_hdp_imx_bind(struct device *dev, struct device *master,
}
return 0;
-err_irq:
+
+err_free_hdmi_gpio:
+ if (gpio_is_valid(hdp->hdmi_ctrl_gpio))
+ gpio_free(hdp->hdmi_ctrl_gpio);
+err_cleanup_encoder:
drm_encoder_cleanup(encoder);
return ret;
}
@@ -1206,6 +1226,9 @@ static void imx_hdp_imx_unbind(struct device *dev, struct device *master,
imx_hdp_call(hdp, pixel_clock_disable, &hdp->clks);
imx_hdp_call(hdp, pixel_link_deinit, &hdp->state);
drm_bridge_detach(&hdp->bridge);
+
+ if (gpio_is_valid(hdp->hdmi_ctrl_gpio))
+ gpio_free(hdp->hdmi_ctrl_gpio);
}
static const struct component_ops imx_hdp_imx_ops = {
diff --git a/drivers/gpu/drm/imx/hdp/imx-hdp.h b/drivers/gpu/drm/imx/hdp/imx-hdp.h
index 5ece81345aa4..af0f81bbaf02 100644
--- a/drivers/gpu/drm/imx/hdp/imx-hdp.h
+++ b/drivers/gpu/drm/imx/hdp/imx-hdp.h
@@ -107,6 +107,7 @@ struct hdp_ops {
struct hdp_devtype {
u8 is_edid;
u8 is_4kp60;
+ u8 is_hdmi_level;
u8 audio_type;
struct hdp_ops *ops;
struct hdp_rw_func *rw;
@@ -191,6 +192,7 @@ struct imx_hdp {
struct edid *edid;
char cable_state;
+ int hdmi_ctrl_gpio;
void __iomem *regs_base; /* Controller regs base */
void __iomem *ss_base; /* HDP Subsystem regs base */