Re: [PATCH 1/2] drm/bridge: ti-sn65dsi86: improve HPD interrupt handling

Doug Anderson <[email protected]>
Newsgroups gmane.linux.kernel,gmane.comp.video.dri.devel
Message-ID <CAD=FV=Vg+v5A4QC3E5U2xnunOmoV9iK6mpwTYoGVX-ZbFa4gMw@mail.gmail.com>
Hi,

On Fri, Aug 14, 2026 at 5:03 AM Yashas D <[email protected]> wrote:
>
> Fix the interrupt handler to clear all three IRQ status registers
> to fully de-assert the IRQ pin, enable replug event detection, and
> use per-connector hotplug notification instead of polling all
> connectors on every DP HPD event.
>
> Signed-off-by: Yashas D <[email protected]>
> ---
>  drivers/gpu/drm/bridge/ti-sn65dsi86.c | 34 ++++++++++++++++++++-------
>  1 file changed, 25 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> index 48b83df9aed6..d9bd4ef8f0e2 100644
> --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> @@ -113,14 +113,19 @@
>  #define SN_IRQ_EVENTS_EN_REG                   0xE6
>  #define  HPD_INSERTION_EN                      BIT(1)
>  #define  HPD_REMOVAL_EN                                BIT(2)
> +#define  HPD_REPLUG_EN                         BIT(3)
>
>  #define SN_AUX_CMD_STATUS_REG                  0xF4
>  #define  AUX_IRQ_STATUS_AUX_RPLY_TOUT          BIT(3)
>  #define  AUX_IRQ_STATUS_AUX_SHORT              BIT(5)
>  #define  AUX_IRQ_STATUS_NAT_I2C_FAIL           BIT(6)
>  #define SN_IRQ_STATUS_REG                      0xF5
> +#define  HPD_REPLUG_STATUS                     BIT(3)
>  #define  HPD_REMOVAL_STATUS                    BIT(2)
>  #define  HPD_INSERTION_STATUS                  BIT(1)
> +/* General IRQ status registers, write-1-to-clear */
> +#define SN_IRQ_STATUS2_REG                     0xF0
> +#define SN_IRQ_STATUS3_REG                     0xF2

nit: blank line before this section?


> @@ -1387,23 +1391,35 @@ static irqreturn_t ti_sn_bridge_interrupt(int irq, void *private)
>                 return IRQ_NONE;
>         }
>
> -       hpd_event = status & (HPD_REMOVAL_STATUS | HPD_INSERTION_STATUS);
> +       hpd_event = status & (HPD_REMOVAL_STATUS | HPD_INSERTION_STATUS |
> +                             HPD_REPLUG_STATUS);
>
>         dev_dbg(pdata->dev, "(SN_IRQ_STATUS_REG = %#x)\n", status);
>         if (!status)
>                 return IRQ_NONE;
>
> -       ret = regmap_write(pdata->regmap, SN_IRQ_STATUS_REG, status);
> +       /*
> +        * Clear all three IRQ status registers to fully de-assert
> +        * the IRQ pin
> +        */
> +       ret  = regmap_write(pdata->regmap, SN_IRQ_STATUS2_REG, 0xFF);
> +       ret |= regmap_write(pdata->regmap, SN_IRQ_STATUS3_REG, 0xFF);
> +       ret |= regmap_write(pdata->regmap, SN_IRQ_STATUS_REG, status);

Can you explain clearly why you need to clear STATUS2 and STATUS3? Is
this actually a thing you saw causing problems?

As far as I understand, all these extra interrupts should be masked
anyway. That means they shouldn't be affecting the IRQ line and they
shouldn't need to be cleared, right? Taking one example bit
(CHA_SOT_BIT_ERR), we can see that in register 0xE1 they default state
is to mask it. That means there should be no need to clear it in
register 0xF2, right?

If you want to be defensive, you could explictly zero out some of the
0xE1 - 0xE5 at probe time just in some bootloader made things enabled.
...but I don't see any reason to be clearing the status registers at
IRQ time unless there's some interrupt that we can't mask.



>         if (ret) {
>                 dev_err(pdata->dev, "Failed to clear IRQ status: %d\n", ret);
>                 return IRQ_NONE;
>         }
>
> -       /* Only send the HPD event if we are bound with a device. */
> +       /* Notify only the DP connector, not all connectors on the device. */
>         mutex_lock(&pdata->hpd_mutex);
> -       if (pdata->hpd_enabled && hpd_event)
> -               drm_kms_helper_hotplug_event(dev);
> -       mutex_unlock(&pdata->hpd_mutex);
> +       if (pdata->hpd_enabled && hpd_event && pdata->bridge.hpd_data) {
> +               struct drm_connector *connector =
> +                       (struct drm_connector *)pdata->bridge.hpd_data;
> +               mutex_unlock(&pdata->hpd_mutex);
> +               drm_connector_helper_hpd_irq_event(connector);
> +       } else {
> +               mutex_unlock(&pdata->hpd_mutex);
> +       }

Do you really need the above change? I haven't studied the DRM
framework all that much, but...

1. It feels like an abstraction violation to reach into
"bridge.hpd_data" and assume it's the connector. I guess Sashiko
agress with me...

2. The documentation for the old function were were calling
(drm_kms_helper_hotplug_event) says that, if you know the connector,
you should call drm_kms_helper_connector_hotplug_event(). You're not
doing that and are instead calling
drm_connector_helper_hpd_irq_event().

Unless this is actually fixing problems, I'm inclined not to take this
patch. If you _really_ feel like it's an improvement, maybe someone
else can comment on it or I can schedule some time in the future to
dig more.


Maybe split the "replug" part of this patch into its own patch, if
that's actually something that you've confirmed is useful / does
something?


-Doug
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.