Hi Maxime On Mon, 11 Jan 2021 at 14:23, Maxime Ripard <maxime@xxxxxxxxxx> wrote: > > The BCM2711 has two different interrupt sources to transmit and receive > CEC messages, provided through an external interrupt chip shared between > the two HDMI interrupt controllers. > > The rest of the CEC controller is identical though so we need to change > a bit the code organisation to share the code as much as possible, yet > still allowing to register independant handlers. s/independant/independent > > Signed-off-by: Maxime Ripard <maxime@xxxxxxxxxx> With that Reviewed-by: Dave Stevenson <dave.stevenson@xxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/vc4/vc4_hdmi.c | 86 +++++++++++++++++++++++++--------- > 1 file changed, 65 insertions(+), 21 deletions(-) > > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c > index 7b5c92df8f1b..12ca5f3084af 100644 > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c > @@ -1454,15 +1454,22 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) > } > > #ifdef CONFIG_DRM_VC4_HDMI_CEC > -static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv) > +static irqreturn_t vc4_cec_irq_handler_rx_thread(int irq, void *priv) > { > struct vc4_hdmi *vc4_hdmi = priv; > > - if (vc4_hdmi->cec_irq_was_rx) { > - if (vc4_hdmi->cec_rx_msg.len) > - cec_received_msg(vc4_hdmi->cec_adap, > - &vc4_hdmi->cec_rx_msg); > - } else if (vc4_hdmi->cec_tx_ok) { > + if (vc4_hdmi->cec_rx_msg.len) > + cec_received_msg(vc4_hdmi->cec_adap, > + &vc4_hdmi->cec_rx_msg); > + > + return IRQ_HANDLED; > +} > + > +static irqreturn_t vc4_cec_irq_handler_tx_thread(int irq, void *priv) > +{ > + struct vc4_hdmi *vc4_hdmi = priv; > + > + if (vc4_hdmi->cec_tx_ok) { > cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK, > 0, 0, 0, 0); > } else { > @@ -1476,6 +1483,19 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv) > return IRQ_HANDLED; > } > > +static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv) > +{ > + struct vc4_hdmi *vc4_hdmi = priv; > + irqreturn_t ret; > + > + if (vc4_hdmi->cec_irq_was_rx) > + ret = vc4_cec_irq_handler_rx_thread(irq, priv); > + else > + ret = vc4_cec_irq_handler_tx_thread(irq, priv); > + > + return ret; > +} > + > static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) > { > struct drm_device *dev = vc4_hdmi->connector.dev; > @@ -1500,31 +1520,55 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) > } > } > > +static irqreturn_t vc4_cec_irq_handler_tx_bare(int irq, void *priv) > +{ > + struct vc4_hdmi *vc4_hdmi = priv; > + u32 cntrl1; > + > + cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1); > + vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD; > + cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN; > + HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1); > + > + return IRQ_WAKE_THREAD; > +} > + > +static irqreturn_t vc4_cec_irq_handler_rx_bare(int irq, void *priv) > +{ > + struct vc4_hdmi *vc4_hdmi = priv; > + u32 cntrl1; > + > + vc4_hdmi->cec_rx_msg.len = 0; > + cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1); > + vc4_cec_read_msg(vc4_hdmi, cntrl1); > + cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF; > + HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1); > + cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF; > + > + HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1); > + > + return IRQ_WAKE_THREAD; > +} > + > static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) > { > struct vc4_hdmi *vc4_hdmi = priv; > u32 stat = HDMI_READ(HDMI_CEC_CPU_STATUS); > - u32 cntrl1, cntrl5; > + irqreturn_t ret; > + u32 cntrl5; > > if (!(stat & VC4_HDMI_CPU_CEC)) > return IRQ_NONE; > - vc4_hdmi->cec_rx_msg.len = 0; > - cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1); > + > cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5); > vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT; > - if (vc4_hdmi->cec_irq_was_rx) { > - vc4_cec_read_msg(vc4_hdmi, cntrl1); > - cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF; > - HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1); > - cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF; > - } else { > - vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD; > - cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN; > - } > - HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1); > + if (vc4_hdmi->cec_irq_was_rx) > + ret = vc4_cec_irq_handler_rx_bare(irq, priv); > + else > + ret = vc4_cec_irq_handler_tx_bare(irq, priv); > + > HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC); > - > - return IRQ_WAKE_THREAD; > + return ret; > } > > static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) > -- > 2.29.2 >