diff mbox series

[v2,09/15] drm/vc4: hdmi: Split the interrupt handlers

Message ID 20210111142309.193441-10-maxime@cerno.tech
State New
Headers show
Series drm/vc4: hdmi: Add CEC support for the BCM2711 | expand

Commit Message

Maxime Ripard Jan. 11, 2021, 2:23 p.m. UTC
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.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 86 +++++++++++++++++++++++++---------
 1 file changed, 65 insertions(+), 21 deletions(-)

Comments

Dave Stevenson Jan. 22, 2021, 1:01 p.m. UTC | #1
Hi Maxime

On Mon, 11 Jan 2021 at 14:23, Maxime Ripard <maxime@cerno.tech> 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@cerno.tech>

With that
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  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
>
diff mbox series

Patch

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)