vce_v3_0.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. /*
  2. * Copyright 2014 Advanced Micro Devices, Inc.
  3. * All Rights Reserved.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the
  7. * "Software"), to deal in the Software without restriction, including
  8. * without limitation the rights to use, copy, modify, merge, publish,
  9. * distribute, sub license, and/or sell copies of the Software, and to
  10. * permit persons to whom the Software is furnished to do so, subject to
  11. * the following conditions:
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  16. * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  17. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  18. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  19. * USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. *
  21. * The above copyright notice and this permission notice (including the
  22. * next paragraph) shall be included in all copies or substantial portions
  23. * of the Software.
  24. *
  25. * Authors: Christian König <christian.koenig@amd.com>
  26. */
  27. #include <linux/firmware.h>
  28. #include <drm/drmP.h>
  29. #include "amdgpu.h"
  30. #include "amdgpu_vce.h"
  31. #include "vid.h"
  32. #include "vce/vce_3_0_d.h"
  33. #include "vce/vce_3_0_sh_mask.h"
  34. #include "oss/oss_3_0_d.h"
  35. #include "oss/oss_3_0_sh_mask.h"
  36. #include "gca/gfx_8_0_d.h"
  37. #include "smu/smu_7_1_2_d.h"
  38. #include "smu/smu_7_1_2_sh_mask.h"
  39. #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT 0x04
  40. #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK 0x10
  41. #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR0 0x8616
  42. #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR1 0x8617
  43. #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR2 0x8618
  44. #define VCE_V3_0_FW_SIZE (384 * 1024)
  45. #define VCE_V3_0_STACK_SIZE (64 * 1024)
  46. #define VCE_V3_0_DATA_SIZE ((16 * 1024 * AMDGPU_MAX_VCE_HANDLES) + (52 * 1024))
  47. static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);
  48. static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
  49. static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev);
  50. /**
  51. * vce_v3_0_ring_get_rptr - get read pointer
  52. *
  53. * @ring: amdgpu_ring pointer
  54. *
  55. * Returns the current hardware read pointer
  56. */
  57. static uint32_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring)
  58. {
  59. struct amdgpu_device *adev = ring->adev;
  60. if (ring == &adev->vce.ring[0])
  61. return RREG32(mmVCE_RB_RPTR);
  62. else
  63. return RREG32(mmVCE_RB_RPTR2);
  64. }
  65. /**
  66. * vce_v3_0_ring_get_wptr - get write pointer
  67. *
  68. * @ring: amdgpu_ring pointer
  69. *
  70. * Returns the current hardware write pointer
  71. */
  72. static uint32_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring)
  73. {
  74. struct amdgpu_device *adev = ring->adev;
  75. if (ring == &adev->vce.ring[0])
  76. return RREG32(mmVCE_RB_WPTR);
  77. else
  78. return RREG32(mmVCE_RB_WPTR2);
  79. }
  80. /**
  81. * vce_v3_0_ring_set_wptr - set write pointer
  82. *
  83. * @ring: amdgpu_ring pointer
  84. *
  85. * Commits the write pointer to the hardware
  86. */
  87. static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring)
  88. {
  89. struct amdgpu_device *adev = ring->adev;
  90. if (ring == &adev->vce.ring[0])
  91. WREG32(mmVCE_RB_WPTR, ring->wptr);
  92. else
  93. WREG32(mmVCE_RB_WPTR2, ring->wptr);
  94. }
  95. static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override)
  96. {
  97. u32 tmp, data;
  98. tmp = data = RREG32(mmVCE_RB_ARB_CTRL);
  99. if (override)
  100. data |= VCE_RB_ARB_CTRL__VCE_CGTT_OVERRIDE_MASK;
  101. else
  102. data &= ~VCE_RB_ARB_CTRL__VCE_CGTT_OVERRIDE_MASK;
  103. if (tmp != data)
  104. WREG32(mmVCE_RB_ARB_CTRL, data);
  105. }
  106. static void vce_v3_0_set_vce_sw_clock_gating(struct amdgpu_device *adev,
  107. bool gated)
  108. {
  109. u32 tmp, data;
  110. /* Set Override to disable Clock Gating */
  111. vce_v3_0_override_vce_clock_gating(adev, true);
  112. if (!gated) {
  113. /* Force CLOCK ON for VCE_CLOCK_GATING_B,
  114. * {*_FORCE_ON, *_FORCE_OFF} = {1, 0}
  115. * VREG can be FORCE ON or set to Dynamic, but can't be OFF
  116. */
  117. tmp = data = RREG32(mmVCE_CLOCK_GATING_B);
  118. data |= 0x1ff;
  119. data &= ~0xef0000;
  120. if (tmp != data)
  121. WREG32(mmVCE_CLOCK_GATING_B, data);
  122. /* Force CLOCK ON for VCE_UENC_CLOCK_GATING,
  123. * {*_FORCE_ON, *_FORCE_OFF} = {1, 0}
  124. */
  125. tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING);
  126. data |= 0x3ff000;
  127. data &= ~0xffc00000;
  128. if (tmp != data)
  129. WREG32(mmVCE_UENC_CLOCK_GATING, data);
  130. /* set VCE_UENC_CLOCK_GATING_2 */
  131. tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING_2);
  132. data |= 0x2;
  133. data &= ~0x2;
  134. if (tmp != data)
  135. WREG32(mmVCE_UENC_CLOCK_GATING_2, data);
  136. /* Force CLOCK ON for VCE_UENC_REG_CLOCK_GATING */
  137. tmp = data = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
  138. data |= 0x37f;
  139. if (tmp != data)
  140. WREG32(mmVCE_UENC_REG_CLOCK_GATING, data);
  141. /* Force VCE_UENC_DMA_DCLK_CTRL Clock ON */
  142. tmp = data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL);
  143. data |= VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK |
  144. VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK |
  145. VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK |
  146. 0x8;
  147. if (tmp != data)
  148. WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data);
  149. } else {
  150. /* Force CLOCK OFF for VCE_CLOCK_GATING_B,
  151. * {*, *_FORCE_OFF} = {*, 1}
  152. * set VREG to Dynamic, as it can't be OFF
  153. */
  154. tmp = data = RREG32(mmVCE_CLOCK_GATING_B);
  155. data &= ~0x80010;
  156. data |= 0xe70008;
  157. if (tmp != data)
  158. WREG32(mmVCE_CLOCK_GATING_B, data);
  159. /* Force CLOCK OFF for VCE_UENC_CLOCK_GATING,
  160. * Force ClOCK OFF takes precedent over Force CLOCK ON setting.
  161. * {*_FORCE_ON, *_FORCE_OFF} = {*, 1}
  162. */
  163. tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING);
  164. data |= 0xffc00000;
  165. if (tmp != data)
  166. WREG32(mmVCE_UENC_CLOCK_GATING, data);
  167. /* Set VCE_UENC_CLOCK_GATING_2 */
  168. tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING_2);
  169. data |= 0x10000;
  170. if (tmp != data)
  171. WREG32(mmVCE_UENC_CLOCK_GATING_2, data);
  172. /* Set VCE_UENC_REG_CLOCK_GATING to dynamic */
  173. tmp = data = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
  174. data &= ~0xffc00000;
  175. if (tmp != data)
  176. WREG32(mmVCE_UENC_REG_CLOCK_GATING, data);
  177. /* Set VCE_UENC_DMA_DCLK_CTRL CG always in dynamic mode */
  178. tmp = data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL);
  179. data &= ~(VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK |
  180. VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK |
  181. VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK |
  182. 0x8);
  183. if (tmp != data)
  184. WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data);
  185. }
  186. vce_v3_0_override_vce_clock_gating(adev, false);
  187. }
  188. /**
  189. * vce_v3_0_start - start VCE block
  190. *
  191. * @adev: amdgpu_device pointer
  192. *
  193. * Setup and start the VCE block
  194. */
  195. static int vce_v3_0_start(struct amdgpu_device *adev)
  196. {
  197. struct amdgpu_ring *ring;
  198. int idx, i, j, r;
  199. mutex_lock(&adev->grbm_idx_mutex);
  200. for (idx = 0; idx < 2; ++idx) {
  201. if (adev->vce.harvest_config & (1 << idx))
  202. continue;
  203. if (idx == 0)
  204. WREG32_P(mmGRBM_GFX_INDEX, 0,
  205. ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
  206. else
  207. WREG32_P(mmGRBM_GFX_INDEX,
  208. GRBM_GFX_INDEX__VCE_INSTANCE_MASK,
  209. ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
  210. vce_v3_0_mc_resume(adev, idx);
  211. /* set BUSY flag */
  212. WREG32_P(mmVCE_STATUS, 1, ~1);
  213. if (adev->asic_type >= CHIP_STONEY)
  214. WREG32_P(mmVCE_VCPU_CNTL, 1, ~0x200001);
  215. else
  216. WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK,
  217. ~VCE_VCPU_CNTL__CLK_EN_MASK);
  218. WREG32_P(mmVCE_SOFT_RESET,
  219. VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
  220. ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
  221. mdelay(100);
  222. WREG32_P(mmVCE_SOFT_RESET, 0,
  223. ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
  224. for (i = 0; i < 10; ++i) {
  225. uint32_t status;
  226. for (j = 0; j < 100; ++j) {
  227. status = RREG32(mmVCE_STATUS);
  228. if (status & 2)
  229. break;
  230. mdelay(10);
  231. }
  232. r = 0;
  233. if (status & 2)
  234. break;
  235. DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
  236. WREG32_P(mmVCE_SOFT_RESET,
  237. VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
  238. ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
  239. mdelay(10);
  240. WREG32_P(mmVCE_SOFT_RESET, 0,
  241. ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
  242. mdelay(10);
  243. r = -1;
  244. }
  245. /* clear BUSY flag */
  246. WREG32_P(mmVCE_STATUS, 0, ~1);
  247. /* Set Clock-Gating off */
  248. if (adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)
  249. vce_v3_0_set_vce_sw_clock_gating(adev, false);
  250. if (r) {
  251. DRM_ERROR("VCE not responding, giving up!!!\n");
  252. mutex_unlock(&adev->grbm_idx_mutex);
  253. return r;
  254. }
  255. }
  256. WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
  257. mutex_unlock(&adev->grbm_idx_mutex);
  258. ring = &adev->vce.ring[0];
  259. WREG32(mmVCE_RB_RPTR, ring->wptr);
  260. WREG32(mmVCE_RB_WPTR, ring->wptr);
  261. WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr);
  262. WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
  263. WREG32(mmVCE_RB_SIZE, ring->ring_size / 4);
  264. ring = &adev->vce.ring[1];
  265. WREG32(mmVCE_RB_RPTR2, ring->wptr);
  266. WREG32(mmVCE_RB_WPTR2, ring->wptr);
  267. WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr);
  268. WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
  269. WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
  270. return 0;
  271. }
  272. #define ixVCE_HARVEST_FUSE_MACRO__ADDRESS 0xC0014074
  273. #define VCE_HARVEST_FUSE_MACRO__SHIFT 27
  274. #define VCE_HARVEST_FUSE_MACRO__MASK 0x18000000
  275. static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
  276. {
  277. u32 tmp;
  278. /* Fiji, Stoney, Polaris10, Polaris11 are single pipe */
  279. if ((adev->asic_type == CHIP_FIJI) ||
  280. (adev->asic_type == CHIP_STONEY) ||
  281. (adev->asic_type == CHIP_POLARIS10) ||
  282. (adev->asic_type == CHIP_POLARIS11))
  283. return AMDGPU_VCE_HARVEST_VCE1;
  284. /* Tonga and CZ are dual or single pipe */
  285. if (adev->flags & AMD_IS_APU)
  286. tmp = (RREG32_SMC(ixVCE_HARVEST_FUSE_MACRO__ADDRESS) &
  287. VCE_HARVEST_FUSE_MACRO__MASK) >>
  288. VCE_HARVEST_FUSE_MACRO__SHIFT;
  289. else
  290. tmp = (RREG32_SMC(ixCC_HARVEST_FUSES) &
  291. CC_HARVEST_FUSES__VCE_DISABLE_MASK) >>
  292. CC_HARVEST_FUSES__VCE_DISABLE__SHIFT;
  293. switch (tmp) {
  294. case 1:
  295. return AMDGPU_VCE_HARVEST_VCE0;
  296. case 2:
  297. return AMDGPU_VCE_HARVEST_VCE1;
  298. case 3:
  299. return AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1;
  300. default:
  301. return 0;
  302. }
  303. }
  304. static int vce_v3_0_early_init(void *handle)
  305. {
  306. struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  307. adev->vce.harvest_config = vce_v3_0_get_harvest_config(adev);
  308. if ((adev->vce.harvest_config &
  309. (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) ==
  310. (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1))
  311. return -ENOENT;
  312. vce_v3_0_set_ring_funcs(adev);
  313. vce_v3_0_set_irq_funcs(adev);
  314. return 0;
  315. }
  316. static int vce_v3_0_sw_init(void *handle)
  317. {
  318. struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  319. struct amdgpu_ring *ring;
  320. int r;
  321. /* VCE */
  322. r = amdgpu_irq_add_id(adev, 167, &adev->vce.irq);
  323. if (r)
  324. return r;
  325. r = amdgpu_vce_sw_init(adev, VCE_V3_0_FW_SIZE +
  326. (VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE) * 2);
  327. if (r)
  328. return r;
  329. r = amdgpu_vce_resume(adev);
  330. if (r)
  331. return r;
  332. ring = &adev->vce.ring[0];
  333. sprintf(ring->name, "vce0");
  334. r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf,
  335. &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
  336. if (r)
  337. return r;
  338. ring = &adev->vce.ring[1];
  339. sprintf(ring->name, "vce1");
  340. r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf,
  341. &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
  342. if (r)
  343. return r;
  344. return r;
  345. }
  346. static int vce_v3_0_sw_fini(void *handle)
  347. {
  348. int r;
  349. struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  350. r = amdgpu_vce_suspend(adev);
  351. if (r)
  352. return r;
  353. r = amdgpu_vce_sw_fini(adev);
  354. if (r)
  355. return r;
  356. return r;
  357. }
  358. static int vce_v3_0_hw_init(void *handle)
  359. {
  360. int r, i;
  361. struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  362. r = vce_v3_0_start(adev);
  363. if (r)
  364. return r;
  365. adev->vce.ring[0].ready = false;
  366. adev->vce.ring[1].ready = false;
  367. for (i = 0; i < 2; i++) {
  368. r = amdgpu_ring_test_ring(&adev->vce.ring[i]);
  369. if (r)
  370. return r;
  371. else
  372. adev->vce.ring[i].ready = true;
  373. }
  374. DRM_INFO("VCE initialized successfully.\n");
  375. return 0;
  376. }
  377. static int vce_v3_0_hw_fini(void *handle)
  378. {
  379. return 0;
  380. }
  381. static int vce_v3_0_suspend(void *handle)
  382. {
  383. int r;
  384. struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  385. r = vce_v3_0_hw_fini(adev);
  386. if (r)
  387. return r;
  388. r = amdgpu_vce_suspend(adev);
  389. if (r)
  390. return r;
  391. return r;
  392. }
  393. static int vce_v3_0_resume(void *handle)
  394. {
  395. int r;
  396. struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  397. r = amdgpu_vce_resume(adev);
  398. if (r)
  399. return r;
  400. r = vce_v3_0_hw_init(adev);
  401. if (r)
  402. return r;
  403. return r;
  404. }
  405. static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx)
  406. {
  407. uint32_t offset, size;
  408. WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16));
  409. WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
  410. WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
  411. WREG32(mmVCE_CLOCK_GATING_B, 0xf7);
  412. WREG32(mmVCE_LMI_CTRL, 0x00398000);
  413. WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1);
  414. WREG32(mmVCE_LMI_SWAP_CNTL, 0);
  415. WREG32(mmVCE_LMI_SWAP_CNTL1, 0);
  416. WREG32(mmVCE_LMI_VM_CTRL, 0);
  417. if (adev->asic_type >= CHIP_STONEY) {
  418. WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR0, (adev->vce.gpu_addr >> 8));
  419. WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR1, (adev->vce.gpu_addr >> 8));
  420. WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR2, (adev->vce.gpu_addr >> 8));
  421. } else
  422. WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8));
  423. offset = AMDGPU_VCE_FIRMWARE_OFFSET;
  424. size = VCE_V3_0_FW_SIZE;
  425. WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff);
  426. WREG32(mmVCE_VCPU_CACHE_SIZE0, size);
  427. if (idx == 0) {
  428. offset += size;
  429. size = VCE_V3_0_STACK_SIZE;
  430. WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff);
  431. WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
  432. offset += size;
  433. size = VCE_V3_0_DATA_SIZE;
  434. WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff);
  435. WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
  436. } else {
  437. offset += size + VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE;
  438. size = VCE_V3_0_STACK_SIZE;
  439. WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0xfffffff);
  440. WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
  441. offset += size;
  442. size = VCE_V3_0_DATA_SIZE;
  443. WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0xfffffff);
  444. WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
  445. }
  446. WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
  447. WREG32_P(mmVCE_SYS_INT_EN, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK,
  448. ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
  449. }
  450. static bool vce_v3_0_is_idle(void *handle)
  451. {
  452. struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  453. u32 mask = 0;
  454. mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_STATUS2__VCE0_BUSY_MASK;
  455. mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE1) ? 0 : SRBM_STATUS2__VCE1_BUSY_MASK;
  456. return !(RREG32(mmSRBM_STATUS2) & mask);
  457. }
  458. static int vce_v3_0_wait_for_idle(void *handle)
  459. {
  460. unsigned i;
  461. struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  462. for (i = 0; i < adev->usec_timeout; i++)
  463. if (vce_v3_0_is_idle(handle))
  464. return 0;
  465. return -ETIMEDOUT;
  466. }
  467. static int vce_v3_0_soft_reset(void *handle)
  468. {
  469. struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  470. u32 mask = 0;
  471. mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK;
  472. mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE1) ? 0 : SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK;
  473. WREG32_P(mmSRBM_SOFT_RESET, mask,
  474. ~(SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK |
  475. SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK));
  476. mdelay(5);
  477. return vce_v3_0_start(adev);
  478. }
  479. static int vce_v3_0_set_interrupt_state(struct amdgpu_device *adev,
  480. struct amdgpu_irq_src *source,
  481. unsigned type,
  482. enum amdgpu_interrupt_state state)
  483. {
  484. uint32_t val = 0;
  485. if (state == AMDGPU_IRQ_STATE_ENABLE)
  486. val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK;
  487. WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
  488. return 0;
  489. }
  490. static int vce_v3_0_process_interrupt(struct amdgpu_device *adev,
  491. struct amdgpu_irq_src *source,
  492. struct amdgpu_iv_entry *entry)
  493. {
  494. DRM_DEBUG("IH: VCE\n");
  495. WREG32_P(mmVCE_SYS_INT_STATUS,
  496. VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK,
  497. ~VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK);
  498. switch (entry->src_data) {
  499. case 0:
  500. case 1:
  501. amdgpu_fence_process(&adev->vce.ring[entry->src_data]);
  502. break;
  503. default:
  504. DRM_ERROR("Unhandled interrupt: %d %d\n",
  505. entry->src_id, entry->src_data);
  506. break;
  507. }
  508. return 0;
  509. }
  510. static int vce_v3_0_set_clockgating_state(void *handle,
  511. enum amd_clockgating_state state)
  512. {
  513. struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  514. bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
  515. int i;
  516. if (!(adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG))
  517. return 0;
  518. mutex_lock(&adev->grbm_idx_mutex);
  519. for (i = 0; i < 2; i++) {
  520. /* Program VCE Instance 0 or 1 if not harvested */
  521. if (adev->vce.harvest_config & (1 << i))
  522. continue;
  523. if (i == 0)
  524. WREG32_P(mmGRBM_GFX_INDEX, 0,
  525. ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
  526. else
  527. WREG32_P(mmGRBM_GFX_INDEX,
  528. GRBM_GFX_INDEX__VCE_INSTANCE_MASK,
  529. ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
  530. if (enable) {
  531. /* initialize VCE_CLOCK_GATING_A: Clock ON/OFF delay */
  532. uint32_t data = RREG32(mmVCE_CLOCK_GATING_A);
  533. data &= ~(0xf | 0xff0);
  534. data |= ((0x0 << 0) | (0x04 << 4));
  535. WREG32(mmVCE_CLOCK_GATING_A, data);
  536. /* initialize VCE_UENC_CLOCK_GATING: Clock ON/OFF delay */
  537. data = RREG32(mmVCE_UENC_CLOCK_GATING);
  538. data &= ~(0xf | 0xff0);
  539. data |= ((0x0 << 0) | (0x04 << 4));
  540. WREG32(mmVCE_UENC_CLOCK_GATING, data);
  541. }
  542. vce_v3_0_set_vce_sw_clock_gating(adev, enable);
  543. }
  544. WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
  545. mutex_unlock(&adev->grbm_idx_mutex);
  546. return 0;
  547. }
  548. static int vce_v3_0_set_powergating_state(void *handle,
  549. enum amd_powergating_state state)
  550. {
  551. /* This doesn't actually powergate the VCE block.
  552. * That's done in the dpm code via the SMC. This
  553. * just re-inits the block as necessary. The actual
  554. * gating still happens in the dpm code. We should
  555. * revisit this when there is a cleaner line between
  556. * the smc and the hw blocks
  557. */
  558. struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  559. if (!(adev->pg_flags & AMD_PG_SUPPORT_VCE))
  560. return 0;
  561. if (state == AMD_PG_STATE_GATE)
  562. /* XXX do we need a vce_v3_0_stop()? */
  563. return 0;
  564. else
  565. return vce_v3_0_start(adev);
  566. }
  567. const struct amd_ip_funcs vce_v3_0_ip_funcs = {
  568. .early_init = vce_v3_0_early_init,
  569. .late_init = NULL,
  570. .sw_init = vce_v3_0_sw_init,
  571. .sw_fini = vce_v3_0_sw_fini,
  572. .hw_init = vce_v3_0_hw_init,
  573. .hw_fini = vce_v3_0_hw_fini,
  574. .suspend = vce_v3_0_suspend,
  575. .resume = vce_v3_0_resume,
  576. .is_idle = vce_v3_0_is_idle,
  577. .wait_for_idle = vce_v3_0_wait_for_idle,
  578. .soft_reset = vce_v3_0_soft_reset,
  579. .set_clockgating_state = vce_v3_0_set_clockgating_state,
  580. .set_powergating_state = vce_v3_0_set_powergating_state,
  581. };
  582. static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = {
  583. .get_rptr = vce_v3_0_ring_get_rptr,
  584. .get_wptr = vce_v3_0_ring_get_wptr,
  585. .set_wptr = vce_v3_0_ring_set_wptr,
  586. .parse_cs = amdgpu_vce_ring_parse_cs,
  587. .emit_ib = amdgpu_vce_ring_emit_ib,
  588. .emit_fence = amdgpu_vce_ring_emit_fence,
  589. .test_ring = amdgpu_vce_ring_test_ring,
  590. .test_ib = amdgpu_vce_ring_test_ib,
  591. .insert_nop = amdgpu_ring_insert_nop,
  592. .pad_ib = amdgpu_ring_generic_pad_ib,
  593. };
  594. static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)
  595. {
  596. adev->vce.ring[0].funcs = &vce_v3_0_ring_funcs;
  597. adev->vce.ring[1].funcs = &vce_v3_0_ring_funcs;
  598. }
  599. static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = {
  600. .set = vce_v3_0_set_interrupt_state,
  601. .process = vce_v3_0_process_interrupt,
  602. };
  603. static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev)
  604. {
  605. adev->vce.irq.num_types = 1;
  606. adev->vce.irq.funcs = &vce_v3_0_irq_funcs;
  607. };