Am Dienstag, den 07.01.2014, 08:30 -0700 schrieb Eric Nelson: > Hi Philipp, > > On 01/07/2014 04:29 AM, Philipp Zabel wrote: > > Am Montag, den 06.01.2014, 19:31 -0700 schrieb Eric Nelson: > >> Hi Russell, > >> > >> On 01/06/2014 10:46 AM, Russell King - ARM Linux wrote: > >>> On Mon, Jan 06, 2014 at 06:41:28PM +0100, Philipp Zabel wrote: > >>>> Hi Eric, > >>>> > >>>> Am Freitag, den 03.01.2014, 12:14 -0700 schrieb Eric Nelson: > >>>>> This is an issue we've seen before. The SABRE Lite board has > >>>>> a voltage divider on the HPD pins and some monitors (esp. DVI > >>>>> monitors) either don't drive things high enough to assert HPD or > >>>>> bounce with connect/disconnect. > >>>> > >>>> Yes, I used a DVI monitor. > >>>> > >>>>> We've instrumented our 3.0.35 kernels to use the RX_SENSE bits > >>>>> instead. > >>>> > >>>> Reacting to RX_SENSE0 instead of HPD seems to work. > >>> > >>> However, it's non-compliant, because HPD can be lowered and raised by > >>> the sink when it changes its EDID data (eg, because you're connected > >>> through a switch and the routing has been changed.) > >>> > >>> So, reacting to RX_SENSE0 instead of HPD has to be a work-around enabled > >>> only for those boards which are broken in this regard. > >>> > >> > >> I understand. We'll need to carry some patches for a while though, > >> since there are lots of these boards in the wild. > > > > Could you point me to your changes? Maybe this could be added to > > mainline as a quirk enabled by a device tree property on sabrelite only. > > > > We only have them for 3.0.35 at the moment. > > Here's the patch to use RXSENSE instead of HPD > https://github.com/boundarydevices/linux-imx6/commit/c0439e262bb6c23887d96466b2ab7916aa0488d9 > > A follow-up patch disables the disconnect detection entirely > unless requested: > https://github.com/boundarydevices/linux-imx6/commit/d9cd79d11ff9f7a7f89cbc94b68757b67cdfe5fc Thanky you. This is what I came up with so far: From: Philipp Zabel <p.zabel@xxxxxxxxxxxxxx> Subject: [PATCH 1/2] staging: imx-hdmi: use RX_SENSE0 for plug detection if HPD is unreliable On some boards HPD might not reliably detect DVI monitors. Allow to use RX_SENSE0 as a workaround. Signed-off-by: Philipp Zabel <p.zabel@xxxxxxxxxxxxxx> --- drivers/staging/imx-drm/imx-hdmi.c | 45 +++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/drivers/staging/imx-drm/imx-hdmi.c b/drivers/staging/imx-drm/imx-hdmi.c index 7779337..cc305f3 100644 --- a/drivers/staging/imx-drm/imx-hdmi.c +++ b/drivers/staging/imx-drm/imx-hdmi.c @@ -139,6 +139,7 @@ struct imx_hdmi { struct regmap *regmap; struct i2c_adapter *ddc; + bool hpd_unreliable; void __iomem *regs; unsigned int sample_rate; @@ -1309,6 +1310,14 @@ static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode) /* Wait until we are registered to enable interrupts */ static int imx_hdmi_fb_registered(struct imx_hdmi *hdmi) { + int stat_bit = HDMI_IH_PHY_STAT0_HPD; + int mask_bits = ~HDMI_PHY_HPD; + + if (hdmi->hpd_unreliable) { + stat_bit = HDMI_IH_PHY_STAT0_RX_SENSE0; + mask_bits = ~HDMI_PHY_RX_SENSE0; + } + hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL, HDMI_PHY_I2CM_INT_ADDR); @@ -1317,10 +1326,10 @@ static int imx_hdmi_fb_registered(struct imx_hdmi *hdmi) HDMI_PHY_I2CM_CTLINT_ADDR); /* enable cable hot plug irq */ - hdmi_writeb(hdmi, (u8)~HDMI_PHY_RX_SENSE0, HDMI_PHY_MASK0); + hdmi_writeb(hdmi, (u8)mask_bits, HDMI_PHY_MASK0); /* Clear Hotplug interrupts */ - hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_RX_SENSE0, HDMI_IH_PHY_STAT0); + hdmi_writeb(hdmi, stat_bit, HDMI_IH_PHY_STAT0); return 0; } @@ -1524,25 +1533,32 @@ static irqreturn_t imx_hdmi_hardirq(int irq, void *dev_id) static irqreturn_t imx_hdmi_irq(int irq, void *dev_id) { struct imx_hdmi *hdmi = dev_id; + int stat_bit = HDMI_IH_PHY_STAT0_HPD; + int pol_bit = HDMI_PHY_HPD; u8 intr_stat; u8 phy_int_pol; + if (hdmi->hpd_unreliable) { + stat_bit = HDMI_IH_PHY_STAT0_RX_SENSE0; + pol_bit = HDMI_PHY_RX_SENSE0; + } + intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0); phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0); - if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE0) { - if (phy_int_pol & HDMI_PHY_RX_SENSE0) { + if (intr_stat & stat_bit) { + if (phy_int_pol & pol_bit) { dev_dbg(hdmi->dev, "EVENT=plugin\n"); - hdmi_modb(hdmi, 0, HDMI_PHY_RX_SENSE0, HDMI_PHY_POL0); + hdmi_modb(hdmi, 0, pol_bit, HDMI_PHY_POL0); hdmi->connector_status = connector_status_connected; imx_hdmi_poweron(hdmi); } else { dev_dbg(hdmi->dev, "EVENT=plugout\n"); - hdmi_modb(hdmi, HDMI_PHY_RX_SENSE0, HDMI_PHY_RX_SENSE0, HDMI_PHY_POL0); + hdmi_modb(hdmi, pol_bit, pol_bit, HDMI_PHY_POL0); hdmi->connector_status = connector_status_disconnected; imx_hdmi_poweroff(hdmi); @@ -1551,7 +1567,7 @@ static irqreturn_t imx_hdmi_irq(int irq, void *dev_id) } hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0); - hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_RX_SENSE0, HDMI_IH_MUTE_PHY_STAT0); + hdmi_writeb(hdmi, ~stat_bit, HDMI_IH_MUTE_PHY_STAT0); return IRQ_HANDLED; } @@ -1611,6 +1627,7 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data) struct device_node *ddc_node; struct imx_hdmi *hdmi; struct resource *iores; + int pol_bit, stat_bit; int ret, irq; hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); @@ -1703,14 +1720,22 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data) */ hdmi_init_clk_regenerator(hdmi); + pol_bit = HDMI_PHY_HPD; + stat_bit = HDMI_IH_PHY_STAT0_HPD; + hdmi->hpd_unreliable = of_property_read_bool(np, "hpd-unreliable"); + if (hdmi->hpd_unreliable) { + pol_bit = HDMI_PHY_RX_SENSE0; + stat_bit = HDMI_IH_PHY_STAT0_RX_SENSE0; + } + /* * Configure registers related to HDMI interrupt * generation before registering IRQ. */ - hdmi_writeb(hdmi, HDMI_PHY_RX_SENSE0, HDMI_PHY_POL0); + hdmi_writeb(hdmi, pol_bit, HDMI_PHY_POL0); /* Clear Hotplug interrupts */ - hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_RX_SENSE0, HDMI_IH_PHY_STAT0); + hdmi_writeb(hdmi, stat_bit, HDMI_IH_PHY_STAT0); ret = imx_hdmi_fb_registered(hdmi); if (ret) @@ -1721,7 +1746,7 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data) goto err_iahb; /* Unmute interrupts */ - hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_RX_SENSE0, HDMI_IH_MUTE_PHY_STAT0); + hdmi_writeb(hdmi, ~stat_bit, HDMI_IH_MUTE_PHY_STAT0); ret = snd_dw_hdmi_probe(&hdmi->audio, dev, hdmi->regs, irq, hdmi); if (ret) -- 1.8.5.2 regards Philipp _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel