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
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.
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
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>
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(-)
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
30 static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
32 + unsigned long flags;
34 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
36 HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
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);
42 HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
44 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
47 static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
49 + unsigned long flags;
51 reset_control_reset(vc4_hdmi->reset);
53 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
55 HDMI_WRITE(HDMI_DVP_CTL, 0);
57 HDMI_WRITE(HDMI_CLOCK_STOP,
58 HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL);
60 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
63 #ifdef CONFIG_DRM_VC4_HDMI_CEC
64 static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi)
66 + unsigned long cec_rate = clk_get_rate(vc4_hdmi->cec_clock);
67 + unsigned long flags;
71 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
73 value = HDMI_READ(HDMI_CEC_CNTRL_1);
74 value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
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.
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);
85 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
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))
93 - } else if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) {
96 + unsigned long flags;
99 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
100 + hotplug = HDMI_READ(HDMI_HOTPLUG);
101 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
103 + if (hotplug & VC4_HDMI_HOTPLUG_CONNECTED)
108 @@ -374,9 +400,12 @@ static int vc4_hdmi_stop_packet(struct d
110 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
111 u32 packet_id = type - 0x80;
112 + unsigned long flags;
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);
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;
129 @@ -413,6 +443,8 @@ static void vc4_hdmi_write_infoframe(str
133 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
135 for (i = 0; i < len; i += 7) {
136 writel(buffer[i + 0] << 0 |
138 @@ -430,6 +462,9 @@ static void vc4_hdmi_write_infoframe(str
140 HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
141 HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
143 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
145 ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) &
146 BIT(packet_id)), 100);
148 @@ -549,6 +584,7 @@ static void vc4_hdmi_enable_scrambling(s
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;
154 if (!vc4_hdmi_supports_scrambling(encoder, mode))
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);
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);
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(
169 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
170 struct drm_crtc *crtc = encoder->crtc;
171 + unsigned long flags;
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);
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);
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)
189 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
190 + unsigned long flags;
192 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
194 HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
196 HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_CLRRGB);
198 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
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);
207 vc4_hdmi_disable_scrambling(encoder);
210 @@ -628,10 +677,13 @@ static void vc4_hdmi_encoder_post_crtc_p
211 struct drm_atomic_state *state)
213 struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
214 + unsigned long flags;
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);
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
226 static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
228 + unsigned long flags;
231 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
233 csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
234 VC4_HD_CSC_CTL_ORDER);
236 @@ -681,14 +736,19 @@ static void vc4_hdmi_csc_setup(struct vc
238 /* The RGB order applies even when CSC is disabled. */
239 HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
241 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
244 static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
246 + unsigned long flags;
249 csc_ctl = 0x07; /* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */
251 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
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
259 HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
261 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
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;
271 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
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
277 HDMI_WRITE(HDMI_VERTB0, vertb_even);
278 HDMI_WRITE(HDMI_VERTB1, vertb);
280 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
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;
293 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
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);
301 HDMI_WRITE(HDMI_CLOCK_STOP, 0);
303 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
306 static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
308 + unsigned long flags;
312 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
314 drift = HDMI_READ(HDMI_FIFO_CTL);
315 drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
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);
322 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
324 usleep_range(1000, 1100);
326 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
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);
333 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
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;
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);
350 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
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);
357 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
359 if (vc4_hdmi->variant->set_timings)
360 vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode);
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;
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;
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);
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;
387 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
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);
396 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
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);
405 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
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
413 if (vc4_encoder->hdmi_monitor) {
414 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
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);
423 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
425 vc4_hdmi_set_infoframes(encoder);
428 @@ -1196,6 +1298,7 @@ static void vc4_hdmi_audio_set_mai_clock
429 unsigned int samplerate)
431 u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock);
432 + unsigned long flags;
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,
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);
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
452 + lockdep_assert_held(&vc4_hdmi->hw_lock);
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
459 struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
460 struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
461 + unsigned long flags;
464 * If the HDMI encoder hasn't probed, or the encoder is
465 @@ -1258,12 +1366,14 @@ static int vc4_hdmi_audio_startup(struct
467 vc4_hdmi->audio.streaming = true;
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);
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
482 struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
483 struct device *dev = &vc4_hdmi->pdev->dev;
484 + unsigned long flags;
487 vc4_hdmi->audio.streaming = false;
488 @@ -1282,20 +1393,29 @@ static void vc4_hdmi_audio_reset(struct
490 dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
492 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
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);
498 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
501 static void vc4_hdmi_audio_shutdown(struct device *dev, void *data)
503 struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
504 + unsigned long flags;
506 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
508 HDMI_WRITE(HDMI_MAI_CTL,
509 VC4_HD_MAI_CTL_DLATE |
510 VC4_HD_MAI_CTL_ERRORE |
511 VC4_HD_MAI_CTL_ERRORF);
513 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
515 if (vc4_hdmi->variant->phy_rng_disable)
516 vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
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;
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);
530 + vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate);
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);
539 - vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate);
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);
549 vc4_hdmi_set_n_cts(vc4_hdmi, sample_rate);
551 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
553 memcpy(&vc4_hdmi->audio.infoframe, ¶ms->cea, sizeof(params->cea));
554 vc4_hdmi_set_audio_infoframe(encoder);
556 @@ -1678,6 +1803,8 @@ static void vc4_cec_read_msg(struct vc4_
557 struct cec_msg *msg = &vc4_hdmi->cec_rx_msg;
560 + lockdep_assert_held(&vc4_hdmi->hw_lock);
562 msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
563 VC4_HDMI_CEC_REC_WRD_CNT_SHIFT);
565 @@ -1696,11 +1823,12 @@ static void vc4_cec_read_msg(struct vc4_
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)
572 - struct vc4_hdmi *vc4_hdmi = priv;
575 + lockdep_assert_held(&vc4_hdmi->hw_lock);
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;
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)
587 struct vc4_hdmi *vc4_hdmi = priv;
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);
597 +static irqreturn_t vc4_cec_irq_handler_rx_bare_locked(struct vc4_hdmi *vc4_hdmi)
601 + lockdep_assert_held(&vc4_hdmi->hw_lock);
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;
610 +static irqreturn_t vc4_cec_irq_handler_rx_bare(int irq, void *priv)
612 + struct vc4_hdmi *vc4_hdmi = priv;
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);
622 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
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))
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);
636 - ret = vc4_cec_irq_handler_tx_bare(irq, priv);
637 + ret = vc4_cec_irq_handler_tx_bare_locked(vc4_hdmi);
639 HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC);
640 + spin_unlock(&vc4_hdmi->hw_lock);
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;
653 @@ -1759,6 +1916,8 @@ static int vc4_hdmi_cec_enable(struct ce
657 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
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);
666 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
671 static int vc4_hdmi_cec_disable(struct cec_adapter *adap)
673 struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
674 + unsigned long flags;
676 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
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);
684 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
686 pm_runtime_put(&vc4_hdmi->pdev->dev);
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)
692 struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
693 + unsigned long flags;
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);
704 @@ -1830,6 +2000,7 @@ static int vc4_hdmi_cec_adap_transmit(st
706 struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
707 struct drm_device *dev = vc4_hdmi->connector.dev;
708 + unsigned long flags;
712 @@ -1838,6 +2009,8 @@ static int vc4_hdmi_cec_adap_transmit(st
716 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
718 for (i = 0; i < msg->len; i += 4)
719 HDMI_WRITE(HDMI_CEC_TX_DATA_1 + (i >> 2),
721 @@ -1853,6 +2026,9 @@ static int vc4_hdmi_cec_adap_transmit(st
722 val |= VC4_HDMI_CEC_START_XMIT_BEGIN;
724 HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
726 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
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;
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);
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);
750 vc4_hdmi_cec_update_clk_div(vc4_hdmi);
752 @@ -1909,7 +2088,9 @@ static int vc4_hdmi_cec_init(struct vc4_
754 goto err_remove_cec_rx_handler;
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);
760 ret = request_threaded_irq(platform_get_irq(pdev, 0),
762 @@ -2179,6 +2360,7 @@ static int vc4_hdmi_bind(struct device *
763 vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
766 + spin_lock_init(&vc4_hdmi->hw_lock);
767 INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq);
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 {
774 struct debugfs_regset32 hdmi_regset;
775 struct debugfs_regset32 hd_regset;
778 + * @hw_lock: Spinlock protecting device register access.
780 + spinlock_t hw_lock;
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)
790 + unsigned long flags;
792 /* PHY should be in reset, like
793 * vc4_hdmi_encoder_disable() does.
796 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
798 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
799 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
801 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
804 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
806 + unsigned long flags;
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);
813 void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
815 + unsigned long flags;
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);
824 void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
826 + unsigned long flags;
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);
835 static unsigned long long
836 @@ -336,6 +354,8 @@ phy_get_channel_settings(enum vc4_hdmi_p
838 static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
840 + lockdep_assert_held(&vc4_hdmi->hw_lock);
842 HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f);
843 HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
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;
852 vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div);
854 + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
856 vc5_hdmi_reset_phy(vc4_hdmi);
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);
864 + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
867 void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
869 + unsigned long flags;
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);
876 void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
878 + unsigned long flags;
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);
887 void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
889 + unsigned long flags;
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);
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;
903 + lockdep_assert_held(&hdmi->hw_lock);
905 WARN_ON(!pm_runtime_active(&hdmi->pdev->dev));
907 if (reg >= variant->num_registers) {