Hi Alexander,

On 10/06/2026 19:48, Alexander Kaplan wrote:
> The DP standard requires a DP-to-HDMI protocol converter to assert
> an IRQ_HPD pulse with the CEC_IRQ bit in the
> DEVICE_SERVICE_IRQ_VECTOR_ESI1 register set whenever it sets a bit in
> the CEC_TUNNELING_IRQ_FLAGS register (DP v2.0, Table 2-194, DPCD
> address 3004h).
> 
> The Synaptics VMM7100 based DP-to-HDMI protocol converters get this
> half right.
> They assert an IRQ_HPD pulse for each CEC event, but never set the
> CEC_IRQ bit.
> ESI1 reads as 0 at the very moment CEC_TUNNELING_IRQ_FLAGS has the
> corresponding TX/RX flags set.
> drm_dp_cec_irq() trusts the bit and returns without servicing the
> flags, so no transmit is ever completed and the CEC adapter is
> unusable with these devices.
> Every transmit times out, claiming a logical address fails and the
> /dev/cecX device ends up unconfigured.
> The converter's CEC engine itself works fine.
> Driving the CEC tunneling DPCD registers manually shows the TV
> ACKing the tunneled messages and sending requests of its own.
> 
> Demote the CEC_IRQ bit from a gate to an acknowledge hint: service
> the CEC tunneling IRQ flags on every IRQ_HPD pulse, whether or not
> the branch device set CEC_IRQ, and acknowledge CEC_IRQ in ESI1 only
> when it was actually set.
> Servicing is idempotent since every action is keyed to a
> write-1-to-clear flag bit, so for branch devices with no pending CEC
> event this amounts to one additional AUX read of the flags register,
> and only on connectors that advertise the CEC tunneling capability
> (without it no CEC adapter is registered and drm_dp_cec_irq()
> returns early as before).
> Devices that conformantly set CEC_IRQ are serviced exactly as before.
> 
> With this the CEC adapter of a VMM7100 based USB-C to HDMI adapter
> configures and transmits successfully (verified against an LG OLED
> TV with an Intel Panther Lake xe device, including TV power on/off
> over CEC).
> 
> Fixes: 2c6d1fffa1d9 ("drm: add support for DisplayPort 
> CEC-Tunneling-over-AUX")
> Signed-off-by: Alexander Kaplan <[email protected]>
> ---
> This patch is part of a set of independent fixes for the USB-C to DP
> to HDMI 2.1 protocol converter (PCON) path, found and verified on an
> ASUS NUC 16 Pro (Panther Lake, xe) with Synaptics VMM7100 based
> adapters.
> Each part stands on its own and can be merged independently.
> The other parts:
> [1] 
> https://lore.kernel.org/r/[email protected]
> [2] 
> https://lore.kernel.org/r/[email protected]
> [3] 
> https://lore.kernel.org/r/[email protected]
>  drivers/gpu/drm/display/drm_dp_cec.c | 18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_cec.c 
> b/drivers/gpu/drm/display/drm_dp_cec.c
> index 436bfe9f9081..824a99f86a3d 100644
> --- a/drivers/gpu/drm/display/drm_dp_cec.c
> +++ b/drivers/gpu/drm/display/drm_dp_cec.c
> @@ -218,6 +218,9 @@ static void drm_dp_cec_handle_irq(struct drm_dp_aux *aux)
>       if (drm_dp_dpcd_read_byte(aux, DP_CEC_TUNNELING_IRQ_FLAGS, &flags) < 0)
>               return;
>  
> +     if (!flags)
> +             return;
> +
>       if (flags & DP_CEC_RX_MESSAGE_INFO_VALID)
>               drm_dp_cec_received(aux);
>  
> @@ -255,11 +258,22 @@ void drm_dp_cec_irq(struct drm_dp_aux *aux)
>  
>       ret = drm_dp_dpcd_read_byte(aux, DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1,
>                                   &cec_irq);
> -     if (ret < 0 || !(cec_irq & DP_CEC_IRQ))
> +     if (ret < 0)
>               goto unlock;

I saw that you added a quirk for this device in this patch series:

https://lore.kernel.org/all/[email protected]/

Should we add a quirk for this as well? It's not worth it if that's a lot of 
work,
but if it is easy to add, then I think that's the better approach for this.

Regards,

        Hans

>  
> +     /*
> +      * Some branch devices, for instance the Synaptics VMM7100 based
> +      * DP-to-HDMI protocol converters, assert an IRQ_HPD pulse for each
> +      * CEC event, but never set the CEC_IRQ bit in the
> +      * DEVICE_SERVICE_IRQ_VECTOR_ESI1 register. Check the CEC tunneling
> +      * IRQ flags even without CEC_IRQ being set: servicing the flags is
> +      * idempotent and only costs one additional AUX read.
> +      */
>       drm_dp_cec_handle_irq(aux);
> -     drm_dp_dpcd_write_byte(aux, DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1, 
> DP_CEC_IRQ);
> +
> +     if (cec_irq & DP_CEC_IRQ)
> +             drm_dp_dpcd_write_byte(aux, DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1,
> +                                    DP_CEC_IRQ);
>  unlock:
>       mutex_unlock(&aux->cec.lock);
>  }

Reply via email to