bcm27xx: switch to 5.15
[openwrt/staging/chunkeey.git] / target / linux / bcm27xx / patches-5.10 / 950-0458-drm-vc4-hdmi-Split-the-interrupt-handlers.patch
1 From 423173ed6e873ec9a6ae0e62d55bd4c746f0f982 Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Mon, 11 Jan 2021 15:23:03 +0100
4 Subject: [PATCH] drm/vc4: hdmi: Split the interrupt handlers
5
6 The BCM2711 has two different interrupt sources to transmit and receive
7 CEC messages, provided through an external interrupt chip shared between
8 the two HDMI interrupt controllers.
9
10 The rest of the CEC controller is identical though so we need to change
11 a bit the code organisation to share the code as much as possible, yet
12 still allowing to register independant handlers.
13
14 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
15 Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
16 ---
17 drivers/gpu/drm/vc4/vc4_hdmi.c | 86 +++++++++++++++++++++++++---------
18 1 file changed, 65 insertions(+), 21 deletions(-)
19
20 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
21 +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
22 @@ -1574,15 +1574,22 @@ static int vc4_hdmi_audio_init(struct vc
23 }
24
25 #ifdef CONFIG_DRM_VC4_HDMI_CEC
26 -static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
27 +static irqreturn_t vc4_cec_irq_handler_rx_thread(int irq, void *priv)
28 +{
29 + struct vc4_hdmi *vc4_hdmi = priv;
30 +
31 + if (vc4_hdmi->cec_rx_msg.len)
32 + cec_received_msg(vc4_hdmi->cec_adap,
33 + &vc4_hdmi->cec_rx_msg);
34 +
35 + return IRQ_HANDLED;
36 +}
37 +
38 +static irqreturn_t vc4_cec_irq_handler_tx_thread(int irq, void *priv)
39 {
40 struct vc4_hdmi *vc4_hdmi = priv;
41
42 - if (vc4_hdmi->cec_irq_was_rx) {
43 - if (vc4_hdmi->cec_rx_msg.len)
44 - cec_received_msg(vc4_hdmi->cec_adap,
45 - &vc4_hdmi->cec_rx_msg);
46 - } else if (vc4_hdmi->cec_tx_ok) {
47 + if (vc4_hdmi->cec_tx_ok) {
48 cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK,
49 0, 0, 0, 0);
50 } else {
51 @@ -1596,6 +1603,19 @@ static irqreturn_t vc4_cec_irq_handler_t
52 return IRQ_HANDLED;
53 }
54
55 +static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
56 +{
57 + struct vc4_hdmi *vc4_hdmi = priv;
58 + irqreturn_t ret;
59 +
60 + if (vc4_hdmi->cec_irq_was_rx)
61 + ret = vc4_cec_irq_handler_rx_thread(irq, priv);
62 + else
63 + ret = vc4_cec_irq_handler_tx_thread(irq, priv);
64 +
65 + return ret;
66 +}
67 +
68 static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
69 {
70 struct drm_device *dev = vc4_hdmi->connector.dev;
71 @@ -1620,31 +1640,55 @@ static void vc4_cec_read_msg(struct vc4_
72 }
73 }
74
75 +static irqreturn_t vc4_cec_irq_handler_tx_bare(int irq, void *priv)
76 +{
77 + struct vc4_hdmi *vc4_hdmi = priv;
78 + u32 cntrl1;
79 +
80 + cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
81 + vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
82 + cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
83 + HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
84 +
85 + return IRQ_WAKE_THREAD;
86 +}
87 +
88 +static irqreturn_t vc4_cec_irq_handler_rx_bare(int irq, void *priv)
89 +{
90 + struct vc4_hdmi *vc4_hdmi = priv;
91 + u32 cntrl1;
92 +
93 + vc4_hdmi->cec_rx_msg.len = 0;
94 + cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
95 + vc4_cec_read_msg(vc4_hdmi, cntrl1);
96 + cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
97 + HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
98 + cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
99 +
100 + HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
101 +
102 + return IRQ_WAKE_THREAD;
103 +}
104 +
105 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
106 {
107 struct vc4_hdmi *vc4_hdmi = priv;
108 u32 stat = HDMI_READ(HDMI_CEC_CPU_STATUS);
109 - u32 cntrl1, cntrl5;
110 + irqreturn_t ret;
111 + u32 cntrl5;
112
113 if (!(stat & VC4_HDMI_CPU_CEC))
114 return IRQ_NONE;
115 - vc4_hdmi->cec_rx_msg.len = 0;
116 - cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
117 +
118 cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5);
119 vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
120 - if (vc4_hdmi->cec_irq_was_rx) {
121 - vc4_cec_read_msg(vc4_hdmi, cntrl1);
122 - cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
123 - HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
124 - cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
125 - } else {
126 - vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
127 - cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
128 - }
129 - HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
130 - HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC);
131 + if (vc4_hdmi->cec_irq_was_rx)
132 + ret = vc4_cec_irq_handler_rx_bare(irq, priv);
133 + else
134 + ret = vc4_cec_irq_handler_tx_bare(irq, priv);
135
136 - return IRQ_WAKE_THREAD;
137 + HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC);
138 + return ret;
139 }
140
141 static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)