aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c')
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c87
1 files changed, 43 insertions, 44 deletions
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index e18b222ed739..e242ed85cb07 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -28,7 +28,6 @@
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/seq_file.h>
-#include <linux/gpio.h>
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
#include <sound/asound.h>
#include <sound/asoundef.h>
@@ -38,6 +37,9 @@
#include "dss.h"
#include "dss_features.h"
+#define HDMI_IRQ_LINK_CONNECT (1 << 25)
+#define HDMI_IRQ_LINK_DISCONNECT (1 << 26)
+
static inline void hdmi_write_reg(void __iomem *base_addr,
const u16 idx, u32 val)
{
@@ -233,37 +235,39 @@ void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data)
hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
}
-static int hdmi_check_hpd_state(struct hdmi_ip_data *ip_data)
+static irqreturn_t hdmi_irq_handler(int irq, void *data)
{
- bool hpd;
- int r;
-
- mutex_lock(&ip_data->lock);
-
- hpd = gpio_get_value(ip_data->hpd_gpio);
+ struct hdmi_ip_data *ip_data = data;
+ void __iomem *wp_base = hdmi_wp_base(ip_data);
+ u32 irqstatus;
+
+ irqstatus = hdmi_read_reg(wp_base, HDMI_WP_IRQSTATUS);
+ hdmi_write_reg(wp_base, HDMI_WP_IRQSTATUS, irqstatus);
+ /* flush posted write */
+ hdmi_read_reg(wp_base, HDMI_WP_IRQSTATUS);
+
+ if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
+ irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
+ /*
+ * If we get both connect and disconnect interrupts at the same
+ * time, turn off the PHY, clear interrupts, and restart, which
+ * raises connect interrupt if a cable is connected, or nothing
+ * if cable is not connected.
+ */
+ hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
- if (hpd)
- r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
- else
- r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
+ hdmi_write_reg(wp_base, HDMI_WP_IRQSTATUS,
+ HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
+ /* flush posted write */
+ hdmi_read_reg(wp_base, HDMI_WP_IRQSTATUS);
- if (r) {
- DSSERR("Failed to %s PHY TX power\n",
- hpd ? "enable" : "disable");
- goto err;
+ hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
+ } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
+ hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
+ } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
+ hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
}
-err:
- mutex_unlock(&ip_data->lock);
- return r;
-}
-
-static irqreturn_t hpd_irq_handler(int irq, void *data)
-{
- struct hdmi_ip_data *ip_data = data;
-
- hdmi_check_hpd_state(ip_data);
-
return IRQ_HANDLED;
}
@@ -272,6 +276,12 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
u16 r = 0;
void __iomem *phy_base = hdmi_phy_base(ip_data);
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_IRQENABLE_CLR,
+ 0xffffffff);
+
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_IRQSTATUS,
+ HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
+
r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
if (r)
return r;
@@ -297,29 +307,23 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
/* Write to phy address 3 to change the polarity control */
REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
- r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio),
- NULL, hpd_irq_handler,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
- IRQF_ONESHOT, "hpd", ip_data);
+ r = request_threaded_irq(ip_data->irq, NULL, hdmi_irq_handler,
+ IRQF_ONESHOT, "OMAP HDMI", ip_data);
if (r) {
- DSSERR("HPD IRQ request failed\n");
+ DSSERR("HDMI IRQ request failed\n");
hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
return r;
}
- r = hdmi_check_hpd_state(ip_data);
- if (r) {
- free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data);
- hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
- return r;
- }
+ hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_IRQENABLE_SET,
+ HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
return 0;
}
void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data)
{
- free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data);
+ free_irq(ip_data->irq, ip_data);
hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
}
@@ -476,11 +480,6 @@ int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data,
return l;
}
-bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data)
-{
- return gpio_get_value(ip_data->hpd_gpio);
-}
-
static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
struct hdmi_core_infoframe_avi *avi_cfg,
struct hdmi_core_packet_enable_repeat *repeat_cfg)