diff options
author | Stefan Agner <stefan.agner@toradex.com> | 2018-02-16 16:07:24 +0100 |
---|---|---|
committer | Stefan Agner <stefan.agner@toradex.com> | 2018-02-16 16:07:24 +0100 |
commit | d8868d38dc929cc5c4591f583489cdc57e93e9f2 (patch) | |
tree | d00a6299e6cf27451204630be07317cdce909e07 | |
parent | 9fe8e87ad955c087d2fa6a35fda3287aa5dccbd7 (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.c | 29 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/hdp/imx-hdp.h | 2 |
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 */ |