1dfd57dbfSLeo Liu /*
2dfd57dbfSLeo Liu * Copyright 2019 Advanced Micro Devices, Inc.
3dfd57dbfSLeo Liu *
4dfd57dbfSLeo Liu * Permission is hereby granted, free of charge, to any person obtaining a
5dfd57dbfSLeo Liu * copy of this software and associated documentation files (the "Software"),
6dfd57dbfSLeo Liu * to deal in the Software without restriction, including without limitation
7dfd57dbfSLeo Liu * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8dfd57dbfSLeo Liu * and/or sell copies of the Software, and to permit persons to whom the
9dfd57dbfSLeo Liu * Software is furnished to do so, subject to the following conditions:
10dfd57dbfSLeo Liu *
11dfd57dbfSLeo Liu * The above copyright notice and this permission notice shall be included in
12dfd57dbfSLeo Liu * all copies or substantial portions of the Software.
13dfd57dbfSLeo Liu *
14dfd57dbfSLeo Liu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15dfd57dbfSLeo Liu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16dfd57dbfSLeo Liu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17dfd57dbfSLeo Liu * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18dfd57dbfSLeo Liu * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19dfd57dbfSLeo Liu * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20dfd57dbfSLeo Liu * OTHER DEALINGS IN THE SOFTWARE.
21dfd57dbfSLeo Liu *
22dfd57dbfSLeo Liu */
23dfd57dbfSLeo Liu
24dfd57dbfSLeo Liu #include "amdgpu.h"
25dfd57dbfSLeo Liu #include "amdgpu_jpeg.h"
26dfd57dbfSLeo Liu #include "amdgpu_pm.h"
27dfd57dbfSLeo Liu #include "soc15.h"
28dfd57dbfSLeo Liu #include "soc15d.h"
29dfd57dbfSLeo Liu #include "jpeg_v2_0.h"
30dfd57dbfSLeo Liu
31dfd57dbfSLeo Liu #include "vcn/vcn_3_0_0_offset.h"
32dfd57dbfSLeo Liu #include "vcn/vcn_3_0_0_sh_mask.h"
33dfd57dbfSLeo Liu #include "ivsrcid/vcn/irqsrcs_vcn_2_0.h"
34dfd57dbfSLeo Liu
35dfd57dbfSLeo Liu #define mmUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f
36dfd57dbfSLeo Liu
37dfd57dbfSLeo Liu static void jpeg_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev);
38dfd57dbfSLeo Liu static void jpeg_v3_0_set_irq_funcs(struct amdgpu_device *adev);
39dfd57dbfSLeo Liu static int jpeg_v3_0_set_powergating_state(void *handle,
40dfd57dbfSLeo Liu enum amd_powergating_state state);
41dfd57dbfSLeo Liu
42dfd57dbfSLeo Liu /**
43dfd57dbfSLeo Liu * jpeg_v3_0_early_init - set function pointers
44dfd57dbfSLeo Liu *
45dfd57dbfSLeo Liu * @handle: amdgpu_device pointer
46dfd57dbfSLeo Liu *
47dfd57dbfSLeo Liu * Set ring and irq function pointers
48dfd57dbfSLeo Liu */
jpeg_v3_0_early_init(void * handle)49dfd57dbfSLeo Liu static int jpeg_v3_0_early_init(void *handle)
50dfd57dbfSLeo Liu {
51dfd57dbfSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle;
523d417b58SJames Zhu
5337d6b150STim Huang u32 harvest;
54dfd57dbfSLeo Liu
5537d6b150STim Huang switch (adev->ip_versions[UVD_HWIP][0]) {
5637d6b150STim Huang case IP_VERSION(3, 1, 1):
57c488a937SSaleemkhan Jamadar case IP_VERSION(3, 1, 2):
5837d6b150STim Huang break;
5937d6b150STim Huang default:
6037d6b150STim Huang harvest = RREG32_SOC15(JPEG, 0, mmCC_UVD_HARVESTING);
61dfd57dbfSLeo Liu if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK)
62dfd57dbfSLeo Liu return -ENOENT;
6337d6b150STim Huang break;
643d417b58SJames Zhu }
65156589f7SJames Zhu
66dfd57dbfSLeo Liu adev->jpeg.num_jpeg_inst = 1;
6728bb7f13SJames Zhu adev->jpeg.num_jpeg_rings = 1;
68dfd57dbfSLeo Liu
69dfd57dbfSLeo Liu jpeg_v3_0_set_dec_ring_funcs(adev);
70dfd57dbfSLeo Liu jpeg_v3_0_set_irq_funcs(adev);
71dfd57dbfSLeo Liu
72dfd57dbfSLeo Liu return 0;
73dfd57dbfSLeo Liu }
74dfd57dbfSLeo Liu
75dfd57dbfSLeo Liu /**
76dfd57dbfSLeo Liu * jpeg_v3_0_sw_init - sw init for JPEG block
77dfd57dbfSLeo Liu *
78dfd57dbfSLeo Liu * @handle: amdgpu_device pointer
79dfd57dbfSLeo Liu *
80dfd57dbfSLeo Liu * Load firmware and sw initialization
81dfd57dbfSLeo Liu */
jpeg_v3_0_sw_init(void * handle)82dfd57dbfSLeo Liu static int jpeg_v3_0_sw_init(void *handle)
83dfd57dbfSLeo Liu {
84dfd57dbfSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle;
85dfd57dbfSLeo Liu struct amdgpu_ring *ring;
86dfd57dbfSLeo Liu int r;
87dfd57dbfSLeo Liu
88dfd57dbfSLeo Liu /* JPEG TRAP */
89dfd57dbfSLeo Liu r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
90dfd57dbfSLeo Liu VCN_2_0__SRCID__JPEG_DECODE, &adev->jpeg.inst->irq);
91dfd57dbfSLeo Liu if (r)
92dfd57dbfSLeo Liu return r;
93dfd57dbfSLeo Liu
94dfd57dbfSLeo Liu r = amdgpu_jpeg_sw_init(adev);
95dfd57dbfSLeo Liu if (r)
96dfd57dbfSLeo Liu return r;
97dfd57dbfSLeo Liu
98dfd57dbfSLeo Liu r = amdgpu_jpeg_resume(adev);
99dfd57dbfSLeo Liu if (r)
100dfd57dbfSLeo Liu return r;
101dfd57dbfSLeo Liu
102bc224553SJames Zhu ring = adev->jpeg.inst->ring_dec;
103dfd57dbfSLeo Liu ring->use_doorbell = true;
104dfd57dbfSLeo Liu ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1;
105f4caf584SHawking Zhang ring->vm_hub = AMDGPU_MMHUB0(0);
106dfd57dbfSLeo Liu sprintf(ring->name, "jpeg_dec");
107dfd57dbfSLeo Liu r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0,
108c107171bSChristian König AMDGPU_RING_PRIO_DEFAULT, NULL);
109dfd57dbfSLeo Liu if (r)
110dfd57dbfSLeo Liu return r;
111dfd57dbfSLeo Liu
112bc224553SJames Zhu adev->jpeg.internal.jpeg_pitch[0] = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
113bc224553SJames Zhu adev->jpeg.inst->external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH);
114dfd57dbfSLeo Liu
115dfd57dbfSLeo Liu return 0;
116dfd57dbfSLeo Liu }
117dfd57dbfSLeo Liu
118dfd57dbfSLeo Liu /**
119dfd57dbfSLeo Liu * jpeg_v3_0_sw_fini - sw fini for JPEG block
120dfd57dbfSLeo Liu *
121dfd57dbfSLeo Liu * @handle: amdgpu_device pointer
122dfd57dbfSLeo Liu *
123dfd57dbfSLeo Liu * JPEG suspend and free up sw allocation
124dfd57dbfSLeo Liu */
jpeg_v3_0_sw_fini(void * handle)125dfd57dbfSLeo Liu static int jpeg_v3_0_sw_fini(void *handle)
126dfd57dbfSLeo Liu {
127dfd57dbfSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle;
128dfd57dbfSLeo Liu int r;
129dfd57dbfSLeo Liu
130dfd57dbfSLeo Liu r = amdgpu_jpeg_suspend(adev);
131dfd57dbfSLeo Liu if (r)
132dfd57dbfSLeo Liu return r;
133dfd57dbfSLeo Liu
134dfd57dbfSLeo Liu r = amdgpu_jpeg_sw_fini(adev);
135dfd57dbfSLeo Liu
136dfd57dbfSLeo Liu return r;
137dfd57dbfSLeo Liu }
138dfd57dbfSLeo Liu
139dfd57dbfSLeo Liu /**
140dfd57dbfSLeo Liu * jpeg_v3_0_hw_init - start and test JPEG block
141dfd57dbfSLeo Liu *
142dfd57dbfSLeo Liu * @handle: amdgpu_device pointer
143dfd57dbfSLeo Liu *
144dfd57dbfSLeo Liu */
jpeg_v3_0_hw_init(void * handle)145dfd57dbfSLeo Liu static int jpeg_v3_0_hw_init(void *handle)
146dfd57dbfSLeo Liu {
147dfd57dbfSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle;
148bc224553SJames Zhu struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
149dfd57dbfSLeo Liu int r;
150dfd57dbfSLeo Liu
151dfd57dbfSLeo Liu adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
152dfd57dbfSLeo Liu (adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
153dfd57dbfSLeo Liu
154dfd57dbfSLeo Liu r = amdgpu_ring_test_helper(ring);
155dfd57dbfSLeo Liu if (r)
156dfd57dbfSLeo Liu return r;
157dfd57dbfSLeo Liu
158dfd57dbfSLeo Liu DRM_INFO("JPEG decode initialized successfully.\n");
159dfd57dbfSLeo Liu
160dfd57dbfSLeo Liu return 0;
161dfd57dbfSLeo Liu }
162dfd57dbfSLeo Liu
163dfd57dbfSLeo Liu /**
164dfd57dbfSLeo Liu * jpeg_v3_0_hw_fini - stop the hardware block
165dfd57dbfSLeo Liu *
166dfd57dbfSLeo Liu * @handle: amdgpu_device pointer
167dfd57dbfSLeo Liu *
168dfd57dbfSLeo Liu * Stop the JPEG block, mark ring as not ready any more
169dfd57dbfSLeo Liu */
jpeg_v3_0_hw_fini(void * handle)170dfd57dbfSLeo Liu static int jpeg_v3_0_hw_fini(void *handle)
171dfd57dbfSLeo Liu {
172dfd57dbfSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle;
173dfd57dbfSLeo Liu
174223ce1d5SJames Zhu cancel_delayed_work_sync(&adev->vcn.idle_work);
175223ce1d5SJames Zhu
176dfd57dbfSLeo Liu if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
177dfd57dbfSLeo Liu RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS))
178dfd57dbfSLeo Liu jpeg_v3_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
179dfd57dbfSLeo Liu
180dfd57dbfSLeo Liu return 0;
181dfd57dbfSLeo Liu }
182dfd57dbfSLeo Liu
183dfd57dbfSLeo Liu /**
184dfd57dbfSLeo Liu * jpeg_v3_0_suspend - suspend JPEG block
185dfd57dbfSLeo Liu *
186dfd57dbfSLeo Liu * @handle: amdgpu_device pointer
187dfd57dbfSLeo Liu *
188dfd57dbfSLeo Liu * HW fini and suspend JPEG block
189dfd57dbfSLeo Liu */
jpeg_v3_0_suspend(void * handle)190dfd57dbfSLeo Liu static int jpeg_v3_0_suspend(void *handle)
191dfd57dbfSLeo Liu {
192dfd57dbfSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle;
193dfd57dbfSLeo Liu int r;
194dfd57dbfSLeo Liu
195dfd57dbfSLeo Liu r = jpeg_v3_0_hw_fini(adev);
196dfd57dbfSLeo Liu if (r)
197dfd57dbfSLeo Liu return r;
198dfd57dbfSLeo Liu
199dfd57dbfSLeo Liu r = amdgpu_jpeg_suspend(adev);
200dfd57dbfSLeo Liu
201dfd57dbfSLeo Liu return r;
202dfd57dbfSLeo Liu }
203dfd57dbfSLeo Liu
204dfd57dbfSLeo Liu /**
205dfd57dbfSLeo Liu * jpeg_v3_0_resume - resume JPEG block
206dfd57dbfSLeo Liu *
207dfd57dbfSLeo Liu * @handle: amdgpu_device pointer
208dfd57dbfSLeo Liu *
209dfd57dbfSLeo Liu * Resume firmware and hw init JPEG block
210dfd57dbfSLeo Liu */
jpeg_v3_0_resume(void * handle)211dfd57dbfSLeo Liu static int jpeg_v3_0_resume(void *handle)
212dfd57dbfSLeo Liu {
213dfd57dbfSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle;
214dfd57dbfSLeo Liu int r;
215dfd57dbfSLeo Liu
216dfd57dbfSLeo Liu r = amdgpu_jpeg_resume(adev);
217dfd57dbfSLeo Liu if (r)
218dfd57dbfSLeo Liu return r;
219dfd57dbfSLeo Liu
220dfd57dbfSLeo Liu r = jpeg_v3_0_hw_init(adev);
221dfd57dbfSLeo Liu
222dfd57dbfSLeo Liu return r;
223dfd57dbfSLeo Liu }
224dfd57dbfSLeo Liu
jpeg_v3_0_disable_clock_gating(struct amdgpu_device * adev)225b52e271eSLeo Liu static void jpeg_v3_0_disable_clock_gating(struct amdgpu_device *adev)
226b52e271eSLeo Liu {
227b52e271eSLeo Liu uint32_t data = 0;
228b52e271eSLeo Liu
229b52e271eSLeo Liu data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL);
230b52e271eSLeo Liu if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG)
231b52e271eSLeo Liu data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
232b52e271eSLeo Liu else
233b52e271eSLeo Liu data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
234b52e271eSLeo Liu
235b52e271eSLeo Liu data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
236b52e271eSLeo Liu data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
237b52e271eSLeo Liu WREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL, data);
238b52e271eSLeo Liu
239b52e271eSLeo Liu data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE);
240b52e271eSLeo Liu data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK
241b52e271eSLeo Liu | JPEG_CGC_GATE__JPEG2_DEC_MASK
242b52e271eSLeo Liu | JPEG_CGC_GATE__JPEG_ENC_MASK
243b52e271eSLeo Liu | JPEG_CGC_GATE__JMCIF_MASK
244b52e271eSLeo Liu | JPEG_CGC_GATE__JRBBM_MASK);
245b52e271eSLeo Liu WREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE, data);
246b52e271eSLeo Liu
247b52e271eSLeo Liu data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL);
248b52e271eSLeo Liu data &= ~(JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK
249b52e271eSLeo Liu | JPEG_CGC_CTRL__JPEG2_DEC_MODE_MASK
250b52e271eSLeo Liu | JPEG_CGC_CTRL__JMCIF_MODE_MASK
251b52e271eSLeo Liu | JPEG_CGC_CTRL__JRBBM_MODE_MASK);
252b52e271eSLeo Liu WREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL, data);
253b52e271eSLeo Liu }
254b52e271eSLeo Liu
jpeg_v3_0_enable_clock_gating(struct amdgpu_device * adev)255b52e271eSLeo Liu static void jpeg_v3_0_enable_clock_gating(struct amdgpu_device *adev)
256b52e271eSLeo Liu {
257b52e271eSLeo Liu uint32_t data = 0;
258b52e271eSLeo Liu
259b52e271eSLeo Liu data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE);
260b52e271eSLeo Liu data |= (JPEG_CGC_GATE__JPEG_DEC_MASK
261b52e271eSLeo Liu |JPEG_CGC_GATE__JPEG2_DEC_MASK
262b52e271eSLeo Liu |JPEG_CGC_GATE__JPEG_ENC_MASK
263b52e271eSLeo Liu |JPEG_CGC_GATE__JMCIF_MASK
264b52e271eSLeo Liu |JPEG_CGC_GATE__JRBBM_MASK);
265b52e271eSLeo Liu WREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE, data);
266b52e271eSLeo Liu }
267b52e271eSLeo Liu
jpeg_v3_0_disable_static_power_gating(struct amdgpu_device * adev)268b52e271eSLeo Liu static int jpeg_v3_0_disable_static_power_gating(struct amdgpu_device *adev)
269b52e271eSLeo Liu {
270b52e271eSLeo Liu if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {
271b52e271eSLeo Liu uint32_t data = 0;
272b52e271eSLeo Liu int r = 0;
273b52e271eSLeo Liu
274b52e271eSLeo Liu data = 1 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT;
275b52e271eSLeo Liu WREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_PGFSM_CONFIG), data);
276b52e271eSLeo Liu
277450da2efSJames Zhu r = SOC15_WAIT_ON_RREG(JPEG, 0,
278b52e271eSLeo Liu mmUVD_PGFSM_STATUS, UVD_PGFSM_STATUS_UVDJ_PWR_ON,
279450da2efSJames Zhu UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK);
280b52e271eSLeo Liu
281b52e271eSLeo Liu if (r) {
282b52e271eSLeo Liu DRM_ERROR("amdgpu: JPEG disable power gating failed\n");
283b52e271eSLeo Liu return r;
284b52e271eSLeo Liu }
285b52e271eSLeo Liu }
286b52e271eSLeo Liu
287b52e271eSLeo Liu /* disable anti hang mechanism */
288b52e271eSLeo Liu WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS), 0,
289b52e271eSLeo Liu ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
290b52e271eSLeo Liu
291b52e271eSLeo Liu /* keep the JPEG in static PG mode */
292b52e271eSLeo Liu WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS), 0,
293b52e271eSLeo Liu ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK);
294b52e271eSLeo Liu
295b52e271eSLeo Liu return 0;
296b52e271eSLeo Liu }
297b52e271eSLeo Liu
jpeg_v3_0_enable_static_power_gating(struct amdgpu_device * adev)298b52e271eSLeo Liu static int jpeg_v3_0_enable_static_power_gating(struct amdgpu_device *adev)
299b52e271eSLeo Liu {
300b52e271eSLeo Liu /* enable anti hang mechanism */
301b52e271eSLeo Liu WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS),
302b52e271eSLeo Liu UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
303b52e271eSLeo Liu ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
304b52e271eSLeo Liu
305b52e271eSLeo Liu if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {
306b52e271eSLeo Liu uint32_t data = 0;
307b52e271eSLeo Liu int r = 0;
308b52e271eSLeo Liu
309b52e271eSLeo Liu data = 2 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT;
310b52e271eSLeo Liu WREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_PGFSM_CONFIG), data);
311b52e271eSLeo Liu
312450da2efSJames Zhu r = SOC15_WAIT_ON_RREG(JPEG, 0, mmUVD_PGFSM_STATUS,
313b52e271eSLeo Liu (2 << UVD_PGFSM_STATUS__UVDJ_PWR_STATUS__SHIFT),
314450da2efSJames Zhu UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK);
315b52e271eSLeo Liu
316b52e271eSLeo Liu if (r) {
317b52e271eSLeo Liu DRM_ERROR("amdgpu: JPEG enable power gating failed\n");
318b52e271eSLeo Liu return r;
319b52e271eSLeo Liu }
320b52e271eSLeo Liu }
321b52e271eSLeo Liu
322b52e271eSLeo Liu return 0;
323b52e271eSLeo Liu }
324b52e271eSLeo Liu
325dfd57dbfSLeo Liu /**
326dfd57dbfSLeo Liu * jpeg_v3_0_start - start JPEG block
327dfd57dbfSLeo Liu *
328dfd57dbfSLeo Liu * @adev: amdgpu_device pointer
329dfd57dbfSLeo Liu *
330dfd57dbfSLeo Liu * Setup and start the JPEG block
331dfd57dbfSLeo Liu */
jpeg_v3_0_start(struct amdgpu_device * adev)332dfd57dbfSLeo Liu static int jpeg_v3_0_start(struct amdgpu_device *adev)
333dfd57dbfSLeo Liu {
334bc224553SJames Zhu struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
335b52e271eSLeo Liu int r;
336dfd57dbfSLeo Liu
337dfd57dbfSLeo Liu if (adev->pm.dpm_enabled)
338dfd57dbfSLeo Liu amdgpu_dpm_enable_jpeg(adev, true);
339dfd57dbfSLeo Liu
340b52e271eSLeo Liu /* disable power gating */
341b52e271eSLeo Liu r = jpeg_v3_0_disable_static_power_gating(adev);
342b52e271eSLeo Liu if (r)
343b52e271eSLeo Liu return r;
344b52e271eSLeo Liu
345b52e271eSLeo Liu /* JPEG disable CGC */
346b52e271eSLeo Liu jpeg_v3_0_disable_clock_gating(adev);
347b52e271eSLeo Liu
348dfd57dbfSLeo Liu /* MJPEG global tiling registers */
349dfd57dbfSLeo Liu WREG32_SOC15(JPEG, 0, mmJPEG_DEC_GFX10_ADDR_CONFIG,
350dfd57dbfSLeo Liu adev->gfx.config.gb_addr_config);
351dfd57dbfSLeo Liu WREG32_SOC15(JPEG, 0, mmJPEG_ENC_GFX10_ADDR_CONFIG,
352dfd57dbfSLeo Liu adev->gfx.config.gb_addr_config);
353dfd57dbfSLeo Liu
354dfd57dbfSLeo Liu /* enable JMI channel */
355dfd57dbfSLeo Liu WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JMI_CNTL), 0,
356dfd57dbfSLeo Liu ~UVD_JMI_CNTL__SOFT_RESET_MASK);
357dfd57dbfSLeo Liu
358dfd57dbfSLeo Liu /* enable System Interrupt for JRBC */
359dfd57dbfSLeo Liu WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmJPEG_SYS_INT_EN),
360dfd57dbfSLeo Liu JPEG_SYS_INT_EN__DJRBC_MASK,
361dfd57dbfSLeo Liu ~JPEG_SYS_INT_EN__DJRBC_MASK);
362dfd57dbfSLeo Liu
363dfd57dbfSLeo Liu WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
364dfd57dbfSLeo Liu WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
365dfd57dbfSLeo Liu WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
366dfd57dbfSLeo Liu lower_32_bits(ring->gpu_addr));
367dfd57dbfSLeo Liu WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
368dfd57dbfSLeo Liu upper_32_bits(ring->gpu_addr));
369dfd57dbfSLeo Liu WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR, 0);
370dfd57dbfSLeo Liu WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, 0);
371dfd57dbfSLeo Liu WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, 0x00000002L);
372dfd57dbfSLeo Liu WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_SIZE, ring->ring_size / 4);
373dfd57dbfSLeo Liu ring->wptr = RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR);
374dfd57dbfSLeo Liu
375dfd57dbfSLeo Liu return 0;
376dfd57dbfSLeo Liu }
377dfd57dbfSLeo Liu
378dfd57dbfSLeo Liu /**
379dfd57dbfSLeo Liu * jpeg_v3_0_stop - stop JPEG block
380dfd57dbfSLeo Liu *
381dfd57dbfSLeo Liu * @adev: amdgpu_device pointer
382dfd57dbfSLeo Liu *
383dfd57dbfSLeo Liu * stop the JPEG block
384dfd57dbfSLeo Liu */
jpeg_v3_0_stop(struct amdgpu_device * adev)385dfd57dbfSLeo Liu static int jpeg_v3_0_stop(struct amdgpu_device *adev)
386dfd57dbfSLeo Liu {
387b52e271eSLeo Liu int r;
388b52e271eSLeo Liu
389dfd57dbfSLeo Liu /* reset JMI */
390dfd57dbfSLeo Liu WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JMI_CNTL),
391dfd57dbfSLeo Liu UVD_JMI_CNTL__SOFT_RESET_MASK,
392dfd57dbfSLeo Liu ~UVD_JMI_CNTL__SOFT_RESET_MASK);
393dfd57dbfSLeo Liu
394b52e271eSLeo Liu jpeg_v3_0_enable_clock_gating(adev);
395b52e271eSLeo Liu
396b52e271eSLeo Liu /* enable power gating */
397b52e271eSLeo Liu r = jpeg_v3_0_enable_static_power_gating(adev);
398b52e271eSLeo Liu if (r)
399b52e271eSLeo Liu return r;
400b52e271eSLeo Liu
401dfd57dbfSLeo Liu if (adev->pm.dpm_enabled)
402dfd57dbfSLeo Liu amdgpu_dpm_enable_jpeg(adev, false);
403dfd57dbfSLeo Liu
404dfd57dbfSLeo Liu return 0;
405dfd57dbfSLeo Liu }
406dfd57dbfSLeo Liu
407dfd57dbfSLeo Liu /**
408dfd57dbfSLeo Liu * jpeg_v3_0_dec_ring_get_rptr - get read pointer
409dfd57dbfSLeo Liu *
410dfd57dbfSLeo Liu * @ring: amdgpu_ring pointer
411dfd57dbfSLeo Liu *
412dfd57dbfSLeo Liu * Returns the current hardware read pointer
413dfd57dbfSLeo Liu */
jpeg_v3_0_dec_ring_get_rptr(struct amdgpu_ring * ring)414dfd57dbfSLeo Liu static uint64_t jpeg_v3_0_dec_ring_get_rptr(struct amdgpu_ring *ring)
415dfd57dbfSLeo Liu {
416dfd57dbfSLeo Liu struct amdgpu_device *adev = ring->adev;
417dfd57dbfSLeo Liu
418dfd57dbfSLeo Liu return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR);
419dfd57dbfSLeo Liu }
420dfd57dbfSLeo Liu
421dfd57dbfSLeo Liu /**
422dfd57dbfSLeo Liu * jpeg_v3_0_dec_ring_get_wptr - get write pointer
423dfd57dbfSLeo Liu *
424dfd57dbfSLeo Liu * @ring: amdgpu_ring pointer
425dfd57dbfSLeo Liu *
426dfd57dbfSLeo Liu * Returns the current hardware write pointer
427dfd57dbfSLeo Liu */
jpeg_v3_0_dec_ring_get_wptr(struct amdgpu_ring * ring)428dfd57dbfSLeo Liu static uint64_t jpeg_v3_0_dec_ring_get_wptr(struct amdgpu_ring *ring)
429dfd57dbfSLeo Liu {
430dfd57dbfSLeo Liu struct amdgpu_device *adev = ring->adev;
431dfd57dbfSLeo Liu
432dfd57dbfSLeo Liu if (ring->use_doorbell)
4333748424bSJack Xiao return *ring->wptr_cpu_addr;
434dfd57dbfSLeo Liu else
435dfd57dbfSLeo Liu return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR);
436dfd57dbfSLeo Liu }
437dfd57dbfSLeo Liu
438dfd57dbfSLeo Liu /**
439dfd57dbfSLeo Liu * jpeg_v3_0_dec_ring_set_wptr - set write pointer
440dfd57dbfSLeo Liu *
441dfd57dbfSLeo Liu * @ring: amdgpu_ring pointer
442dfd57dbfSLeo Liu *
443dfd57dbfSLeo Liu * Commits the write pointer to the hardware
444dfd57dbfSLeo Liu */
jpeg_v3_0_dec_ring_set_wptr(struct amdgpu_ring * ring)445dfd57dbfSLeo Liu static void jpeg_v3_0_dec_ring_set_wptr(struct amdgpu_ring *ring)
446dfd57dbfSLeo Liu {
447dfd57dbfSLeo Liu struct amdgpu_device *adev = ring->adev;
448dfd57dbfSLeo Liu
449dfd57dbfSLeo Liu if (ring->use_doorbell) {
4503748424bSJack Xiao *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);
451dfd57dbfSLeo Liu WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
452dfd57dbfSLeo Liu } else {
453dfd57dbfSLeo Liu WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
454dfd57dbfSLeo Liu }
455dfd57dbfSLeo Liu }
456dfd57dbfSLeo Liu
jpeg_v3_0_is_idle(void * handle)457dfd57dbfSLeo Liu static bool jpeg_v3_0_is_idle(void *handle)
458dfd57dbfSLeo Liu {
459dfd57dbfSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle;
460dfd57dbfSLeo Liu int ret = 1;
461dfd57dbfSLeo Liu
462dfd57dbfSLeo Liu ret &= (((RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS) &
463dfd57dbfSLeo Liu UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==
464dfd57dbfSLeo Liu UVD_JRBC_STATUS__RB_JOB_DONE_MASK));
465dfd57dbfSLeo Liu
466dfd57dbfSLeo Liu return ret;
467dfd57dbfSLeo Liu }
468dfd57dbfSLeo Liu
jpeg_v3_0_wait_for_idle(void * handle)469dfd57dbfSLeo Liu static int jpeg_v3_0_wait_for_idle(void *handle)
470dfd57dbfSLeo Liu {
471dfd57dbfSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle;
472dfd57dbfSLeo Liu
473cdab4211SLeo Liu return SOC15_WAIT_ON_RREG(JPEG, 0, mmUVD_JRBC_STATUS,
474dfd57dbfSLeo Liu UVD_JRBC_STATUS__RB_JOB_DONE_MASK,
475450da2efSJames Zhu UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
476dfd57dbfSLeo Liu }
477dfd57dbfSLeo Liu
jpeg_v3_0_set_clockgating_state(void * handle,enum amd_clockgating_state state)478dfd57dbfSLeo Liu static int jpeg_v3_0_set_clockgating_state(void *handle,
479dfd57dbfSLeo Liu enum amd_clockgating_state state)
480dfd57dbfSLeo Liu {
481b52e271eSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle;
482*3b780089SRuan Jinjie bool enable = state == AMD_CG_STATE_GATE;
483b52e271eSLeo Liu
484b52e271eSLeo Liu if (enable) {
485df3183b3SJames Zhu if (!jpeg_v3_0_is_idle(handle))
486b52e271eSLeo Liu return -EBUSY;
487b52e271eSLeo Liu jpeg_v3_0_enable_clock_gating(adev);
488b52e271eSLeo Liu } else {
489b52e271eSLeo Liu jpeg_v3_0_disable_clock_gating(adev);
490b52e271eSLeo Liu }
491b52e271eSLeo Liu
492dfd57dbfSLeo Liu return 0;
493dfd57dbfSLeo Liu }
494dfd57dbfSLeo Liu
jpeg_v3_0_set_powergating_state(void * handle,enum amd_powergating_state state)495dfd57dbfSLeo Liu static int jpeg_v3_0_set_powergating_state(void *handle,
496dfd57dbfSLeo Liu enum amd_powergating_state state)
497dfd57dbfSLeo Liu {
498dfd57dbfSLeo Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle;
499dfd57dbfSLeo Liu int ret;
500dfd57dbfSLeo Liu
501dfd57dbfSLeo Liu if(state == adev->jpeg.cur_state)
502dfd57dbfSLeo Liu return 0;
503dfd57dbfSLeo Liu
504dfd57dbfSLeo Liu if (state == AMD_PG_STATE_GATE)
505dfd57dbfSLeo Liu ret = jpeg_v3_0_stop(adev);
506dfd57dbfSLeo Liu else
507dfd57dbfSLeo Liu ret = jpeg_v3_0_start(adev);
508dfd57dbfSLeo Liu
509dfd57dbfSLeo Liu if(!ret)
510dfd57dbfSLeo Liu adev->jpeg.cur_state = state;
511dfd57dbfSLeo Liu
512dfd57dbfSLeo Liu return ret;
513dfd57dbfSLeo Liu }
514dfd57dbfSLeo Liu
jpeg_v3_0_set_interrupt_state(struct amdgpu_device * adev,struct amdgpu_irq_src * source,unsigned type,enum amdgpu_interrupt_state state)515dfd57dbfSLeo Liu static int jpeg_v3_0_set_interrupt_state(struct amdgpu_device *adev,
516dfd57dbfSLeo Liu struct amdgpu_irq_src *source,
517dfd57dbfSLeo Liu unsigned type,
518dfd57dbfSLeo Liu enum amdgpu_interrupt_state state)
519dfd57dbfSLeo Liu {
520dfd57dbfSLeo Liu return 0;
521dfd57dbfSLeo Liu }
522dfd57dbfSLeo Liu
jpeg_v3_0_process_interrupt(struct amdgpu_device * adev,struct amdgpu_irq_src * source,struct amdgpu_iv_entry * entry)523dfd57dbfSLeo Liu static int jpeg_v3_0_process_interrupt(struct amdgpu_device *adev,
524dfd57dbfSLeo Liu struct amdgpu_irq_src *source,
525dfd57dbfSLeo Liu struct amdgpu_iv_entry *entry)
526dfd57dbfSLeo Liu {
527dfd57dbfSLeo Liu DRM_DEBUG("IH: JPEG TRAP\n");
528dfd57dbfSLeo Liu
529dfd57dbfSLeo Liu switch (entry->src_id) {
530dfd57dbfSLeo Liu case VCN_2_0__SRCID__JPEG_DECODE:
531bc224553SJames Zhu amdgpu_fence_process(adev->jpeg.inst->ring_dec);
532dfd57dbfSLeo Liu break;
533dfd57dbfSLeo Liu default:
534dfd57dbfSLeo Liu DRM_ERROR("Unhandled interrupt: %d %d\n",
535dfd57dbfSLeo Liu entry->src_id, entry->src_data[0]);
536dfd57dbfSLeo Liu break;
537dfd57dbfSLeo Liu }
538dfd57dbfSLeo Liu
539dfd57dbfSLeo Liu return 0;
540dfd57dbfSLeo Liu }
541dfd57dbfSLeo Liu
542dfd57dbfSLeo Liu static const struct amd_ip_funcs jpeg_v3_0_ip_funcs = {
543dfd57dbfSLeo Liu .name = "jpeg_v3_0",
544dfd57dbfSLeo Liu .early_init = jpeg_v3_0_early_init,
545dfd57dbfSLeo Liu .late_init = NULL,
546dfd57dbfSLeo Liu .sw_init = jpeg_v3_0_sw_init,
547dfd57dbfSLeo Liu .sw_fini = jpeg_v3_0_sw_fini,
548dfd57dbfSLeo Liu .hw_init = jpeg_v3_0_hw_init,
549dfd57dbfSLeo Liu .hw_fini = jpeg_v3_0_hw_fini,
550dfd57dbfSLeo Liu .suspend = jpeg_v3_0_suspend,
551dfd57dbfSLeo Liu .resume = jpeg_v3_0_resume,
552dfd57dbfSLeo Liu .is_idle = jpeg_v3_0_is_idle,
553dfd57dbfSLeo Liu .wait_for_idle = jpeg_v3_0_wait_for_idle,
554dfd57dbfSLeo Liu .check_soft_reset = NULL,
555dfd57dbfSLeo Liu .pre_soft_reset = NULL,
556dfd57dbfSLeo Liu .soft_reset = NULL,
557dfd57dbfSLeo Liu .post_soft_reset = NULL,
558dfd57dbfSLeo Liu .set_clockgating_state = jpeg_v3_0_set_clockgating_state,
559dfd57dbfSLeo Liu .set_powergating_state = jpeg_v3_0_set_powergating_state,
560dfd57dbfSLeo Liu };
561dfd57dbfSLeo Liu
562dfd57dbfSLeo Liu static const struct amdgpu_ring_funcs jpeg_v3_0_dec_ring_vm_funcs = {
563dfd57dbfSLeo Liu .type = AMDGPU_RING_TYPE_VCN_JPEG,
564dfd57dbfSLeo Liu .align_mask = 0xf,
565dfd57dbfSLeo Liu .get_rptr = jpeg_v3_0_dec_ring_get_rptr,
566dfd57dbfSLeo Liu .get_wptr = jpeg_v3_0_dec_ring_get_wptr,
567dfd57dbfSLeo Liu .set_wptr = jpeg_v3_0_dec_ring_set_wptr,
568dfd57dbfSLeo Liu .emit_frame_size =
569dfd57dbfSLeo Liu SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
570dfd57dbfSLeo Liu SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
571dfd57dbfSLeo Liu 8 + /* jpeg_v3_0_dec_ring_emit_vm_flush */
572dfd57dbfSLeo Liu 18 + 18 + /* jpeg_v3_0_dec_ring_emit_fence x2 vm fence */
573dfd57dbfSLeo Liu 8 + 16,
574dfd57dbfSLeo Liu .emit_ib_size = 22, /* jpeg_v3_0_dec_ring_emit_ib */
575dfd57dbfSLeo Liu .emit_ib = jpeg_v2_0_dec_ring_emit_ib,
576dfd57dbfSLeo Liu .emit_fence = jpeg_v2_0_dec_ring_emit_fence,
577dfd57dbfSLeo Liu .emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,
578dfd57dbfSLeo Liu .test_ring = amdgpu_jpeg_dec_ring_test_ring,
579dfd57dbfSLeo Liu .test_ib = amdgpu_jpeg_dec_ring_test_ib,
580dfd57dbfSLeo Liu .insert_nop = jpeg_v2_0_dec_ring_nop,
581dfd57dbfSLeo Liu .insert_start = jpeg_v2_0_dec_ring_insert_start,
582dfd57dbfSLeo Liu .insert_end = jpeg_v2_0_dec_ring_insert_end,
583dfd57dbfSLeo Liu .pad_ib = amdgpu_ring_generic_pad_ib,
584dfd57dbfSLeo Liu .begin_use = amdgpu_jpeg_ring_begin_use,
585dfd57dbfSLeo Liu .end_use = amdgpu_jpeg_ring_end_use,
586dfd57dbfSLeo Liu .emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,
587dfd57dbfSLeo Liu .emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,
588dfd57dbfSLeo Liu .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
589dfd57dbfSLeo Liu };
590dfd57dbfSLeo Liu
jpeg_v3_0_set_dec_ring_funcs(struct amdgpu_device * adev)591dfd57dbfSLeo Liu static void jpeg_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev)
592dfd57dbfSLeo Liu {
593bc224553SJames Zhu adev->jpeg.inst->ring_dec->funcs = &jpeg_v3_0_dec_ring_vm_funcs;
594dfd57dbfSLeo Liu DRM_INFO("JPEG decode is enabled in VM mode\n");
595dfd57dbfSLeo Liu }
596dfd57dbfSLeo Liu
597dfd57dbfSLeo Liu static const struct amdgpu_irq_src_funcs jpeg_v3_0_irq_funcs = {
598dfd57dbfSLeo Liu .set = jpeg_v3_0_set_interrupt_state,
599dfd57dbfSLeo Liu .process = jpeg_v3_0_process_interrupt,
600dfd57dbfSLeo Liu };
601dfd57dbfSLeo Liu
jpeg_v3_0_set_irq_funcs(struct amdgpu_device * adev)602dfd57dbfSLeo Liu static void jpeg_v3_0_set_irq_funcs(struct amdgpu_device *adev)
603dfd57dbfSLeo Liu {
604dfd57dbfSLeo Liu adev->jpeg.inst->irq.num_types = 1;
605dfd57dbfSLeo Liu adev->jpeg.inst->irq.funcs = &jpeg_v3_0_irq_funcs;
606dfd57dbfSLeo Liu }
607dfd57dbfSLeo Liu
608dfd57dbfSLeo Liu const struct amdgpu_ip_block_version jpeg_v3_0_ip_block =
609dfd57dbfSLeo Liu {
610dfd57dbfSLeo Liu .type = AMD_IP_BLOCK_TYPE_JPEG,
611dfd57dbfSLeo Liu .major = 3,
612dfd57dbfSLeo Liu .minor = 0,
613dfd57dbfSLeo Liu .rev = 0,
614dfd57dbfSLeo Liu .funcs = &jpeg_v3_0_ip_funcs,
615dfd57dbfSLeo Liu };
616