summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Winkler <robert.winkler@boundarydevices.com>2013-07-19 19:00:41 -0700
committerRobert Winkler <robert.winkler@boundarydevices.com>2013-07-19 19:05:16 -0700
commit7d8752905c118af9063738a533227de0b2f6ecd4 (patch)
tree3f6cf636efc2477f87fb45d7648b6a430a72058d
parent9a25a3684e15951a570896f14936bd65e5b05d2f (diff)
Add support for DVI monitors3.0-boundary-imx6-3.0.35-4.0.0-ts1
Signed-off-by: Robert Winkler <robert.winkler@boundarydevices.com>
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc_hdmi.h7
-rw-r--r--drivers/video/mxc_hdmi.c100
2 files changed, 50 insertions, 57 deletions
diff --git a/arch/arm/plat-mxc/include/mach/mxc_hdmi.h b/arch/arm/plat-mxc/include/mach/mxc_hdmi.h
index 60946cadc441..8a7b991a669d 100644
--- a/arch/arm/plat-mxc/include/mach/mxc_hdmi.h
+++ b/arch/arm/plat-mxc/include/mach/mxc_hdmi.h
@@ -605,6 +605,10 @@ enum {
HDMI_IH_MUTE_PHY_STAT0_TX_PHY_LOCK = 0x2,
HDMI_IH_MUTE_PHY_STAT0_HPD = 0x1,
+/* IH and IH_MUTE convenience macro RX_SENSE | HPD*/
+ HDMI_DVI_IH_STAT = 0x3D,
+
+
/* IH_AHBDMAAUD_STAT0 field values */
HDMI_IH_AHBDMAAUD_STAT0_ERROR = 0x20,
HDMI_IH_AHBDMAAUD_STAT0_LOST = 0x10,
@@ -903,6 +907,9 @@ enum {
HDMI_PHY_HPD = 0x02,
HDMI_PHY_TX_PHY_LOCK = 0x01,
+/* HDMI STAT convenience RX_SENSE | HPD */
+ HDMI_DVI_STAT = 0xF2,
+
/* PHY_I2CM_SLAVE_ADDR field values */
HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69,
HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY = 0x49,
diff --git a/drivers/video/mxc_hdmi.c b/drivers/video/mxc_hdmi.c
index d38ac10b76ae..68f845093e2a 100644
--- a/drivers/video/mxc_hdmi.c
+++ b/drivers/video/mxc_hdmi.c
@@ -178,7 +178,6 @@ struct mxc_hdmi {
bool dft_mode_set;
char *dft_mode_str;
int default_bpp;
- u8 latest_intr_stat;
bool irq_enabled;
spinlock_t irq_lock;
bool phy_enabled;
@@ -1784,58 +1783,48 @@ static void hotplug_worker(struct work_struct *work)
struct delayed_work *delay_work = to_delayed_work(work);
struct mxc_hdmi *hdmi =
container_of(delay_work, struct mxc_hdmi, hotplug_work);
- u32 phy_int_stat, phy_int_pol, phy_int_mask;
- u8 val;
+ u32 hdmi_phy_stat0, hdmi_phy_pol0, hdmi_phy_mask0;
unsigned long flags;
char event_string[16];
char *envp[] = { event_string, NULL };
- phy_int_stat = hdmi->latest_intr_stat;
- phy_int_pol = hdmi_readb(HDMI_PHY_POL0);
- dev_dbg(&hdmi->pdev->dev, "phy_int_stat=0x%x, phy_int_pol=0x%x\n",
- phy_int_stat, phy_int_pol);
+ hdmi_phy_stat0 = hdmi_readb(HDMI_PHY_STAT0);
+ hdmi_phy_pol0 = hdmi_readb(HDMI_PHY_POL0);
+
+ dev_dbg(&hdmi->pdev->dev, "hdmi_phy_stat0=0x%x, hdmi_phy_pol0=0x%x\n",
+ hdmi_phy_stat0, hdmi_phy_pol0);
+
+ /* Make HPD intr active low to capture unplug event or
+ * active high to capture plugin event */
+ hdmi_writeb((HDMI_DVI_STAT & ~hdmi_phy_stat0), HDMI_PHY_POL0);
/* check cable status */
- if (phy_int_stat & HDMI_IH_PHY_STAT0_HPD) {
- /* cable connection changes */
- if (phy_int_pol & HDMI_PHY_HPD) {
- /* Plugin event */
- dev_dbg(&hdmi->pdev->dev, "EVENT=plugin\n");
- mxc_hdmi_cable_connected(hdmi);
-
- /* Make HPD intr active low to capture unplug event */
- val = hdmi_readb(HDMI_PHY_POL0);
- val &= ~HDMI_PHY_HPD;
- hdmi_writeb(val, HDMI_PHY_POL0);
-
- sprintf(event_string, "EVENT=plugin");
- kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+ if (hdmi_phy_stat0 & HDMI_DVI_STAT) {
+ /* Plugin event */
+ dev_dbg(&hdmi->pdev->dev, "EVENT=plugin\n");
+ mxc_hdmi_cable_connected(hdmi);
+
+ sprintf(event_string, "EVENT=plugin");
+ kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
#ifdef CONFIG_MXC_HDMI_CEC
- mxc_hdmi_cec_handle(0x80);
+ mxc_hdmi_cec_handle(0x80);
#endif
- hdmi_set_cable_state(1);
-
- } else if (!(phy_int_pol & HDMI_PHY_HPD)) {
- /* Plugout event */
- dev_dbg(&hdmi->pdev->dev, "EVENT=plugout\n");
- hdmi_set_cable_state(0);
- mxc_hdmi_abort_stream();
- mxc_hdmi_cable_disconnected(hdmi);
+ hdmi_set_cable_state(1);
- /* Make HPD intr active high to capture plugin event */
- val = hdmi_readb(HDMI_PHY_POL0);
- val |= HDMI_PHY_HPD;
- hdmi_writeb(val, HDMI_PHY_POL0);
-
- sprintf(event_string, "EVENT=plugout");
- kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+ } else {
+ /* Plugout event */
+ dev_dbg(&hdmi->pdev->dev, "EVENT=plugout\n");
+ hdmi_set_cable_state(0);
+ mxc_hdmi_abort_stream();
+ mxc_hdmi_cable_disconnected(hdmi);
+
+ sprintf(event_string, "EVENT=plugout");
+ kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
#ifdef CONFIG_MXC_HDMI_CEC
- mxc_hdmi_cec_handle(0x100);
+ mxc_hdmi_cec_handle(0x100);
#endif
- } else
- dev_dbg(&hdmi->pdev->dev, "EVENT=none?\n");
}
/* Lock here to ensure full powerdown sequence
@@ -1843,12 +1832,12 @@ static void hotplug_worker(struct work_struct *work)
spin_lock_irqsave(&hdmi->irq_lock, flags);
/* Re-enable HPD interrupts */
- phy_int_mask = hdmi_readb(HDMI_PHY_MASK0);
- phy_int_mask &= ~HDMI_PHY_HPD;
- hdmi_writeb(phy_int_mask, HDMI_PHY_MASK0);
+ hdmi_phy_mask0 = hdmi_readb(HDMI_PHY_MASK0);
+ hdmi_phy_mask0 &= ~HDMI_DVI_STAT;
+ hdmi_writeb(hdmi_phy_mask0, HDMI_PHY_MASK0);
/* Unmute interrupts */
- hdmi_writeb(~HDMI_IH_MUTE_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+ hdmi_writeb(~HDMI_DVI_IH_STAT, HDMI_IH_MUTE_PHY_STAT0);
if (hdmi_readb(HDMI_IH_FC_STAT2) & HDMI_IH_FC_STAT2_OVERFLOW_MASK)
mxc_hdmi_clear_overflow();
@@ -1859,7 +1848,7 @@ static void hotplug_worker(struct work_struct *work)
static irqreturn_t mxc_hdmi_hotplug(int irq, void *data)
{
struct mxc_hdmi *hdmi = data;
- u8 val, intr_stat;
+ u8 val;
unsigned long flags;
spin_lock_irqsave(&hdmi->irq_lock, flags);
@@ -1881,25 +1870,22 @@ static irqreturn_t mxc_hdmi_hotplug(int irq, void *data)
* HDMI registers.
*/
/* Capture status - used in hotplug_worker ISR */
- intr_stat = hdmi_readb(HDMI_IH_PHY_STAT0);
-
- if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
+ if (hdmi_readb(HDMI_IH_PHY_STAT0) & HDMI_DVI_IH_STAT) {
dev_dbg(&hdmi->pdev->dev, "Hotplug interrupt received\n");
- hdmi->latest_intr_stat = intr_stat;
/* Mute interrupts until handled */
val = hdmi_readb(HDMI_IH_MUTE_PHY_STAT0);
- val |= HDMI_IH_MUTE_PHY_STAT0_HPD;
+ val |= HDMI_DVI_IH_STAT;
hdmi_writeb(val, HDMI_IH_MUTE_PHY_STAT0);
val = hdmi_readb(HDMI_PHY_MASK0);
- val |= HDMI_PHY_HPD;
+ val |= HDMI_DVI_STAT;
hdmi_writeb(val, HDMI_PHY_MASK0);
/* Clear Hotplug interrupts */
- hdmi_writeb(HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+ hdmi_writeb(HDMI_DVI_IH_STAT, HDMI_IH_PHY_STAT0);
schedule_delayed_work(&(hdmi->hotplug_work), msecs_to_jiffies(20));
}
@@ -2059,13 +2045,13 @@ static void mxc_hdmi_fb_registered(struct mxc_hdmi *hdmi)
HDMI_PHY_I2CM_CTLINT_ADDR);
/* enable cable hot plug irq */
- hdmi_writeb((u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
+ hdmi_writeb((u8)~HDMI_DVI_STAT, HDMI_PHY_MASK0);
/* Clear Hotplug interrupts */
- hdmi_writeb(HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+ hdmi_writeb(HDMI_DVI_IH_STAT, HDMI_IH_PHY_STAT0);
/* Unmute interrupts */
- hdmi_writeb(~HDMI_IH_MUTE_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+ hdmi_writeb(~HDMI_DVI_IH_STAT, HDMI_IH_MUTE_PHY_STAT0);
hdmi->fb_reg = true;
@@ -2298,10 +2284,10 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_handle *disp,
/* Configure registers related to HDMI interrupt
* generation before registering IRQ. */
- hdmi_writeb(HDMI_PHY_HPD, HDMI_PHY_POL0);
+ hdmi_writeb(HDMI_DVI_STAT, HDMI_PHY_POL0);
/* Clear Hotplug interrupts */
- hdmi_writeb(HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+ hdmi_writeb(HDMI_DVI_IH_STAT, HDMI_IH_PHY_STAT0);
hdmi->nb.notifier_call = mxc_hdmi_fb_event;
ret = fb_register_client(&hdmi->nb);