8691fdc49a11e634a231695bd2365efa3df4c813
[openwrt/staging/blogic.git] /
1 From d91a953904e1aeddf24a95af40fc1ae7ba2319fd Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Mon, 25 Oct 2021 16:11:08 +0200
4 Subject: [PATCH] drm/vc4: hdmi: Add a spinlock to protect register
5 access
6
7 The vc4 HDMI driver has multiple path shared between the CEC, ALSA and
8 KMS frameworks, plus two interrupt handlers (CEC and hotplug) that will
9 read and modify a number of registers.
10
11 Even though not bug has been reported so far, it's definitely unsafe, so
12 let's just add a spinlock to protect the register access of the HDMI
13 controller.
14
15 Link: https://lore.kernel.org/r/20211025141113.702757-5-maxime@cerno.tech
16 Fixes: c8b75bca92cb ("drm/vc4: Add KMS support for Raspberry Pi.")
17 Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
18 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
19 ---
20 drivers/gpu/drm/vc4/vc4_hdmi.c | 202 ++++++++++++++++++++++++++--
21 drivers/gpu/drm/vc4/vc4_hdmi.h | 5 +
22 drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 37 +++++
23 drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 2 +
24 4 files changed, 236 insertions(+), 10 deletions(-)
25
26 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
27 +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
28 @@ -122,6 +122,10 @@ static int vc4_hdmi_debugfs_regs(struct
29
30 static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
31 {
32 + unsigned long flags;
33 +
34 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
35 +
36 HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
37 udelay(1);
38 HDMI_WRITE(HDMI_M_CTL, 0);
39 @@ -133,24 +137,36 @@ static void vc4_hdmi_reset(struct vc4_hd
40 VC4_HDMI_SW_RESET_FORMAT_DETECT);
41
42 HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
43 +
44 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
45 }
46
47 static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
48 {
49 + unsigned long flags;
50 +
51 reset_control_reset(vc4_hdmi->reset);
52
53 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
54 +
55 HDMI_WRITE(HDMI_DVP_CTL, 0);
56
57 HDMI_WRITE(HDMI_CLOCK_STOP,
58 HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL);
59 +
60 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
61 }
62
63 #ifdef CONFIG_DRM_VC4_HDMI_CEC
64 static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi)
65 {
66 + unsigned long cec_rate = clk_get_rate(vc4_hdmi->cec_clock);
67 + unsigned long flags;
68 u16 clk_cnt;
69 u32 value;
70
71 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
72 +
73 value = HDMI_READ(HDMI_CEC_CNTRL_1);
74 value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
75
76 @@ -158,9 +174,11 @@ static void vc4_hdmi_cec_update_clk_div(
77 * Set the clock divider: the hsm_clock rate and this divider
78 * setting will give a 40 kHz CEC clock.
79 */
80 - clk_cnt = clk_get_rate(vc4_hdmi->cec_clock) / CEC_CLOCK_FREQ;
81 + clk_cnt = cec_rate / CEC_CLOCK_FREQ;
82 value |= clk_cnt << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT;
83 HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
84 +
85 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
86 }
87 #else
88 static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {}
89 @@ -179,8 +197,16 @@ vc4_hdmi_connector_detect(struct drm_con
90 if (vc4_hdmi->hpd_gpio) {
91 if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio))
92 connected = true;
93 - } else if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) {
94 - connected = true;
95 + } else {
96 + unsigned long flags;
97 + u32 hotplug;
98 +
99 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
100 + hotplug = HDMI_READ(HDMI_HOTPLUG);
101 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
102 +
103 + if (hotplug & VC4_HDMI_HOTPLUG_CONNECTED)
104 + connected = true;
105 }
106
107 if (connected) {
108 @@ -374,9 +400,12 @@ static int vc4_hdmi_stop_packet(struct d
109 {
110 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
111 u32 packet_id = type - 0x80;
112 + unsigned long flags;
113
114 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
115 HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
116 HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
117 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
118
119 if (!poll)
120 return 0;
121 @@ -396,6 +425,7 @@ static void vc4_hdmi_write_infoframe(str
122 void __iomem *base = __vc4_hdmi_get_field_base(vc4_hdmi,
123 ram_packet_start->reg);
124 uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
125 + unsigned long flags;
126 ssize_t len, i;
127 int ret;
128
129 @@ -413,6 +443,8 @@ static void vc4_hdmi_write_infoframe(str
130 return;
131 }
132
133 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
134 +
135 for (i = 0; i < len; i += 7) {
136 writel(buffer[i + 0] << 0 |
137 buffer[i + 1] << 8 |
138 @@ -430,6 +462,9 @@ static void vc4_hdmi_write_infoframe(str
139
140 HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
141 HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
142 +
143 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
144 +
145 ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) &
146 BIT(packet_id)), 100);
147 if (ret)
148 @@ -549,6 +584,7 @@ static void vc4_hdmi_enable_scrambling(s
149 {
150 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
151 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
152 + unsigned long flags;
153
154 if (!vc4_hdmi_supports_scrambling(encoder, mode))
155 return;
156 @@ -559,8 +595,10 @@ static void vc4_hdmi_enable_scrambling(s
157 drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true);
158 drm_scdc_set_scrambling(vc4_hdmi->ddc, true);
159
160 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
161 HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) |
162 VC5_HDMI_SCRAMBLER_CTL_ENABLE);
163 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
164
165 queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work,
166 msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS));
167 @@ -570,6 +608,7 @@ static void vc4_hdmi_disable_scrambling(
168 {
169 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
170 struct drm_crtc *crtc = encoder->crtc;
171 + unsigned long flags;
172
173 /*
174 * At boot, encoder->crtc will be NULL. Since we don't know the
175 @@ -585,8 +624,10 @@ static void vc4_hdmi_disable_scrambling(
176 if (delayed_work_pending(&vc4_hdmi->scrambling_work))
177 cancel_delayed_work_sync(&vc4_hdmi->scrambling_work);
178
179 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
180 HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) &
181 ~VC5_HDMI_SCRAMBLER_CTL_ENABLE);
182 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
183
184 drm_scdc_set_scrambling(vc4_hdmi->ddc, false);
185 drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, false);
186 @@ -612,15 +653,23 @@ static void vc4_hdmi_encoder_post_crtc_d
187 struct drm_atomic_state *state)
188 {
189 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
190 + unsigned long flags;
191 +
192 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
193
194 HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
195
196 HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_CLRRGB);
197
198 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
199 +
200 mdelay(1);
201
202 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
203 HDMI_WRITE(HDMI_VID_CTL,
204 HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
205 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
206 +
207 vc4_hdmi_disable_scrambling(encoder);
208 }
209
210 @@ -628,10 +677,13 @@ static void vc4_hdmi_encoder_post_crtc_p
211 struct drm_atomic_state *state)
212 {
213 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
214 + unsigned long flags;
215 int ret;
216
217 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
218 HDMI_WRITE(HDMI_VID_CTL,
219 HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
220 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
221
222 if (vc4_hdmi->variant->phy_disable)
223 vc4_hdmi->variant->phy_disable(vc4_hdmi);
224 @@ -650,8 +702,11 @@ static void vc4_hdmi_encoder_disable(str
225
226 static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
227 {
228 + unsigned long flags;
229 u32 csc_ctl;
230
231 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
232 +
233 csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
234 VC4_HD_CSC_CTL_ORDER);
235
236 @@ -681,14 +736,19 @@ static void vc4_hdmi_csc_setup(struct vc
237
238 /* The RGB order applies even when CSC is disabled. */
239 HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
240 +
241 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
242 }
243
244 static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
245 {
246 + unsigned long flags;
247 u32 csc_ctl;
248
249 csc_ctl = 0x07; /* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */
250
251 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
252 +
253 if (enable) {
254 /* CEA VICs other than #1 requre limited range RGB
255 * output unless overridden by an AVI infoframe.
256 @@ -720,6 +780,8 @@ static void vc5_hdmi_csc_setup(struct vc
257 }
258
259 HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
260 +
261 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
262 }
263
264 static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
265 @@ -743,6 +805,9 @@ static void vc4_hdmi_set_timings(struct
266 VC4_SET_FIELD(mode->crtc_vtotal -
267 mode->crtc_vsync_end,
268 VC4_HDMI_VERTB_VBP));
269 + unsigned long flags;
270 +
271 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
272
273 HDMI_WRITE(HDMI_HORZA,
274 (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
275 @@ -766,6 +831,8 @@ static void vc4_hdmi_set_timings(struct
276
277 HDMI_WRITE(HDMI_VERTB0, vertb_even);
278 HDMI_WRITE(HDMI_VERTB1, vertb);
279 +
280 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
281 }
282
283 static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
284 @@ -790,10 +857,13 @@ static void vc5_hdmi_set_timings(struct
285 VC4_SET_FIELD(mode->crtc_vtotal -
286 mode->crtc_vsync_end,
287 VC4_HDMI_VERTB_VBP));
288 + unsigned long flags;
289 unsigned char gcp;
290 bool gcp_en;
291 u32 reg;
292
293 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
294 +
295 HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
296 HDMI_WRITE(HDMI_HORZA,
297 (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |
298 @@ -857,13 +927,18 @@ static void vc5_hdmi_set_timings(struct
299 HDMI_WRITE(HDMI_MISC_CONTROL, reg);
300
301 HDMI_WRITE(HDMI_CLOCK_STOP, 0);
302 +
303 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
304 }
305
306 static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
307 {
308 + unsigned long flags;
309 u32 drift;
310 int ret;
311
312 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
313 +
314 drift = HDMI_READ(HDMI_FIFO_CTL);
315 drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
316
317 @@ -871,12 +946,20 @@ static void vc4_hdmi_recenter_fifo(struc
318 drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
319 HDMI_WRITE(HDMI_FIFO_CTL,
320 drift | VC4_HDMI_FIFO_CTL_RECENTER);
321 +
322 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
323 +
324 usleep_range(1000, 1100);
325 +
326 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
327 +
328 HDMI_WRITE(HDMI_FIFO_CTL,
329 drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
330 HDMI_WRITE(HDMI_FIFO_CTL,
331 drift | VC4_HDMI_FIFO_CTL_RECENTER);
332
333 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
334 +
335 ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
336 VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
337 WARN_ONCE(ret, "Timeout waiting for "
338 @@ -910,6 +993,7 @@ static void vc4_hdmi_encoder_pre_crtc_co
339 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
340 unsigned long pixel_rate = vc4_conn_state->pixel_rate;
341 unsigned long bvb_rate, hsm_rate;
342 + unsigned long flags;
343 int ret;
344
345 /*
346 @@ -978,11 +1062,15 @@ static void vc4_hdmi_encoder_pre_crtc_co
347 if (vc4_hdmi->variant->phy_init)
348 vc4_hdmi->variant->phy_init(vc4_hdmi, vc4_conn_state);
349
350 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
351 +
352 HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
353 HDMI_READ(HDMI_SCHEDULER_CONTROL) |
354 VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
355 VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
356
357 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
358 +
359 if (vc4_hdmi->variant->set_timings)
360 vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode);
361
362 @@ -1002,6 +1090,7 @@ static void vc4_hdmi_encoder_pre_crtc_en
363 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
364 struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
365 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
366 + unsigned long flags;
367
368 if (vc4_encoder->hdmi_monitor &&
369 drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
370 @@ -1016,7 +1105,9 @@ static void vc4_hdmi_encoder_pre_crtc_en
371 vc4_encoder->limited_rgb_range = false;
372 }
373
374 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
375 HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
376 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
377 }
378
379 static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
380 @@ -1027,8 +1118,11 @@ static void vc4_hdmi_encoder_post_crtc_e
381 struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
382 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
383 bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
384 + unsigned long flags;
385 int ret;
386
387 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
388 +
389 HDMI_WRITE(HDMI_VID_CTL,
390 VC4_HD_VID_CTL_ENABLE |
391 VC4_HD_VID_CTL_CLRRGB |
392 @@ -1045,6 +1139,8 @@ static void vc4_hdmi_encoder_post_crtc_e
393 HDMI_READ(HDMI_SCHEDULER_CONTROL) |
394 VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
395
396 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
397 +
398 ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
399 VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
400 WARN_ONCE(ret, "Timeout waiting for "
401 @@ -1057,6 +1153,8 @@ static void vc4_hdmi_encoder_post_crtc_e
402 HDMI_READ(HDMI_SCHEDULER_CONTROL) &
403 ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
404
405 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
406 +
407 ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
408 VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
409 WARN_ONCE(ret, "Timeout waiting for "
410 @@ -1064,6 +1162,8 @@ static void vc4_hdmi_encoder_post_crtc_e
411 }
412
413 if (vc4_encoder->hdmi_monitor) {
414 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
415 +
416 WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
417 VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
418 HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
419 @@ -1073,6 +1173,8 @@ static void vc4_hdmi_encoder_post_crtc_e
420 HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
421 VC4_HDMI_RAM_PACKET_ENABLE);
422
423 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
424 +
425 vc4_hdmi_set_infoframes(encoder);
426 }
427
428 @@ -1196,6 +1298,7 @@ static void vc4_hdmi_audio_set_mai_clock
429 unsigned int samplerate)
430 {
431 u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock);
432 + unsigned long flags;
433 unsigned long n, m;
434
435 rational_best_approximation(hsm_clock, samplerate,
436 @@ -1205,9 +1308,11 @@ static void vc4_hdmi_audio_set_mai_clock
437 VC4_HD_MAI_SMP_M_SHIFT) + 1,
438 &n, &m);
439
440 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
441 HDMI_WRITE(HDMI_MAI_SMP,
442 VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
443 VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
444 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
445 }
446
447 static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate)
448 @@ -1218,6 +1323,8 @@ static void vc4_hdmi_set_n_cts(struct vc
449 u32 n, cts;
450 u64 tmp;
451
452 + lockdep_assert_held(&vc4_hdmi->hw_lock);
453 +
454 n = 128 * samplerate / 1000;
455 tmp = (u64)(mode->clock * 1000) * n;
456 do_div(tmp, 128 * samplerate);
457 @@ -1247,6 +1354,7 @@ static int vc4_hdmi_audio_startup(struct
458 {
459 struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
460 struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
461 + unsigned long flags;
462
463 /*
464 * If the HDMI encoder hasn't probed, or the encoder is
465 @@ -1258,12 +1366,14 @@ static int vc4_hdmi_audio_startup(struct
466
467 vc4_hdmi->audio.streaming = true;
468
469 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
470 HDMI_WRITE(HDMI_MAI_CTL,
471 VC4_HD_MAI_CTL_RESET |
472 VC4_HD_MAI_CTL_FLUSH |
473 VC4_HD_MAI_CTL_DLATE |
474 VC4_HD_MAI_CTL_ERRORE |
475 VC4_HD_MAI_CTL_ERRORF);
476 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
477
478 if (vc4_hdmi->variant->phy_rng_enable)
479 vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
480 @@ -1275,6 +1385,7 @@ static void vc4_hdmi_audio_reset(struct
481 {
482 struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
483 struct device *dev = &vc4_hdmi->pdev->dev;
484 + unsigned long flags;
485 int ret;
486
487 vc4_hdmi->audio.streaming = false;
488 @@ -1282,20 +1393,29 @@ static void vc4_hdmi_audio_reset(struct
489 if (ret)
490 dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
491
492 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
493 +
494 HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_RESET);
495 HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
496 HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
497 +
498 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
499 }
500
501 static void vc4_hdmi_audio_shutdown(struct device *dev, void *data)
502 {
503 struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
504 + unsigned long flags;
505 +
506 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
507
508 HDMI_WRITE(HDMI_MAI_CTL,
509 VC4_HD_MAI_CTL_DLATE |
510 VC4_HD_MAI_CTL_ERRORE |
511 VC4_HD_MAI_CTL_ERRORF);
512
513 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
514 +
515 if (vc4_hdmi->variant->phy_rng_disable)
516 vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
517
518 @@ -1350,6 +1470,7 @@ static int vc4_hdmi_audio_prepare(struct
519 struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
520 unsigned int sample_rate = params->sample_rate;
521 unsigned int channels = params->channels;
522 + unsigned long flags;
523 u32 audio_packet_config, channel_mask;
524 u32 channel_map;
525 u32 mai_audio_format;
526 @@ -1358,14 +1479,15 @@ static int vc4_hdmi_audio_prepare(struct
527 dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
528 sample_rate, params->sample_width, channels);
529
530 + vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate);
531 +
532 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
533 HDMI_WRITE(HDMI_MAI_CTL,
534 VC4_SET_FIELD(channels, VC4_HD_MAI_CTL_CHNUM) |
535 VC4_HD_MAI_CTL_WHOLSMP |
536 VC4_HD_MAI_CTL_CHALIGN |
537 VC4_HD_MAI_CTL_ENABLE);
538
539 - vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate);
540 -
541 mai_sample_rate = sample_rate_to_mai_fmt(sample_rate);
542 if (params->iec.status[0] & IEC958_AES0_NONAUDIO &&
543 params->channels == 8)
544 @@ -1403,8 +1525,11 @@ static int vc4_hdmi_audio_prepare(struct
545 channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask);
546 HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
547 HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
548 +
549 vc4_hdmi_set_n_cts(vc4_hdmi, sample_rate);
550
551 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
552 +
553 memcpy(&vc4_hdmi->audio.infoframe, &params->cea, sizeof(params->cea));
554 vc4_hdmi_set_audio_infoframe(encoder);
555
556 @@ -1678,6 +1803,8 @@ static void vc4_cec_read_msg(struct vc4_
557 struct cec_msg *msg = &vc4_hdmi->cec_rx_msg;
558 unsigned int i;
559
560 + lockdep_assert_held(&vc4_hdmi->hw_lock);
561 +
562 msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
563 VC4_HDMI_CEC_REC_WRD_CNT_SHIFT);
564
565 @@ -1696,11 +1823,12 @@ static void vc4_cec_read_msg(struct vc4_
566 }
567 }
568
569 -static irqreturn_t vc4_cec_irq_handler_tx_bare(int irq, void *priv)
570 +static irqreturn_t vc4_cec_irq_handler_tx_bare_locked(struct vc4_hdmi *vc4_hdmi)
571 {
572 - struct vc4_hdmi *vc4_hdmi = priv;
573 u32 cntrl1;
574
575 + lockdep_assert_held(&vc4_hdmi->hw_lock);
576 +
577 cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
578 vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
579 cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
580 @@ -1709,11 +1837,24 @@ static irqreturn_t vc4_cec_irq_handler_t
581 return IRQ_WAKE_THREAD;
582 }
583
584 -static irqreturn_t vc4_cec_irq_handler_rx_bare(int irq, void *priv)
585 +static irqreturn_t vc4_cec_irq_handler_tx_bare(int irq, void *priv)
586 {
587 struct vc4_hdmi *vc4_hdmi = priv;
588 + irqreturn_t ret;
589 +
590 + spin_lock(&vc4_hdmi->hw_lock);
591 + ret = vc4_cec_irq_handler_tx_bare_locked(vc4_hdmi);
592 + spin_unlock(&vc4_hdmi->hw_lock);
593 +
594 + return ret;
595 +}
596 +
597 +static irqreturn_t vc4_cec_irq_handler_rx_bare_locked(struct vc4_hdmi *vc4_hdmi)
598 +{
599 u32 cntrl1;
600
601 + lockdep_assert_held(&vc4_hdmi->hw_lock);
602 +
603 vc4_hdmi->cec_rx_msg.len = 0;
604 cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
605 vc4_cec_read_msg(vc4_hdmi, cntrl1);
606 @@ -1726,6 +1867,18 @@ static irqreturn_t vc4_cec_irq_handler_r
607 return IRQ_WAKE_THREAD;
608 }
609
610 +static irqreturn_t vc4_cec_irq_handler_rx_bare(int irq, void *priv)
611 +{
612 + struct vc4_hdmi *vc4_hdmi = priv;
613 + irqreturn_t ret;
614 +
615 + spin_lock(&vc4_hdmi->hw_lock);
616 + ret = vc4_cec_irq_handler_rx_bare_locked(vc4_hdmi);
617 + spin_unlock(&vc4_hdmi->hw_lock);
618 +
619 + return ret;
620 +}
621 +
622 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
623 {
624 struct vc4_hdmi *vc4_hdmi = priv;
625 @@ -1736,14 +1889,17 @@ static irqreturn_t vc4_cec_irq_handler(i
626 if (!(stat & VC4_HDMI_CPU_CEC))
627 return IRQ_NONE;
628
629 + spin_lock(&vc4_hdmi->hw_lock);
630 cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5);
631 vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
632 if (vc4_hdmi->cec_irq_was_rx)
633 - ret = vc4_cec_irq_handler_rx_bare(irq, priv);
634 + ret = vc4_cec_irq_handler_rx_bare_locked(vc4_hdmi);
635 else
636 - ret = vc4_cec_irq_handler_tx_bare(irq, priv);
637 + ret = vc4_cec_irq_handler_tx_bare_locked(vc4_hdmi);
638
639 HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC);
640 + spin_unlock(&vc4_hdmi->hw_lock);
641 +
642 return ret;
643 }
644
645 @@ -1752,6 +1908,7 @@ static int vc4_hdmi_cec_enable(struct ce
646 struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
647 /* clock period in microseconds */
648 const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
649 + unsigned long flags;
650 u32 val;
651 int ret;
652
653 @@ -1759,6 +1916,8 @@ static int vc4_hdmi_cec_enable(struct ce
654 if (ret)
655 return ret;
656
657 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
658 +
659 val = HDMI_READ(HDMI_CEC_CNTRL_5);
660 val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET |
661 VC4_HDMI_CEC_CNT_TO_4700_US_MASK |
662 @@ -1789,12 +1948,17 @@ static int vc4_hdmi_cec_enable(struct ce
663 if (!vc4_hdmi->variant->external_irq_controller)
664 HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
665
666 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
667 +
668 return 0;
669 }
670
671 static int vc4_hdmi_cec_disable(struct cec_adapter *adap)
672 {
673 struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
674 + unsigned long flags;
675 +
676 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
677
678 if (!vc4_hdmi->variant->external_irq_controller)
679 HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
680 @@ -1802,6 +1966,8 @@ static int vc4_hdmi_cec_disable(struct c
681 HDMI_WRITE(HDMI_CEC_CNTRL_5, HDMI_READ(HDMI_CEC_CNTRL_5) |
682 VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
683
684 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
685 +
686 pm_runtime_put(&vc4_hdmi->pdev->dev);
687
688 return 0;
689 @@ -1818,10 +1984,14 @@ static int vc4_hdmi_cec_adap_enable(stru
690 static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
691 {
692 struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
693 + unsigned long flags;
694
695 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
696 HDMI_WRITE(HDMI_CEC_CNTRL_1,
697 (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
698 (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT);
699 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
700 +
701 return 0;
702 }
703
704 @@ -1830,6 +2000,7 @@ static int vc4_hdmi_cec_adap_transmit(st
705 {
706 struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
707 struct drm_device *dev = vc4_hdmi->connector.dev;
708 + unsigned long flags;
709 u32 val;
710 unsigned int i;
711
712 @@ -1838,6 +2009,8 @@ static int vc4_hdmi_cec_adap_transmit(st
713 return -ENOMEM;
714 }
715
716 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
717 +
718 for (i = 0; i < msg->len; i += 4)
719 HDMI_WRITE(HDMI_CEC_TX_DATA_1 + (i >> 2),
720 (msg->msg[i]) |
721 @@ -1853,6 +2026,9 @@ static int vc4_hdmi_cec_adap_transmit(st
722 val |= VC4_HDMI_CEC_START_XMIT_BEGIN;
723
724 HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
725 +
726 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
727 +
728 return 0;
729 }
730
731 @@ -1867,6 +2043,7 @@ static int vc4_hdmi_cec_init(struct vc4_
732 struct cec_connector_info conn_info;
733 struct platform_device *pdev = vc4_hdmi->pdev;
734 struct device *dev = &pdev->dev;
735 + unsigned long flags;
736 u32 value;
737 int ret;
738
739 @@ -1887,10 +2064,12 @@ static int vc4_hdmi_cec_init(struct vc4_
740 cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
741 cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
742
743 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
744 value = HDMI_READ(HDMI_CEC_CNTRL_1);
745 /* Set the logical address to Unregistered */
746 value |= VC4_HDMI_CEC_ADDR_MASK;
747 HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
748 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
749
750 vc4_hdmi_cec_update_clk_div(vc4_hdmi);
751
752 @@ -1909,7 +2088,9 @@ static int vc4_hdmi_cec_init(struct vc4_
753 if (ret)
754 goto err_remove_cec_rx_handler;
755 } else {
756 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
757 HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
758 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
759
760 ret = request_threaded_irq(platform_get_irq(pdev, 0),
761 vc4_cec_irq_handler,
762 @@ -2179,6 +2360,7 @@ static int vc4_hdmi_bind(struct device *
763 vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
764 if (!vc4_hdmi)
765 return -ENOMEM;
766 + spin_lock_init(&vc4_hdmi->hw_lock);
767 INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq);
768
769 dev_set_drvdata(dev, vc4_hdmi);
770 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
771 +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
772 @@ -179,6 +179,11 @@ struct vc4_hdmi {
773
774 struct debugfs_regset32 hdmi_regset;
775 struct debugfs_regset32 hd_regset;
776 +
777 + /**
778 + * @hw_lock: Spinlock protecting device register access.
779 + */
780 + spinlock_t hw_lock;
781 };
782
783 static inline struct vc4_hdmi *
784 --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
785 +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
786 @@ -130,31 +130,49 @@
787 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
788 struct vc4_hdmi_connector_state *conn_state)
789 {
790 + unsigned long flags;
791 +
792 /* PHY should be in reset, like
793 * vc4_hdmi_encoder_disable() does.
794 */
795
796 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
797 +
798 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
799 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
800 +
801 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
802 }
803
804 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
805 {
806 + unsigned long flags;
807 +
808 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
809 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
810 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
811 }
812
813 void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
814 {
815 + unsigned long flags;
816 +
817 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
818 HDMI_WRITE(HDMI_TX_PHY_CTL_0,
819 HDMI_READ(HDMI_TX_PHY_CTL_0) &
820 ~VC4_HDMI_TX_PHY_RNG_PWRDN);
821 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
822 }
823
824 void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
825 {
826 + unsigned long flags;
827 +
828 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
829 HDMI_WRITE(HDMI_TX_PHY_CTL_0,
830 HDMI_READ(HDMI_TX_PHY_CTL_0) |
831 VC4_HDMI_TX_PHY_RNG_PWRDN);
832 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
833 }
834
835 static unsigned long long
836 @@ -336,6 +354,8 @@ phy_get_channel_settings(enum vc4_hdmi_p
837
838 static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
839 {
840 + lockdep_assert_held(&vc4_hdmi->hw_lock);
841 +
842 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f);
843 HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
844 }
845 @@ -348,10 +368,13 @@ void vc5_hdmi_phy_init(struct vc4_hdmi *
846 unsigned long long pixel_freq = conn_state->pixel_rate;
847 unsigned long long vco_freq;
848 unsigned char word_sel;
849 + unsigned long flags;
850 u8 vco_sel, vco_div;
851
852 vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div);
853
854 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
855 +
856 vc5_hdmi_reset_phy(vc4_hdmi);
857
858 HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
859 @@ -501,23 +524,37 @@ void vc5_hdmi_phy_init(struct vc4_hdmi *
860 HDMI_READ(HDMI_TX_PHY_RESET_CTL) |
861 VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
862 VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB);
863 +
864 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
865 }
866
867 void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
868 {
869 + unsigned long flags;
870 +
871 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
872 vc5_hdmi_reset_phy(vc4_hdmi);
873 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
874 }
875
876 void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
877 {
878 + unsigned long flags;
879 +
880 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
881 HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
882 HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) &
883 ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
884 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
885 }
886
887 void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
888 {
889 + unsigned long flags;
890 +
891 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
892 HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
893 HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) |
894 VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
895 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
896 }
897 --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
898 +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
899 @@ -445,6 +445,8 @@ static inline void vc4_hdmi_write(struct
900 const struct vc4_hdmi_variant *variant = hdmi->variant;
901 void __iomem *base;
902
903 + lockdep_assert_held(&hdmi->hw_lock);
904 +
905 WARN_ON(!pm_runtime_active(&hdmi->pdev->dev));
906
907 if (reg >= variant->num_registers) {