vc4_hvs.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2015 Broadcom
  4. */
  5. /**
  6. * DOC: VC4 HVS module.
  7. *
  8. * The Hardware Video Scaler (HVS) is the piece of hardware that does
  9. * translation, scaling, colorspace conversion, and compositing of
  10. * pixels stored in framebuffers into a FIFO of pixels going out to
  11. * the Pixel Valve (CRTC). It operates at the system clock rate (the
  12. * system audio clock gate, specifically), which is much higher than
  13. * the pixel clock rate.
  14. *
  15. * There is a single global HVS, with multiple output FIFOs that can
  16. * be consumed by the PVs. This file just manages the resources for
  17. * the HVS, while the vc4_crtc.c code actually drives HVS setup for
  18. * each CRTC.
  19. */
  20. #include <linux/bitfield.h>
  21. #include <linux/clk.h>
  22. #include <linux/component.h>
  23. #include <linux/platform_device.h>
  24. #include <drm/drm_atomic_helper.h>
  25. #include <drm/drm_drv.h>
  26. #include <drm/drm_vblank.h>
  27. #include <soc/bcm2835/raspberrypi-firmware.h>
  28. #include "vc4_drv.h"
  29. #include "vc4_regs.h"
  30. static const struct debugfs_reg32 hvs_regs[] = {
  31. VC4_REG32(SCALER_DISPCTRL),
  32. VC4_REG32(SCALER_DISPSTAT),
  33. VC4_REG32(SCALER_DISPID),
  34. VC4_REG32(SCALER_DISPECTRL),
  35. VC4_REG32(SCALER_DISPPROF),
  36. VC4_REG32(SCALER_DISPDITHER),
  37. VC4_REG32(SCALER_DISPEOLN),
  38. VC4_REG32(SCALER_DISPLIST0),
  39. VC4_REG32(SCALER_DISPLIST1),
  40. VC4_REG32(SCALER_DISPLIST2),
  41. VC4_REG32(SCALER_DISPLSTAT),
  42. VC4_REG32(SCALER_DISPLACT0),
  43. VC4_REG32(SCALER_DISPLACT1),
  44. VC4_REG32(SCALER_DISPLACT2),
  45. VC4_REG32(SCALER_DISPCTRL0),
  46. VC4_REG32(SCALER_DISPBKGND0),
  47. VC4_REG32(SCALER_DISPSTAT0),
  48. VC4_REG32(SCALER_DISPBASE0),
  49. VC4_REG32(SCALER_DISPCTRL1),
  50. VC4_REG32(SCALER_DISPBKGND1),
  51. VC4_REG32(SCALER_DISPSTAT1),
  52. VC4_REG32(SCALER_DISPBASE1),
  53. VC4_REG32(SCALER_DISPCTRL2),
  54. VC4_REG32(SCALER_DISPBKGND2),
  55. VC4_REG32(SCALER_DISPSTAT2),
  56. VC4_REG32(SCALER_DISPBASE2),
  57. VC4_REG32(SCALER_DISPALPHA2),
  58. VC4_REG32(SCALER_OLEDOFFS),
  59. VC4_REG32(SCALER_OLEDCOEF0),
  60. VC4_REG32(SCALER_OLEDCOEF1),
  61. VC4_REG32(SCALER_OLEDCOEF2),
  62. };
  63. void vc4_hvs_dump_state(struct vc4_hvs *hvs)
  64. {
  65. struct drm_device *drm = &hvs->vc4->base;
  66. struct drm_printer p = drm_info_printer(&hvs->pdev->dev);
  67. int idx, i;
  68. if (!drm_dev_enter(drm, &idx))
  69. return;
  70. drm_print_regset32(&p, &hvs->regset);
  71. DRM_INFO("HVS ctx:\n");
  72. for (i = 0; i < 64; i += 4) {
  73. DRM_INFO("0x%08x (%s): 0x%08x 0x%08x 0x%08x 0x%08x\n",
  74. i * 4, i < HVS_BOOTLOADER_DLIST_END ? "B" : "D",
  75. readl((u32 __iomem *)hvs->dlist + i + 0),
  76. readl((u32 __iomem *)hvs->dlist + i + 1),
  77. readl((u32 __iomem *)hvs->dlist + i + 2),
  78. readl((u32 __iomem *)hvs->dlist + i + 3));
  79. }
  80. drm_dev_exit(idx);
  81. }
  82. static int vc4_hvs_debugfs_underrun(struct seq_file *m, void *data)
  83. {
  84. struct drm_debugfs_entry *entry = m->private;
  85. struct drm_device *dev = entry->dev;
  86. struct vc4_dev *vc4 = to_vc4_dev(dev);
  87. struct drm_printer p = drm_seq_file_printer(m);
  88. drm_printf(&p, "%d\n", atomic_read(&vc4->underrun));
  89. return 0;
  90. }
  91. static int vc4_hvs_debugfs_dlist(struct seq_file *m, void *data)
  92. {
  93. struct drm_debugfs_entry *entry = m->private;
  94. struct drm_device *dev = entry->dev;
  95. struct vc4_dev *vc4 = to_vc4_dev(dev);
  96. struct vc4_hvs *hvs = vc4->hvs;
  97. struct drm_printer p = drm_seq_file_printer(m);
  98. unsigned int dlist_mem_size = hvs->dlist_mem_size;
  99. unsigned int next_entry_start;
  100. unsigned int i, j;
  101. u32 dlist_word, dispstat;
  102. for (i = 0; i < SCALER_CHANNELS_COUNT; i++) {
  103. dispstat = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(i)),
  104. SCALER_DISPSTATX_MODE);
  105. if (dispstat == SCALER_DISPSTATX_MODE_DISABLED ||
  106. dispstat == SCALER_DISPSTATX_MODE_EOF) {
  107. drm_printf(&p, "HVS chan %u disabled\n", i);
  108. continue;
  109. }
  110. drm_printf(&p, "HVS chan %u:\n", i);
  111. next_entry_start = 0;
  112. for (j = HVS_READ(SCALER_DISPLISTX(i)); j < dlist_mem_size; j++) {
  113. dlist_word = readl((u32 __iomem *)vc4->hvs->dlist + j);
  114. drm_printf(&p, "dlist: %02d: 0x%08x\n", j,
  115. dlist_word);
  116. if (!next_entry_start ||
  117. next_entry_start == j) {
  118. if (dlist_word & SCALER_CTL0_END)
  119. break;
  120. next_entry_start = j +
  121. VC4_GET_FIELD(dlist_word,
  122. SCALER_CTL0_SIZE);
  123. }
  124. }
  125. }
  126. return 0;
  127. }
  128. /* The filter kernel is composed of dwords each containing 3 9-bit
  129. * signed integers packed next to each other.
  130. */
  131. #define VC4_INT_TO_COEFF(coeff) (coeff & 0x1ff)
  132. #define VC4_PPF_FILTER_WORD(c0, c1, c2) \
  133. ((((c0) & 0x1ff) << 0) | \
  134. (((c1) & 0x1ff) << 9) | \
  135. (((c2) & 0x1ff) << 18))
  136. /* The whole filter kernel is arranged as the coefficients 0-16 going
  137. * up, then a pad, then 17-31 going down and reversed within the
  138. * dwords. This means that a linear phase kernel (where it's
  139. * symmetrical at the boundary between 15 and 16) has the last 5
  140. * dwords matching the first 5, but reversed.
  141. */
  142. #define VC4_LINEAR_PHASE_KERNEL(c0, c1, c2, c3, c4, c5, c6, c7, c8, \
  143. c9, c10, c11, c12, c13, c14, c15) \
  144. {VC4_PPF_FILTER_WORD(c0, c1, c2), \
  145. VC4_PPF_FILTER_WORD(c3, c4, c5), \
  146. VC4_PPF_FILTER_WORD(c6, c7, c8), \
  147. VC4_PPF_FILTER_WORD(c9, c10, c11), \
  148. VC4_PPF_FILTER_WORD(c12, c13, c14), \
  149. VC4_PPF_FILTER_WORD(c15, c15, 0)}
  150. #define VC4_LINEAR_PHASE_KERNEL_DWORDS 6
  151. #define VC4_KERNEL_DWORDS (VC4_LINEAR_PHASE_KERNEL_DWORDS * 2 - 1)
  152. /* Recommended B=1/3, C=1/3 filter choice from Mitchell/Netravali.
  153. * http://www.cs.utexas.edu/~fussell/courses/cs384g/lectures/mitchell/Mitchell.pdf
  154. */
  155. static const u32 mitchell_netravali_1_3_1_3_kernel[] =
  156. VC4_LINEAR_PHASE_KERNEL(0, -2, -6, -8, -10, -8, -3, 2, 18,
  157. 50, 82, 119, 155, 187, 213, 227);
  158. static int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs,
  159. struct drm_mm_node *space,
  160. const u32 *kernel)
  161. {
  162. int ret, i;
  163. u32 __iomem *dst_kernel;
  164. /*
  165. * NOTE: We don't need a call to drm_dev_enter()/drm_dev_exit()
  166. * here since that function is only called from vc4_hvs_bind().
  167. */
  168. ret = drm_mm_insert_node(&hvs->dlist_mm, space, VC4_KERNEL_DWORDS);
  169. if (ret) {
  170. drm_err(&hvs->vc4->base, "Failed to allocate space for filter kernel: %d\n",
  171. ret);
  172. return ret;
  173. }
  174. dst_kernel = hvs->dlist + space->start;
  175. for (i = 0; i < VC4_KERNEL_DWORDS; i++) {
  176. if (i < VC4_LINEAR_PHASE_KERNEL_DWORDS)
  177. writel(kernel[i], &dst_kernel[i]);
  178. else {
  179. writel(kernel[VC4_KERNEL_DWORDS - i - 1],
  180. &dst_kernel[i]);
  181. }
  182. }
  183. return 0;
  184. }
  185. static void vc4_hvs_lut_load(struct vc4_hvs *hvs,
  186. struct vc4_crtc *vc4_crtc)
  187. {
  188. struct drm_device *drm = &hvs->vc4->base;
  189. struct drm_crtc *crtc = &vc4_crtc->base;
  190. struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
  191. int idx;
  192. u32 i;
  193. if (!drm_dev_enter(drm, &idx))
  194. return;
  195. if (hvs->vc4->gen != VC4_GEN_4)
  196. goto exit;
  197. /* The LUT memory is laid out with each HVS channel in order,
  198. * each of which takes 256 writes for R, 256 for G, then 256
  199. * for B.
  200. */
  201. HVS_WRITE(SCALER_GAMADDR,
  202. SCALER_GAMADDR_AUTOINC |
  203. (vc4_state->assigned_channel * 3 * crtc->gamma_size));
  204. for (i = 0; i < crtc->gamma_size; i++)
  205. HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
  206. for (i = 0; i < crtc->gamma_size; i++)
  207. HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_g[i]);
  208. for (i = 0; i < crtc->gamma_size; i++)
  209. HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_b[i]);
  210. exit:
  211. drm_dev_exit(idx);
  212. }
  213. static void vc4_hvs_update_gamma_lut(struct vc4_hvs *hvs,
  214. struct vc4_crtc *vc4_crtc)
  215. {
  216. struct drm_crtc_state *crtc_state = vc4_crtc->base.state;
  217. struct drm_color_lut *lut = crtc_state->gamma_lut->data;
  218. u32 length = drm_color_lut_size(crtc_state->gamma_lut);
  219. u32 i;
  220. for (i = 0; i < length; i++) {
  221. vc4_crtc->lut_r[i] = drm_color_lut_extract(lut[i].red, 8);
  222. vc4_crtc->lut_g[i] = drm_color_lut_extract(lut[i].green, 8);
  223. vc4_crtc->lut_b[i] = drm_color_lut_extract(lut[i].blue, 8);
  224. }
  225. vc4_hvs_lut_load(hvs, vc4_crtc);
  226. }
  227. u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo)
  228. {
  229. struct drm_device *drm = &hvs->vc4->base;
  230. u8 field = 0;
  231. int idx;
  232. if (!drm_dev_enter(drm, &idx))
  233. return 0;
  234. switch (fifo) {
  235. case 0:
  236. field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1),
  237. SCALER_DISPSTAT1_FRCNT0);
  238. break;
  239. case 1:
  240. field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1),
  241. SCALER_DISPSTAT1_FRCNT1);
  242. break;
  243. case 2:
  244. field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT2),
  245. SCALER_DISPSTAT2_FRCNT2);
  246. break;
  247. }
  248. drm_dev_exit(idx);
  249. return field;
  250. }
  251. int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output)
  252. {
  253. struct vc4_dev *vc4 = hvs->vc4;
  254. u32 reg;
  255. int ret;
  256. if (vc4->gen == VC4_GEN_4)
  257. return output;
  258. /*
  259. * NOTE: We should probably use drm_dev_enter()/drm_dev_exit()
  260. * here, but this function is only used during the DRM device
  261. * initialization, so we should be fine.
  262. */
  263. switch (output) {
  264. case 0:
  265. return 0;
  266. case 1:
  267. return 1;
  268. case 2:
  269. reg = HVS_READ(SCALER_DISPECTRL);
  270. ret = FIELD_GET(SCALER_DISPECTRL_DSP2_MUX_MASK, reg);
  271. if (ret == 0)
  272. return 2;
  273. return 0;
  274. case 3:
  275. reg = HVS_READ(SCALER_DISPCTRL);
  276. ret = FIELD_GET(SCALER_DISPCTRL_DSP3_MUX_MASK, reg);
  277. if (ret == 3)
  278. return -EPIPE;
  279. return ret;
  280. case 4:
  281. reg = HVS_READ(SCALER_DISPEOLN);
  282. ret = FIELD_GET(SCALER_DISPEOLN_DSP4_MUX_MASK, reg);
  283. if (ret == 3)
  284. return -EPIPE;
  285. return ret;
  286. case 5:
  287. reg = HVS_READ(SCALER_DISPDITHER);
  288. ret = FIELD_GET(SCALER_DISPDITHER_DSP5_MUX_MASK, reg);
  289. if (ret == 3)
  290. return -EPIPE;
  291. return ret;
  292. default:
  293. return -EPIPE;
  294. }
  295. }
  296. static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc,
  297. struct drm_display_mode *mode, bool oneshot)
  298. {
  299. struct vc4_dev *vc4 = hvs->vc4;
  300. struct drm_device *drm = &vc4->base;
  301. struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
  302. struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
  303. unsigned int chan = vc4_crtc_state->assigned_channel;
  304. bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
  305. u32 dispbkgndx;
  306. u32 dispctrl;
  307. int idx;
  308. if (!drm_dev_enter(drm, &idx))
  309. return -ENODEV;
  310. HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
  311. HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET);
  312. HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
  313. /* Turn on the scaler, which will wait for vstart to start
  314. * compositing.
  315. * When feeding the transposer, we should operate in oneshot
  316. * mode.
  317. */
  318. dispctrl = SCALER_DISPCTRLX_ENABLE;
  319. dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
  320. if (vc4->gen == VC4_GEN_4) {
  321. dispctrl |= VC4_SET_FIELD(mode->hdisplay,
  322. SCALER_DISPCTRLX_WIDTH) |
  323. VC4_SET_FIELD(mode->vdisplay,
  324. SCALER_DISPCTRLX_HEIGHT) |
  325. (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
  326. dispbkgndx |= SCALER_DISPBKGND_AUTOHS;
  327. } else {
  328. dispctrl |= VC4_SET_FIELD(mode->hdisplay,
  329. SCALER5_DISPCTRLX_WIDTH) |
  330. VC4_SET_FIELD(mode->vdisplay,
  331. SCALER5_DISPCTRLX_HEIGHT) |
  332. (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
  333. dispbkgndx &= ~SCALER5_DISPBKGND_BCK2BCK;
  334. }
  335. HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
  336. dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
  337. dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE;
  338. HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
  339. ((vc4->gen == VC4_GEN_4) ? SCALER_DISPBKGND_GAMMA : 0) |
  340. (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
  341. /* Reload the LUT, since the SRAMs would have been disabled if
  342. * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
  343. */
  344. vc4_hvs_lut_load(hvs, vc4_crtc);
  345. drm_dev_exit(idx);
  346. return 0;
  347. }
  348. void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan)
  349. {
  350. struct drm_device *drm = &hvs->vc4->base;
  351. int idx;
  352. if (!drm_dev_enter(drm, &idx))
  353. return;
  354. if (!(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE))
  355. goto out;
  356. HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET);
  357. HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
  358. /* Once we leave, the scaler should be disabled and its fifo empty. */
  359. WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
  360. WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
  361. SCALER_DISPSTATX_MODE) !=
  362. SCALER_DISPSTATX_MODE_DISABLED);
  363. WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
  364. (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
  365. SCALER_DISPSTATX_EMPTY);
  366. out:
  367. drm_dev_exit(idx);
  368. }
  369. int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
  370. {
  371. struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
  372. struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
  373. struct drm_device *dev = crtc->dev;
  374. struct vc4_dev *vc4 = to_vc4_dev(dev);
  375. struct drm_plane *plane;
  376. unsigned long flags;
  377. const struct drm_plane_state *plane_state;
  378. u32 dlist_count = 0;
  379. int ret;
  380. /* The pixelvalve can only feed one encoder (and encoders are
  381. * 1:1 with connectors.)
  382. */
  383. if (hweight32(crtc_state->connector_mask) > 1)
  384. return -EINVAL;
  385. drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state)
  386. dlist_count += vc4_plane_dlist_size(plane_state);
  387. dlist_count++; /* Account for SCALER_CTL0_END. */
  388. spin_lock_irqsave(&vc4->hvs->mm_lock, flags);
  389. ret = drm_mm_insert_node(&vc4->hvs->dlist_mm, &vc4_state->mm,
  390. dlist_count);
  391. spin_unlock_irqrestore(&vc4->hvs->mm_lock, flags);
  392. if (ret)
  393. return ret;
  394. return 0;
  395. }
  396. static void vc4_hvs_install_dlist(struct drm_crtc *crtc)
  397. {
  398. struct drm_device *dev = crtc->dev;
  399. struct vc4_dev *vc4 = to_vc4_dev(dev);
  400. struct vc4_hvs *hvs = vc4->hvs;
  401. struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
  402. int idx;
  403. if (!drm_dev_enter(dev, &idx))
  404. return;
  405. HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
  406. vc4_state->mm.start);
  407. drm_dev_exit(idx);
  408. }
  409. static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
  410. {
  411. struct drm_device *dev = crtc->dev;
  412. struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
  413. struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
  414. unsigned long flags;
  415. if (crtc->state->event) {
  416. crtc->state->event->pipe = drm_crtc_index(crtc);
  417. WARN_ON(drm_crtc_vblank_get(crtc) != 0);
  418. spin_lock_irqsave(&dev->event_lock, flags);
  419. if (!vc4_crtc->feeds_txp || vc4_state->txp_armed) {
  420. vc4_crtc->event = crtc->state->event;
  421. crtc->state->event = NULL;
  422. }
  423. spin_unlock_irqrestore(&dev->event_lock, flags);
  424. }
  425. spin_lock_irqsave(&vc4_crtc->irq_lock, flags);
  426. vc4_crtc->current_dlist = vc4_state->mm.start;
  427. spin_unlock_irqrestore(&vc4_crtc->irq_lock, flags);
  428. }
  429. void vc4_hvs_atomic_begin(struct drm_crtc *crtc,
  430. struct drm_atomic_state *state)
  431. {
  432. struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
  433. struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
  434. unsigned long flags;
  435. spin_lock_irqsave(&vc4_crtc->irq_lock, flags);
  436. vc4_crtc->current_hvs_channel = vc4_state->assigned_channel;
  437. spin_unlock_irqrestore(&vc4_crtc->irq_lock, flags);
  438. }
  439. void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
  440. struct drm_atomic_state *state)
  441. {
  442. struct drm_device *dev = crtc->dev;
  443. struct vc4_dev *vc4 = to_vc4_dev(dev);
  444. struct drm_display_mode *mode = &crtc->state->adjusted_mode;
  445. struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
  446. bool oneshot = vc4_crtc->feeds_txp;
  447. vc4_hvs_install_dlist(crtc);
  448. vc4_hvs_update_dlist(crtc);
  449. vc4_hvs_init_channel(vc4->hvs, crtc, mode, oneshot);
  450. }
  451. void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
  452. struct drm_atomic_state *state)
  453. {
  454. struct drm_device *dev = crtc->dev;
  455. struct vc4_dev *vc4 = to_vc4_dev(dev);
  456. struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, crtc);
  457. struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
  458. unsigned int chan = vc4_state->assigned_channel;
  459. vc4_hvs_stop_channel(vc4->hvs, chan);
  460. }
  461. void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
  462. struct drm_atomic_state *state)
  463. {
  464. struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,
  465. crtc);
  466. struct drm_device *dev = crtc->dev;
  467. struct vc4_dev *vc4 = to_vc4_dev(dev);
  468. struct vc4_hvs *hvs = vc4->hvs;
  469. struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
  470. struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
  471. unsigned int channel = vc4_state->assigned_channel;
  472. struct drm_plane *plane;
  473. struct vc4_plane_state *vc4_plane_state;
  474. bool debug_dump_regs = false;
  475. bool enable_bg_fill = false;
  476. u32 __iomem *dlist_start = vc4->hvs->dlist + vc4_state->mm.start;
  477. u32 __iomem *dlist_next = dlist_start;
  478. unsigned int zpos = 0;
  479. bool found = false;
  480. int idx;
  481. if (!drm_dev_enter(dev, &idx)) {
  482. vc4_crtc_send_vblank(crtc);
  483. return;
  484. }
  485. if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED)
  486. goto exit;
  487. if (debug_dump_regs) {
  488. DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc));
  489. vc4_hvs_dump_state(hvs);
  490. }
  491. /* Copy all the active planes' dlist contents to the hardware dlist. */
  492. do {
  493. found = false;
  494. drm_atomic_crtc_for_each_plane(plane, crtc) {
  495. if (plane->state->normalized_zpos != zpos)
  496. continue;
  497. /* Is this the first active plane? */
  498. if (dlist_next == dlist_start) {
  499. /* We need to enable background fill when a plane
  500. * could be alpha blending from the background, i.e.
  501. * where no other plane is underneath. It suffices to
  502. * consider the first active plane here since we set
  503. * needs_bg_fill such that either the first plane
  504. * already needs it or all planes on top blend from
  505. * the first or a lower plane.
  506. */
  507. vc4_plane_state = to_vc4_plane_state(plane->state);
  508. enable_bg_fill = vc4_plane_state->needs_bg_fill;
  509. }
  510. dlist_next += vc4_plane_write_dlist(plane, dlist_next);
  511. found = true;
  512. }
  513. zpos++;
  514. } while (found);
  515. writel(SCALER_CTL0_END, dlist_next);
  516. dlist_next++;
  517. WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm.size);
  518. if (enable_bg_fill)
  519. /* This sets a black background color fill, as is the case
  520. * with other DRM drivers.
  521. */
  522. HVS_WRITE(SCALER_DISPBKGNDX(channel),
  523. HVS_READ(SCALER_DISPBKGNDX(channel)) |
  524. SCALER_DISPBKGND_FILL);
  525. /* Only update DISPLIST if the CRTC was already running and is not
  526. * being disabled.
  527. * vc4_crtc_enable() takes care of updating the dlist just after
  528. * re-enabling VBLANK interrupts and before enabling the engine.
  529. * If the CRTC is being disabled, there's no point in updating this
  530. * information.
  531. */
  532. if (crtc->state->active && old_state->active) {
  533. vc4_hvs_install_dlist(crtc);
  534. vc4_hvs_update_dlist(crtc);
  535. }
  536. if (crtc->state->color_mgmt_changed) {
  537. u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(channel));
  538. if (crtc->state->gamma_lut) {
  539. vc4_hvs_update_gamma_lut(hvs, vc4_crtc);
  540. dispbkgndx |= SCALER_DISPBKGND_GAMMA;
  541. } else {
  542. /* Unsetting DISPBKGND_GAMMA skips the gamma lut step
  543. * in hardware, which is the same as a linear lut that
  544. * DRM expects us to use in absence of a user lut.
  545. */
  546. dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
  547. }
  548. HVS_WRITE(SCALER_DISPBKGNDX(channel), dispbkgndx);
  549. }
  550. if (debug_dump_regs) {
  551. DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
  552. vc4_hvs_dump_state(hvs);
  553. }
  554. exit:
  555. drm_dev_exit(idx);
  556. }
  557. void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel)
  558. {
  559. struct vc4_dev *vc4 = hvs->vc4;
  560. struct drm_device *drm = &vc4->base;
  561. u32 dispctrl;
  562. int idx;
  563. if (!drm_dev_enter(drm, &idx))
  564. return;
  565. dispctrl = HVS_READ(SCALER_DISPCTRL);
  566. dispctrl &= ~((vc4->gen == VC4_GEN_5) ?
  567. SCALER5_DISPCTRL_DSPEISLUR(channel) :
  568. SCALER_DISPCTRL_DSPEISLUR(channel));
  569. HVS_WRITE(SCALER_DISPCTRL, dispctrl);
  570. drm_dev_exit(idx);
  571. }
  572. void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel)
  573. {
  574. struct vc4_dev *vc4 = hvs->vc4;
  575. struct drm_device *drm = &vc4->base;
  576. u32 dispctrl;
  577. int idx;
  578. if (!drm_dev_enter(drm, &idx))
  579. return;
  580. dispctrl = HVS_READ(SCALER_DISPCTRL);
  581. dispctrl |= ((vc4->gen == VC4_GEN_5) ?
  582. SCALER5_DISPCTRL_DSPEISLUR(channel) :
  583. SCALER_DISPCTRL_DSPEISLUR(channel));
  584. HVS_WRITE(SCALER_DISPSTAT,
  585. SCALER_DISPSTAT_EUFLOW(channel));
  586. HVS_WRITE(SCALER_DISPCTRL, dispctrl);
  587. drm_dev_exit(idx);
  588. }
  589. static void vc4_hvs_report_underrun(struct drm_device *dev)
  590. {
  591. struct vc4_dev *vc4 = to_vc4_dev(dev);
  592. atomic_inc(&vc4->underrun);
  593. DRM_DEV_ERROR(dev->dev, "HVS underrun\n");
  594. }
  595. static irqreturn_t vc4_hvs_irq_handler(int irq, void *data)
  596. {
  597. struct drm_device *dev = data;
  598. struct vc4_dev *vc4 = to_vc4_dev(dev);
  599. struct vc4_hvs *hvs = vc4->hvs;
  600. irqreturn_t irqret = IRQ_NONE;
  601. int channel;
  602. u32 control;
  603. u32 status;
  604. u32 dspeislur;
  605. /*
  606. * NOTE: We don't need to protect the register access using
  607. * drm_dev_enter() there because the interrupt handler lifetime
  608. * is tied to the device itself, and not to the DRM device.
  609. *
  610. * So when the device will be gone, one of the first thing we
  611. * will be doing will be to unregister the interrupt handler,
  612. * and then unregister the DRM device. drm_dev_enter() would
  613. * thus always succeed if we are here.
  614. */
  615. status = HVS_READ(SCALER_DISPSTAT);
  616. control = HVS_READ(SCALER_DISPCTRL);
  617. for (channel = 0; channel < SCALER_CHANNELS_COUNT; channel++) {
  618. dspeislur = (vc4->gen == VC4_GEN_5) ?
  619. SCALER5_DISPCTRL_DSPEISLUR(channel) :
  620. SCALER_DISPCTRL_DSPEISLUR(channel);
  621. /* Interrupt masking is not always honored, so check it here. */
  622. if (status & SCALER_DISPSTAT_EUFLOW(channel) &&
  623. control & dspeislur) {
  624. vc4_hvs_mask_underrun(hvs, channel);
  625. vc4_hvs_report_underrun(dev);
  626. irqret = IRQ_HANDLED;
  627. }
  628. }
  629. /* Clear every per-channel interrupt flag. */
  630. HVS_WRITE(SCALER_DISPSTAT, SCALER_DISPSTAT_IRQMASK(0) |
  631. SCALER_DISPSTAT_IRQMASK(1) |
  632. SCALER_DISPSTAT_IRQMASK(2));
  633. return irqret;
  634. }
  635. int vc4_hvs_debugfs_init(struct drm_minor *minor)
  636. {
  637. struct drm_device *drm = minor->dev;
  638. struct vc4_dev *vc4 = to_vc4_dev(drm);
  639. struct vc4_hvs *hvs = vc4->hvs;
  640. if (!vc4->hvs)
  641. return -ENODEV;
  642. if (vc4->gen == VC4_GEN_4)
  643. debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR,
  644. minor->debugfs_root,
  645. &vc4->load_tracker_enabled);
  646. drm_debugfs_add_file(drm, "hvs_dlists", vc4_hvs_debugfs_dlist, NULL);
  647. drm_debugfs_add_file(drm, "hvs_underrun", vc4_hvs_debugfs_underrun, NULL);
  648. vc4_debugfs_add_regset32(drm, "hvs_regs", &hvs->regset);
  649. return 0;
  650. }
  651. struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, struct platform_device *pdev)
  652. {
  653. struct drm_device *drm = &vc4->base;
  654. struct vc4_hvs *hvs;
  655. hvs = drmm_kzalloc(drm, sizeof(*hvs), GFP_KERNEL);
  656. if (!hvs)
  657. return ERR_PTR(-ENOMEM);
  658. hvs->vc4 = vc4;
  659. hvs->pdev = pdev;
  660. spin_lock_init(&hvs->mm_lock);
  661. /* Set up the HVS display list memory manager. We never
  662. * overwrite the setup from the bootloader (just 128b out of
  663. * our 16K), since we don't want to scramble the screen when
  664. * transitioning from the firmware's boot setup to runtime.
  665. */
  666. hvs->dlist_mem_size = (SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END;
  667. drm_mm_init(&hvs->dlist_mm,
  668. HVS_BOOTLOADER_DLIST_END,
  669. hvs->dlist_mem_size);
  670. /* Set up the HVS LBM memory manager. We could have some more
  671. * complicated data structure that allowed reuse of LBM areas
  672. * between planes when they don't overlap on the screen, but
  673. * for now we just allocate globally.
  674. */
  675. if (vc4->gen == VC4_GEN_4)
  676. /* 48k words of 2x12-bit pixels */
  677. drm_mm_init(&hvs->lbm_mm, 0, 48 * 1024);
  678. else
  679. /* 60k words of 4x12-bit pixels */
  680. drm_mm_init(&hvs->lbm_mm, 0, 60 * 1024);
  681. vc4->hvs = hvs;
  682. return hvs;
  683. }
  684. static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
  685. {
  686. struct platform_device *pdev = to_platform_device(dev);
  687. struct drm_device *drm = dev_get_drvdata(master);
  688. struct vc4_dev *vc4 = to_vc4_dev(drm);
  689. struct vc4_hvs *hvs = NULL;
  690. int ret;
  691. u32 dispctrl;
  692. u32 reg, top;
  693. hvs = __vc4_hvs_alloc(vc4, NULL);
  694. if (IS_ERR(hvs))
  695. return PTR_ERR(hvs);
  696. hvs->regs = vc4_ioremap_regs(pdev, 0);
  697. if (IS_ERR(hvs->regs))
  698. return PTR_ERR(hvs->regs);
  699. hvs->regset.base = hvs->regs;
  700. hvs->regset.regs = hvs_regs;
  701. hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
  702. if (vc4->gen == VC4_GEN_5) {
  703. struct rpi_firmware *firmware;
  704. struct device_node *node;
  705. unsigned int max_rate;
  706. node = rpi_firmware_find_node();
  707. if (!node)
  708. return -EINVAL;
  709. firmware = rpi_firmware_get(node);
  710. of_node_put(node);
  711. if (!firmware)
  712. return -EPROBE_DEFER;
  713. hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
  714. if (IS_ERR(hvs->core_clk)) {
  715. dev_err(&pdev->dev, "Couldn't get core clock\n");
  716. return PTR_ERR(hvs->core_clk);
  717. }
  718. max_rate = rpi_firmware_clk_get_max_rate(firmware,
  719. RPI_FIRMWARE_CORE_CLK_ID);
  720. rpi_firmware_put(firmware);
  721. if (max_rate >= 550000000)
  722. hvs->vc5_hdmi_enable_hdmi_20 = true;
  723. if (max_rate >= 600000000)
  724. hvs->vc5_hdmi_enable_4096by2160 = true;
  725. hvs->max_core_rate = max_rate;
  726. ret = clk_prepare_enable(hvs->core_clk);
  727. if (ret) {
  728. dev_err(&pdev->dev, "Couldn't enable the core clock\n");
  729. return ret;
  730. }
  731. }
  732. if (vc4->gen == VC4_GEN_4)
  733. hvs->dlist = hvs->regs + SCALER_DLIST_START;
  734. else
  735. hvs->dlist = hvs->regs + SCALER5_DLIST_START;
  736. /* Upload filter kernels. We only have the one for now, so we
  737. * keep it around for the lifetime of the driver.
  738. */
  739. ret = vc4_hvs_upload_linear_kernel(hvs,
  740. &hvs->mitchell_netravali_filter,
  741. mitchell_netravali_1_3_1_3_kernel);
  742. if (ret)
  743. return ret;
  744. reg = HVS_READ(SCALER_DISPECTRL);
  745. reg &= ~SCALER_DISPECTRL_DSP2_MUX_MASK;
  746. HVS_WRITE(SCALER_DISPECTRL,
  747. reg | VC4_SET_FIELD(0, SCALER_DISPECTRL_DSP2_MUX));
  748. reg = HVS_READ(SCALER_DISPCTRL);
  749. reg &= ~SCALER_DISPCTRL_DSP3_MUX_MASK;
  750. HVS_WRITE(SCALER_DISPCTRL,
  751. reg | VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX));
  752. reg = HVS_READ(SCALER_DISPEOLN);
  753. reg &= ~SCALER_DISPEOLN_DSP4_MUX_MASK;
  754. HVS_WRITE(SCALER_DISPEOLN,
  755. reg | VC4_SET_FIELD(3, SCALER_DISPEOLN_DSP4_MUX));
  756. reg = HVS_READ(SCALER_DISPDITHER);
  757. reg &= ~SCALER_DISPDITHER_DSP5_MUX_MASK;
  758. HVS_WRITE(SCALER_DISPDITHER,
  759. reg | VC4_SET_FIELD(3, SCALER_DISPDITHER_DSP5_MUX));
  760. dispctrl = HVS_READ(SCALER_DISPCTRL);
  761. dispctrl |= SCALER_DISPCTRL_ENABLE;
  762. dispctrl |= SCALER_DISPCTRL_DISPEIRQ(0) |
  763. SCALER_DISPCTRL_DISPEIRQ(1) |
  764. SCALER_DISPCTRL_DISPEIRQ(2);
  765. if (vc4->gen == VC4_GEN_4)
  766. dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
  767. SCALER_DISPCTRL_SLVWREIRQ |
  768. SCALER_DISPCTRL_SLVRDEIRQ |
  769. SCALER_DISPCTRL_DSPEIEOF(0) |
  770. SCALER_DISPCTRL_DSPEIEOF(1) |
  771. SCALER_DISPCTRL_DSPEIEOF(2) |
  772. SCALER_DISPCTRL_DSPEIEOLN(0) |
  773. SCALER_DISPCTRL_DSPEIEOLN(1) |
  774. SCALER_DISPCTRL_DSPEIEOLN(2) |
  775. SCALER_DISPCTRL_DSPEISLUR(0) |
  776. SCALER_DISPCTRL_DSPEISLUR(1) |
  777. SCALER_DISPCTRL_DSPEISLUR(2) |
  778. SCALER_DISPCTRL_SCLEIRQ);
  779. else
  780. dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
  781. SCALER5_DISPCTRL_SLVEIRQ |
  782. SCALER5_DISPCTRL_DSPEIEOF(0) |
  783. SCALER5_DISPCTRL_DSPEIEOF(1) |
  784. SCALER5_DISPCTRL_DSPEIEOF(2) |
  785. SCALER5_DISPCTRL_DSPEIEOLN(0) |
  786. SCALER5_DISPCTRL_DSPEIEOLN(1) |
  787. SCALER5_DISPCTRL_DSPEIEOLN(2) |
  788. SCALER5_DISPCTRL_DSPEISLUR(0) |
  789. SCALER5_DISPCTRL_DSPEISLUR(1) |
  790. SCALER5_DISPCTRL_DSPEISLUR(2) |
  791. SCALER_DISPCTRL_SCLEIRQ);
  792. /* Set AXI panic mode.
  793. * VC4 panics when < 2 lines in FIFO.
  794. * VC5 panics when less than 1 line in the FIFO.
  795. */
  796. dispctrl &= ~(SCALER_DISPCTRL_PANIC0_MASK |
  797. SCALER_DISPCTRL_PANIC1_MASK |
  798. SCALER_DISPCTRL_PANIC2_MASK);
  799. dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC0);
  800. dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC1);
  801. dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC2);
  802. /* Set AXI panic mode.
  803. * VC4 panics when < 2 lines in FIFO.
  804. * VC5 panics when less than 1 line in the FIFO.
  805. */
  806. dispctrl &= ~(SCALER_DISPCTRL_PANIC0_MASK |
  807. SCALER_DISPCTRL_PANIC1_MASK |
  808. SCALER_DISPCTRL_PANIC2_MASK);
  809. dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC0);
  810. dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC1);
  811. dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_PANIC2);
  812. HVS_WRITE(SCALER_DISPCTRL, dispctrl);
  813. /* Recompute Composite Output Buffer (COB) allocations for the displays
  814. */
  815. if (vc4->gen == VC4_GEN_4) {
  816. /* The COB is 20736 pixels, or just over 10 lines at 2048 wide.
  817. * The bottom 2048 pixels are full 32bpp RGBA (intended for the
  818. * TXP composing RGBA to memory), whilst the remainder are only
  819. * 24bpp RGB.
  820. *
  821. * Assign 3 lines to channels 1 & 2, and just over 4 lines to
  822. * channel 0.
  823. */
  824. #define VC4_COB_SIZE 20736
  825. #define VC4_COB_LINE_WIDTH 2048
  826. #define VC4_COB_NUM_LINES 3
  827. reg = 0;
  828. top = VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES;
  829. reg |= (top - 1) << 16;
  830. HVS_WRITE(SCALER_DISPBASE2, reg);
  831. reg = top;
  832. top += VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES;
  833. reg |= (top - 1) << 16;
  834. HVS_WRITE(SCALER_DISPBASE1, reg);
  835. reg = top;
  836. top = VC4_COB_SIZE;
  837. reg |= (top - 1) << 16;
  838. HVS_WRITE(SCALER_DISPBASE0, reg);
  839. } else {
  840. /* The COB is 44416 pixels, or 10.8 lines at 4096 wide.
  841. * The bottom 4096 pixels are full RGBA (intended for the TXP
  842. * composing RGBA to memory), whilst the remainder are only
  843. * RGB. Addressing is always pixel wide.
  844. *
  845. * Assign 3 lines of 4096 to channels 1 & 2, and just over 4
  846. * lines. to channel 0.
  847. */
  848. #define VC5_COB_SIZE 44416
  849. #define VC5_COB_LINE_WIDTH 4096
  850. #define VC5_COB_NUM_LINES 3
  851. reg = 0;
  852. top = VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES;
  853. reg |= top << 16;
  854. HVS_WRITE(SCALER_DISPBASE2, reg);
  855. top += 16;
  856. reg = top;
  857. top += VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES;
  858. reg |= top << 16;
  859. HVS_WRITE(SCALER_DISPBASE1, reg);
  860. top += 16;
  861. reg = top;
  862. top = VC5_COB_SIZE;
  863. reg |= top << 16;
  864. HVS_WRITE(SCALER_DISPBASE0, reg);
  865. }
  866. ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
  867. vc4_hvs_irq_handler, 0, "vc4 hvs", drm);
  868. if (ret)
  869. return ret;
  870. return 0;
  871. }
  872. static void vc4_hvs_unbind(struct device *dev, struct device *master,
  873. void *data)
  874. {
  875. struct drm_device *drm = dev_get_drvdata(master);
  876. struct vc4_dev *vc4 = to_vc4_dev(drm);
  877. struct vc4_hvs *hvs = vc4->hvs;
  878. struct drm_mm_node *node, *next;
  879. if (drm_mm_node_allocated(&vc4->hvs->mitchell_netravali_filter))
  880. drm_mm_remove_node(&vc4->hvs->mitchell_netravali_filter);
  881. drm_mm_for_each_node_safe(node, next, &vc4->hvs->dlist_mm)
  882. drm_mm_remove_node(node);
  883. drm_mm_takedown(&vc4->hvs->dlist_mm);
  884. drm_mm_for_each_node_safe(node, next, &vc4->hvs->lbm_mm)
  885. drm_mm_remove_node(node);
  886. drm_mm_takedown(&vc4->hvs->lbm_mm);
  887. clk_disable_unprepare(hvs->core_clk);
  888. vc4->hvs = NULL;
  889. }
  890. static const struct component_ops vc4_hvs_ops = {
  891. .bind = vc4_hvs_bind,
  892. .unbind = vc4_hvs_unbind,
  893. };
  894. static int vc4_hvs_dev_probe(struct platform_device *pdev)
  895. {
  896. return component_add(&pdev->dev, &vc4_hvs_ops);
  897. }
  898. static void vc4_hvs_dev_remove(struct platform_device *pdev)
  899. {
  900. component_del(&pdev->dev, &vc4_hvs_ops);
  901. }
  902. static const struct of_device_id vc4_hvs_dt_match[] = {
  903. { .compatible = "brcm,bcm2711-hvs" },
  904. { .compatible = "brcm,bcm2835-hvs" },
  905. {}
  906. };
  907. struct platform_driver vc4_hvs_driver = {
  908. .probe = vc4_hvs_dev_probe,
  909. .remove_new = vc4_hvs_dev_remove,
  910. .driver = {
  911. .name = "vc4_hvs",
  912. .of_match_table = vc4_hvs_dt_match,
  913. },
  914. };