950-0007-drm-vc4-hdmi-Add-a-spinlock-to-protect-register-acce.patch 28 KB

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