xref: /linux/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c (revision 46040ea8a6a58e5645d91ffa3ead7ed8fd633d56)
114f43e8fSLeo Liu /*
214f43e8fSLeo Liu  * Copyright 2019 Advanced Micro Devices, Inc.
314f43e8fSLeo Liu  *
414f43e8fSLeo Liu  * Permission is hereby granted, free of charge, to any person obtaining a
514f43e8fSLeo Liu  * copy of this software and associated documentation files (the "Software"),
614f43e8fSLeo Liu  * to deal in the Software without restriction, including without limitation
714f43e8fSLeo Liu  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
814f43e8fSLeo Liu  * and/or sell copies of the Software, and to permit persons to whom the
914f43e8fSLeo Liu  * Software is furnished to do so, subject to the following conditions:
1014f43e8fSLeo Liu  *
1114f43e8fSLeo Liu  * The above copyright notice and this permission notice shall be included in
1214f43e8fSLeo Liu  * all copies or substantial portions of the Software.
1314f43e8fSLeo Liu  *
1414f43e8fSLeo Liu  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1514f43e8fSLeo Liu  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1614f43e8fSLeo Liu  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1714f43e8fSLeo Liu  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1814f43e8fSLeo Liu  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1914f43e8fSLeo Liu  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2014f43e8fSLeo Liu  * OTHER DEALINGS IN THE SOFTWARE.
2114f43e8fSLeo Liu  *
2214f43e8fSLeo Liu  */
2314f43e8fSLeo Liu 
2414f43e8fSLeo Liu #include "amdgpu.h"
2514f43e8fSLeo Liu #include "amdgpu_jpeg.h"
2614f43e8fSLeo Liu #include "soc15.h"
2714f43e8fSLeo Liu #include "soc15d.h"
2814f43e8fSLeo Liu #include "jpeg_v2_0.h"
29749831acSMohammad Zafar Ziya #include "jpeg_v2_5.h"
3014f43e8fSLeo Liu 
3114f43e8fSLeo Liu #include "vcn/vcn_2_5_offset.h"
3214f43e8fSLeo Liu #include "vcn/vcn_2_5_sh_mask.h"
3314f43e8fSLeo Liu #include "ivsrcid/vcn/irqsrcs_vcn_2_0.h"
3414f43e8fSLeo Liu 
3514f43e8fSLeo Liu #define mmUVD_JPEG_PITCH_INTERNAL_OFFSET			0x401f
3614f43e8fSLeo Liu 
3714f43e8fSLeo Liu #define JPEG25_MAX_HW_INSTANCES_ARCTURUS			2
3814f43e8fSLeo Liu 
3914f43e8fSLeo Liu static void jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev);
4014f43e8fSLeo Liu static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev);
4114f43e8fSLeo Liu static int jpeg_v2_5_set_powergating_state(void *handle,
4214f43e8fSLeo Liu 				enum amd_powergating_state state);
43749831acSMohammad Zafar Ziya static void jpeg_v2_5_set_ras_funcs(struct amdgpu_device *adev);
4414f43e8fSLeo Liu 
4514f43e8fSLeo Liu static int amdgpu_ih_clientid_jpeg[] = {
4614f43e8fSLeo Liu 	SOC15_IH_CLIENTID_VCN,
4714f43e8fSLeo Liu 	SOC15_IH_CLIENTID_VCN1
4814f43e8fSLeo Liu };
4914f43e8fSLeo Liu 
5014f43e8fSLeo Liu /**
5114f43e8fSLeo Liu  * jpeg_v2_5_early_init - set function pointers
5214f43e8fSLeo Liu  *
5314f43e8fSLeo Liu  * @handle: amdgpu_device pointer
5414f43e8fSLeo Liu  *
5514f43e8fSLeo Liu  * Set ring and irq function pointers
5614f43e8fSLeo Liu  */
jpeg_v2_5_early_init(void * handle)5714f43e8fSLeo Liu static int jpeg_v2_5_early_init(void *handle)
5814f43e8fSLeo Liu {
5914f43e8fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
6014f43e8fSLeo Liu 	u32 harvest;
6114f43e8fSLeo Liu 	int i;
6214f43e8fSLeo Liu 
6328bb7f13SJames Zhu 	adev->jpeg.num_jpeg_rings = 1;
6414f43e8fSLeo Liu 	adev->jpeg.num_jpeg_inst = JPEG25_MAX_HW_INSTANCES_ARCTURUS;
6514f43e8fSLeo Liu 	for (i = 0; i < adev->jpeg.num_jpeg_inst; i++) {
6614f43e8fSLeo Liu 		harvest = RREG32_SOC15(JPEG, i, mmCC_UVD_HARVESTING);
6714f43e8fSLeo Liu 		if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK)
6814f43e8fSLeo Liu 			adev->jpeg.harvest_config |= 1 << i;
6914f43e8fSLeo Liu 	}
7014f43e8fSLeo Liu 	if (adev->jpeg.harvest_config == (AMDGPU_JPEG_HARVEST_JPEG0 |
7114f43e8fSLeo Liu 					 AMDGPU_JPEG_HARVEST_JPEG1))
7214f43e8fSLeo Liu 		return -ENOENT;
7314f43e8fSLeo Liu 
7414f43e8fSLeo Liu 	jpeg_v2_5_set_dec_ring_funcs(adev);
7514f43e8fSLeo Liu 	jpeg_v2_5_set_irq_funcs(adev);
76749831acSMohammad Zafar Ziya 	jpeg_v2_5_set_ras_funcs(adev);
7714f43e8fSLeo Liu 
7814f43e8fSLeo Liu 	return 0;
7914f43e8fSLeo Liu }
8014f43e8fSLeo Liu 
8114f43e8fSLeo Liu /**
8214f43e8fSLeo Liu  * jpeg_v2_5_sw_init - sw init for JPEG block
8314f43e8fSLeo Liu  *
8414f43e8fSLeo Liu  * @handle: amdgpu_device pointer
8514f43e8fSLeo Liu  *
8614f43e8fSLeo Liu  * Load firmware and sw initialization
8714f43e8fSLeo Liu  */
jpeg_v2_5_sw_init(void * handle)8814f43e8fSLeo Liu static int jpeg_v2_5_sw_init(void *handle)
8914f43e8fSLeo Liu {
9014f43e8fSLeo Liu 	struct amdgpu_ring *ring;
9114f43e8fSLeo Liu 	int i, r;
9214f43e8fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
9314f43e8fSLeo Liu 
9414f43e8fSLeo Liu 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
9514f43e8fSLeo Liu 		if (adev->jpeg.harvest_config & (1 << i))
9614f43e8fSLeo Liu 			continue;
9714f43e8fSLeo Liu 
9814f43e8fSLeo Liu 		/* JPEG TRAP */
9914f43e8fSLeo Liu 		r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],
10014f43e8fSLeo Liu 				VCN_2_0__SRCID__JPEG_DECODE, &adev->jpeg.inst[i].irq);
10114f43e8fSLeo Liu 		if (r)
10214f43e8fSLeo Liu 			return r;
1037e0357fcSMohammad Zafar Ziya 
1047e0357fcSMohammad Zafar Ziya 		/* JPEG DJPEG POISON EVENT */
1057e0357fcSMohammad Zafar Ziya 		r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],
106674f90f8SHoratio Zhang 			VCN_2_6__SRCID_DJPEG0_POISON, &adev->jpeg.inst[i].ras_poison_irq);
1077e0357fcSMohammad Zafar Ziya 		if (r)
1087e0357fcSMohammad Zafar Ziya 			return r;
1097e0357fcSMohammad Zafar Ziya 
1107e0357fcSMohammad Zafar Ziya 		/* JPEG EJPEG POISON EVENT */
1117e0357fcSMohammad Zafar Ziya 		r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],
112674f90f8SHoratio Zhang 			VCN_2_6__SRCID_EJPEG0_POISON, &adev->jpeg.inst[i].ras_poison_irq);
1137e0357fcSMohammad Zafar Ziya 		if (r)
1147e0357fcSMohammad Zafar Ziya 			return r;
11514f43e8fSLeo Liu 	}
11614f43e8fSLeo Liu 
11714f43e8fSLeo Liu 	r = amdgpu_jpeg_sw_init(adev);
11814f43e8fSLeo Liu 	if (r)
11914f43e8fSLeo Liu 		return r;
12014f43e8fSLeo Liu 
12114f43e8fSLeo Liu 	r = amdgpu_jpeg_resume(adev);
12214f43e8fSLeo Liu 	if (r)
12314f43e8fSLeo Liu 		return r;
12414f43e8fSLeo Liu 
12514f43e8fSLeo Liu 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
12614f43e8fSLeo Liu 		if (adev->jpeg.harvest_config & (1 << i))
12714f43e8fSLeo Liu 			continue;
12814f43e8fSLeo Liu 
129bc224553SJames Zhu 		ring = adev->jpeg.inst[i].ring_dec;
13014f43e8fSLeo Liu 		ring->use_doorbell = true;
1314e8303cfSLijo Lazar 		if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(2, 5, 0))
132f4caf584SHawking Zhang 			ring->vm_hub = AMDGPU_MMHUB1(0);
1330530553bSLe Ma 		else
134f4caf584SHawking Zhang 			ring->vm_hub = AMDGPU_MMHUB0(0);
13514f43e8fSLeo Liu 		ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1 + 8 * i;
13614f43e8fSLeo Liu 		sprintf(ring->name, "jpeg_dec_%d", i);
1371c6d567bSNirmoy Das 		r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst[i].irq,
138c107171bSChristian König 				     0, AMDGPU_RING_PRIO_DEFAULT, NULL);
13914f43e8fSLeo Liu 		if (r)
14014f43e8fSLeo Liu 			return r;
14114f43e8fSLeo Liu 
142bc224553SJames Zhu 		adev->jpeg.internal.jpeg_pitch[0] = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
143bc224553SJames Zhu 		adev->jpeg.inst[i].external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_PITCH);
14414f43e8fSLeo Liu 	}
14514f43e8fSLeo Liu 
1465640e06eSHawking Zhang 	r = amdgpu_jpeg_ras_sw_init(adev);
1475640e06eSHawking Zhang 	if (r)
1485640e06eSHawking Zhang 		return r;
1495640e06eSHawking Zhang 
15014f43e8fSLeo Liu 	return 0;
15114f43e8fSLeo Liu }
15214f43e8fSLeo Liu 
15314f43e8fSLeo Liu /**
15414f43e8fSLeo Liu  * jpeg_v2_5_sw_fini - sw fini for JPEG block
15514f43e8fSLeo Liu  *
15614f43e8fSLeo Liu  * @handle: amdgpu_device pointer
15714f43e8fSLeo Liu  *
15814f43e8fSLeo Liu  * JPEG suspend and free up sw allocation
15914f43e8fSLeo Liu  */
jpeg_v2_5_sw_fini(void * handle)16014f43e8fSLeo Liu static int jpeg_v2_5_sw_fini(void *handle)
16114f43e8fSLeo Liu {
16214f43e8fSLeo Liu 	int r;
16314f43e8fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
16414f43e8fSLeo Liu 
16514f43e8fSLeo Liu 	r = amdgpu_jpeg_suspend(adev);
16614f43e8fSLeo Liu 	if (r)
16714f43e8fSLeo Liu 		return r;
16814f43e8fSLeo Liu 
16914f43e8fSLeo Liu 	r = amdgpu_jpeg_sw_fini(adev);
17014f43e8fSLeo Liu 
17114f43e8fSLeo Liu 	return r;
17214f43e8fSLeo Liu }
17314f43e8fSLeo Liu 
17414f43e8fSLeo Liu /**
17514f43e8fSLeo Liu  * jpeg_v2_5_hw_init - start and test JPEG block
17614f43e8fSLeo Liu  *
17714f43e8fSLeo Liu  * @handle: amdgpu_device pointer
17814f43e8fSLeo Liu  *
17914f43e8fSLeo Liu  */
jpeg_v2_5_hw_init(void * handle)18014f43e8fSLeo Liu static int jpeg_v2_5_hw_init(void *handle)
18114f43e8fSLeo Liu {
18214f43e8fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
18314f43e8fSLeo Liu 	struct amdgpu_ring *ring;
18414f43e8fSLeo Liu 	int i, r;
18514f43e8fSLeo Liu 
18614f43e8fSLeo Liu 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
18714f43e8fSLeo Liu 		if (adev->jpeg.harvest_config & (1 << i))
18814f43e8fSLeo Liu 			continue;
18914f43e8fSLeo Liu 
190bc224553SJames Zhu 		ring = adev->jpeg.inst[i].ring_dec;
19114f43e8fSLeo Liu 		adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
19214f43e8fSLeo Liu 			(adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i, i);
19314f43e8fSLeo Liu 
19414f43e8fSLeo Liu 		r = amdgpu_ring_test_helper(ring);
19514f43e8fSLeo Liu 		if (r)
19614f43e8fSLeo Liu 			return r;
19714f43e8fSLeo Liu 	}
19814f43e8fSLeo Liu 
19914f43e8fSLeo Liu 	return 0;
20014f43e8fSLeo Liu }
20114f43e8fSLeo Liu 
20214f43e8fSLeo Liu /**
20314f43e8fSLeo Liu  * jpeg_v2_5_hw_fini - stop the hardware block
20414f43e8fSLeo Liu  *
20514f43e8fSLeo Liu  * @handle: amdgpu_device pointer
20614f43e8fSLeo Liu  *
20714f43e8fSLeo Liu  * Stop the JPEG block, mark ring as not ready any more
20814f43e8fSLeo Liu  */
jpeg_v2_5_hw_fini(void * handle)20914f43e8fSLeo Liu static int jpeg_v2_5_hw_fini(void *handle)
21014f43e8fSLeo Liu {
21114f43e8fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
21214f43e8fSLeo Liu 	int i;
21314f43e8fSLeo Liu 
21423f10a57SJames Zhu 	cancel_delayed_work_sync(&adev->vcn.idle_work);
21523f10a57SJames Zhu 
21614f43e8fSLeo Liu 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
21714f43e8fSLeo Liu 		if (adev->jpeg.harvest_config & (1 << i))
21814f43e8fSLeo Liu 			continue;
21914f43e8fSLeo Liu 
22014f43e8fSLeo Liu 		if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
22114f43e8fSLeo Liu 		      RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS))
22214f43e8fSLeo Liu 			jpeg_v2_5_set_powergating_state(adev, AMD_PG_STATE_GATE);
223674f90f8SHoratio Zhang 
224674f90f8SHoratio Zhang 		if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__JPEG))
225674f90f8SHoratio Zhang 			amdgpu_irq_put(adev, &adev->jpeg.inst[i].ras_poison_irq, 0);
22614f43e8fSLeo Liu 	}
22714f43e8fSLeo Liu 
22814f43e8fSLeo Liu 	return 0;
22914f43e8fSLeo Liu }
23014f43e8fSLeo Liu 
23114f43e8fSLeo Liu /**
23214f43e8fSLeo Liu  * jpeg_v2_5_suspend - suspend JPEG block
23314f43e8fSLeo Liu  *
23414f43e8fSLeo Liu  * @handle: amdgpu_device pointer
23514f43e8fSLeo Liu  *
23614f43e8fSLeo Liu  * HW fini and suspend JPEG block
23714f43e8fSLeo Liu  */
jpeg_v2_5_suspend(void * handle)23814f43e8fSLeo Liu static int jpeg_v2_5_suspend(void *handle)
23914f43e8fSLeo Liu {
24014f43e8fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
24114f43e8fSLeo Liu 	int r;
24214f43e8fSLeo Liu 
24314f43e8fSLeo Liu 	r = jpeg_v2_5_hw_fini(adev);
24414f43e8fSLeo Liu 	if (r)
24514f43e8fSLeo Liu 		return r;
24614f43e8fSLeo Liu 
24714f43e8fSLeo Liu 	r = amdgpu_jpeg_suspend(adev);
24814f43e8fSLeo Liu 
24914f43e8fSLeo Liu 	return r;
25014f43e8fSLeo Liu }
25114f43e8fSLeo Liu 
25214f43e8fSLeo Liu /**
25314f43e8fSLeo Liu  * jpeg_v2_5_resume - resume JPEG block
25414f43e8fSLeo Liu  *
25514f43e8fSLeo Liu  * @handle: amdgpu_device pointer
25614f43e8fSLeo Liu  *
25714f43e8fSLeo Liu  * Resume firmware and hw init JPEG block
25814f43e8fSLeo Liu  */
jpeg_v2_5_resume(void * handle)25914f43e8fSLeo Liu static int jpeg_v2_5_resume(void *handle)
26014f43e8fSLeo Liu {
26114f43e8fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
26214f43e8fSLeo Liu 	int r;
26314f43e8fSLeo Liu 
26414f43e8fSLeo Liu 	r = amdgpu_jpeg_resume(adev);
26514f43e8fSLeo Liu 	if (r)
26614f43e8fSLeo Liu 		return r;
26714f43e8fSLeo Liu 
26814f43e8fSLeo Liu 	r = jpeg_v2_5_hw_init(adev);
26914f43e8fSLeo Liu 
27014f43e8fSLeo Liu 	return r;
27114f43e8fSLeo Liu }
27214f43e8fSLeo Liu 
jpeg_v2_5_disable_clock_gating(struct amdgpu_device * adev,int inst)27314f43e8fSLeo Liu static void jpeg_v2_5_disable_clock_gating(struct amdgpu_device *adev, int inst)
27414f43e8fSLeo Liu {
27514f43e8fSLeo Liu 	uint32_t data;
27614f43e8fSLeo Liu 
27714f43e8fSLeo Liu 	data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL);
27814f43e8fSLeo Liu 	if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG)
27914f43e8fSLeo Liu 		data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
28014f43e8fSLeo Liu 	else
28114f43e8fSLeo Liu 		data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
28214f43e8fSLeo Liu 
28314f43e8fSLeo Liu 	data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
28414f43e8fSLeo Liu 	data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
28514f43e8fSLeo Liu 	WREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL, data);
28614f43e8fSLeo Liu 
28714f43e8fSLeo Liu 	data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE);
28814f43e8fSLeo Liu 	data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK
28914f43e8fSLeo Liu 		| JPEG_CGC_GATE__JPEG2_DEC_MASK
29014f43e8fSLeo Liu 		| JPEG_CGC_GATE__JMCIF_MASK
29114f43e8fSLeo Liu 		| JPEG_CGC_GATE__JRBBM_MASK);
29214f43e8fSLeo Liu 	WREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE, data);
29314f43e8fSLeo Liu 
29414f43e8fSLeo Liu 	data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL);
29514f43e8fSLeo Liu 	data &= ~(JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK
29614f43e8fSLeo Liu 		| JPEG_CGC_CTRL__JPEG2_DEC_MODE_MASK
29714f43e8fSLeo Liu 		| JPEG_CGC_CTRL__JMCIF_MODE_MASK
29814f43e8fSLeo Liu 		| JPEG_CGC_CTRL__JRBBM_MODE_MASK);
29914f43e8fSLeo Liu 	WREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL, data);
30014f43e8fSLeo Liu }
30114f43e8fSLeo Liu 
jpeg_v2_5_enable_clock_gating(struct amdgpu_device * adev,int inst)30214f43e8fSLeo Liu static void jpeg_v2_5_enable_clock_gating(struct amdgpu_device *adev, int inst)
30314f43e8fSLeo Liu {
30414f43e8fSLeo Liu 	uint32_t data;
30514f43e8fSLeo Liu 
30614f43e8fSLeo Liu 	data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE);
30714f43e8fSLeo Liu 	data |= (JPEG_CGC_GATE__JPEG_DEC_MASK
30814f43e8fSLeo Liu 		|JPEG_CGC_GATE__JPEG2_DEC_MASK
30914f43e8fSLeo Liu 		|JPEG_CGC_GATE__JPEG_ENC_MASK
31014f43e8fSLeo Liu 		|JPEG_CGC_GATE__JMCIF_MASK
31114f43e8fSLeo Liu 		|JPEG_CGC_GATE__JRBBM_MASK);
31214f43e8fSLeo Liu 	WREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE, data);
31314f43e8fSLeo Liu }
31414f43e8fSLeo Liu 
31514f43e8fSLeo Liu /**
31614f43e8fSLeo Liu  * jpeg_v2_5_start - start JPEG block
31714f43e8fSLeo Liu  *
31814f43e8fSLeo Liu  * @adev: amdgpu_device pointer
31914f43e8fSLeo Liu  *
32014f43e8fSLeo Liu  * Setup and start the JPEG block
32114f43e8fSLeo Liu  */
jpeg_v2_5_start(struct amdgpu_device * adev)32214f43e8fSLeo Liu static int jpeg_v2_5_start(struct amdgpu_device *adev)
32314f43e8fSLeo Liu {
32414f43e8fSLeo Liu 	struct amdgpu_ring *ring;
32514f43e8fSLeo Liu 	int i;
32614f43e8fSLeo Liu 
32714f43e8fSLeo Liu 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
32814f43e8fSLeo Liu 		if (adev->jpeg.harvest_config & (1 << i))
32914f43e8fSLeo Liu 			continue;
33014f43e8fSLeo Liu 
331bc224553SJames Zhu 		ring = adev->jpeg.inst[i].ring_dec;
33214f43e8fSLeo Liu 		/* disable anti hang mechanism */
33314f43e8fSLeo Liu 		WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_POWER_STATUS), 0,
33414f43e8fSLeo Liu 			~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
33514f43e8fSLeo Liu 
33614f43e8fSLeo Liu 		/* JPEG disable CGC */
33714f43e8fSLeo Liu 		jpeg_v2_5_disable_clock_gating(adev, i);
33814f43e8fSLeo Liu 
33914f43e8fSLeo Liu 		/* MJPEG global tiling registers */
34014f43e8fSLeo Liu 		WREG32_SOC15(JPEG, i, mmJPEG_DEC_GFX8_ADDR_CONFIG,
34114f43e8fSLeo Liu 			adev->gfx.config.gb_addr_config);
34214f43e8fSLeo Liu 		WREG32_SOC15(JPEG, i, mmJPEG_DEC_GFX10_ADDR_CONFIG,
34314f43e8fSLeo Liu 			adev->gfx.config.gb_addr_config);
34414f43e8fSLeo Liu 
34514f43e8fSLeo Liu 		/* enable JMI channel */
34614f43e8fSLeo Liu 		WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JMI_CNTL), 0,
34714f43e8fSLeo Liu 			~UVD_JMI_CNTL__SOFT_RESET_MASK);
34814f43e8fSLeo Liu 
34914f43e8fSLeo Liu 		/* enable System Interrupt for JRBC */
35014f43e8fSLeo Liu 		WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmJPEG_SYS_INT_EN),
35114f43e8fSLeo Liu 			JPEG_SYS_INT_EN__DJRBC_MASK,
35214f43e8fSLeo Liu 			~JPEG_SYS_INT_EN__DJRBC_MASK);
35314f43e8fSLeo Liu 
35414f43e8fSLeo Liu 		WREG32_SOC15(JPEG, i, mmUVD_LMI_JRBC_RB_VMID, 0);
35514f43e8fSLeo Liu 		WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
35614f43e8fSLeo Liu 		WREG32_SOC15(JPEG, i, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
35714f43e8fSLeo Liu 			lower_32_bits(ring->gpu_addr));
35814f43e8fSLeo Liu 		WREG32_SOC15(JPEG, i, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
35914f43e8fSLeo Liu 			upper_32_bits(ring->gpu_addr));
36014f43e8fSLeo Liu 		WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_RPTR, 0);
36114f43e8fSLeo Liu 		WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_WPTR, 0);
36214f43e8fSLeo Liu 		WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_CNTL, 0x00000002L);
36314f43e8fSLeo Liu 		WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_SIZE, ring->ring_size / 4);
36414f43e8fSLeo Liu 		ring->wptr = RREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_WPTR);
36514f43e8fSLeo Liu 	}
36614f43e8fSLeo Liu 
36714f43e8fSLeo Liu 	return 0;
36814f43e8fSLeo Liu }
36914f43e8fSLeo Liu 
37014f43e8fSLeo Liu /**
37114f43e8fSLeo Liu  * jpeg_v2_5_stop - stop JPEG block
37214f43e8fSLeo Liu  *
37314f43e8fSLeo Liu  * @adev: amdgpu_device pointer
37414f43e8fSLeo Liu  *
37514f43e8fSLeo Liu  * stop the JPEG block
37614f43e8fSLeo Liu  */
jpeg_v2_5_stop(struct amdgpu_device * adev)37714f43e8fSLeo Liu static int jpeg_v2_5_stop(struct amdgpu_device *adev)
37814f43e8fSLeo Liu {
37914f43e8fSLeo Liu 	int i;
38014f43e8fSLeo Liu 
38114f43e8fSLeo Liu 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
38214f43e8fSLeo Liu 		if (adev->jpeg.harvest_config & (1 << i))
38314f43e8fSLeo Liu 			continue;
38414f43e8fSLeo Liu 
38514f43e8fSLeo Liu 		/* reset JMI */
38614f43e8fSLeo Liu 		WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JMI_CNTL),
38714f43e8fSLeo Liu 			UVD_JMI_CNTL__SOFT_RESET_MASK,
38814f43e8fSLeo Liu 			~UVD_JMI_CNTL__SOFT_RESET_MASK);
38914f43e8fSLeo Liu 
39014f43e8fSLeo Liu 		jpeg_v2_5_enable_clock_gating(adev, i);
39114f43e8fSLeo Liu 
39214f43e8fSLeo Liu 		/* enable anti hang mechanism */
39314f43e8fSLeo Liu 		WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_POWER_STATUS),
39414f43e8fSLeo Liu 			UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
39514f43e8fSLeo Liu 			~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
39614f43e8fSLeo Liu 	}
39714f43e8fSLeo Liu 
39814f43e8fSLeo Liu 	return 0;
39914f43e8fSLeo Liu }
40014f43e8fSLeo Liu 
40114f43e8fSLeo Liu /**
40214f43e8fSLeo Liu  * jpeg_v2_5_dec_ring_get_rptr - get read pointer
40314f43e8fSLeo Liu  *
40414f43e8fSLeo Liu  * @ring: amdgpu_ring pointer
40514f43e8fSLeo Liu  *
40614f43e8fSLeo Liu  * Returns the current hardware read pointer
40714f43e8fSLeo Liu  */
jpeg_v2_5_dec_ring_get_rptr(struct amdgpu_ring * ring)40814f43e8fSLeo Liu static uint64_t jpeg_v2_5_dec_ring_get_rptr(struct amdgpu_ring *ring)
40914f43e8fSLeo Liu {
41014f43e8fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
41114f43e8fSLeo Liu 
41214f43e8fSLeo Liu 	return RREG32_SOC15(JPEG, ring->me, mmUVD_JRBC_RB_RPTR);
41314f43e8fSLeo Liu }
41414f43e8fSLeo Liu 
41514f43e8fSLeo Liu /**
41614f43e8fSLeo Liu  * jpeg_v2_5_dec_ring_get_wptr - get write pointer
41714f43e8fSLeo Liu  *
41814f43e8fSLeo Liu  * @ring: amdgpu_ring pointer
41914f43e8fSLeo Liu  *
42014f43e8fSLeo Liu  * Returns the current hardware write pointer
42114f43e8fSLeo Liu  */
jpeg_v2_5_dec_ring_get_wptr(struct amdgpu_ring * ring)42214f43e8fSLeo Liu static uint64_t jpeg_v2_5_dec_ring_get_wptr(struct amdgpu_ring *ring)
42314f43e8fSLeo Liu {
42414f43e8fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
42514f43e8fSLeo Liu 
42614f43e8fSLeo Liu 	if (ring->use_doorbell)
4273748424bSJack Xiao 		return *ring->wptr_cpu_addr;
42814f43e8fSLeo Liu 	else
42914f43e8fSLeo Liu 		return RREG32_SOC15(JPEG, ring->me, mmUVD_JRBC_RB_WPTR);
43014f43e8fSLeo Liu }
43114f43e8fSLeo Liu 
43214f43e8fSLeo Liu /**
43314f43e8fSLeo Liu  * jpeg_v2_5_dec_ring_set_wptr - set write pointer
43414f43e8fSLeo Liu  *
43514f43e8fSLeo Liu  * @ring: amdgpu_ring pointer
43614f43e8fSLeo Liu  *
43714f43e8fSLeo Liu  * Commits the write pointer to the hardware
43814f43e8fSLeo Liu  */
jpeg_v2_5_dec_ring_set_wptr(struct amdgpu_ring * ring)43914f43e8fSLeo Liu static void jpeg_v2_5_dec_ring_set_wptr(struct amdgpu_ring *ring)
44014f43e8fSLeo Liu {
44114f43e8fSLeo Liu 	struct amdgpu_device *adev = ring->adev;
44214f43e8fSLeo Liu 
44314f43e8fSLeo Liu 	if (ring->use_doorbell) {
4443748424bSJack Xiao 		*ring->wptr_cpu_addr = lower_32_bits(ring->wptr);
44514f43e8fSLeo Liu 		WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
44614f43e8fSLeo Liu 	} else {
44714f43e8fSLeo Liu 		WREG32_SOC15(JPEG, ring->me, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
44814f43e8fSLeo Liu 	}
44914f43e8fSLeo Liu }
45014f43e8fSLeo Liu 
451c6051149SJames Zhu /**
452c6051149SJames Zhu  * jpeg_v2_6_dec_ring_insert_start - insert a start command
453c6051149SJames Zhu  *
454c6051149SJames Zhu  * @ring: amdgpu_ring pointer
455c6051149SJames Zhu  *
456c6051149SJames Zhu  * Write a start command to the ring.
457c6051149SJames Zhu  */
jpeg_v2_6_dec_ring_insert_start(struct amdgpu_ring * ring)458c6051149SJames Zhu static void jpeg_v2_6_dec_ring_insert_start(struct amdgpu_ring *ring)
459c6051149SJames Zhu {
460c6051149SJames Zhu 	amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
461c6051149SJames Zhu 		0, 0, PACKETJ_TYPE0));
462c6051149SJames Zhu 	amdgpu_ring_write(ring, 0x6aa04); /* PCTL0_MMHUB_DEEPSLEEP_IB */
463c6051149SJames Zhu 
464c6051149SJames Zhu 	amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
465c6051149SJames Zhu 		0, 0, PACKETJ_TYPE0));
466c6051149SJames Zhu 	amdgpu_ring_write(ring, 0x80000000 | (1 << (ring->me * 2 + 14)));
467c6051149SJames Zhu }
468c6051149SJames Zhu 
469c6051149SJames Zhu /**
470c6051149SJames Zhu  * jpeg_v2_6_dec_ring_insert_end - insert a end command
471c6051149SJames Zhu  *
472c6051149SJames Zhu  * @ring: amdgpu_ring pointer
473c6051149SJames Zhu  *
474c6051149SJames Zhu  * Write a end command to the ring.
475c6051149SJames Zhu  */
jpeg_v2_6_dec_ring_insert_end(struct amdgpu_ring * ring)476c6051149SJames Zhu static void jpeg_v2_6_dec_ring_insert_end(struct amdgpu_ring *ring)
477c6051149SJames Zhu {
478c6051149SJames Zhu 	amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
479c6051149SJames Zhu 		0, 0, PACKETJ_TYPE0));
480c6051149SJames Zhu 	amdgpu_ring_write(ring, 0x6aa04); /* PCTL0_MMHUB_DEEPSLEEP_IB */
481c6051149SJames Zhu 
482c6051149SJames Zhu 	amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
483c6051149SJames Zhu 		0, 0, PACKETJ_TYPE0));
484c6051149SJames Zhu 	amdgpu_ring_write(ring, (1 << (ring->me * 2 + 14)));
485c6051149SJames Zhu }
486c6051149SJames Zhu 
jpeg_v2_5_is_idle(void * handle)48714f43e8fSLeo Liu static bool jpeg_v2_5_is_idle(void *handle)
48814f43e8fSLeo Liu {
48914f43e8fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
49014f43e8fSLeo Liu 	int i, ret = 1;
49114f43e8fSLeo Liu 
49214f43e8fSLeo Liu 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
49314f43e8fSLeo Liu 		if (adev->jpeg.harvest_config & (1 << i))
49414f43e8fSLeo Liu 			continue;
49514f43e8fSLeo Liu 
49614f43e8fSLeo Liu 		ret &= (((RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS) &
49714f43e8fSLeo Liu 			UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==
49814f43e8fSLeo Liu 			UVD_JRBC_STATUS__RB_JOB_DONE_MASK));
49914f43e8fSLeo Liu 	}
50014f43e8fSLeo Liu 
50114f43e8fSLeo Liu 	return ret;
50214f43e8fSLeo Liu }
50314f43e8fSLeo Liu 
jpeg_v2_5_wait_for_idle(void * handle)50414f43e8fSLeo Liu static int jpeg_v2_5_wait_for_idle(void *handle)
50514f43e8fSLeo Liu {
50614f43e8fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
507450da2efSJames Zhu 	int i, ret;
50814f43e8fSLeo Liu 
50914f43e8fSLeo Liu 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
51014f43e8fSLeo Liu 		if (adev->jpeg.harvest_config & (1 << i))
51114f43e8fSLeo Liu 			continue;
51214f43e8fSLeo Liu 
513450da2efSJames Zhu 		ret = SOC15_WAIT_ON_RREG(JPEG, i, mmUVD_JRBC_STATUS,
51414f43e8fSLeo Liu 			UVD_JRBC_STATUS__RB_JOB_DONE_MASK,
515450da2efSJames Zhu 			UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
51614f43e8fSLeo Liu 		if (ret)
51714f43e8fSLeo Liu 			return ret;
51814f43e8fSLeo Liu 	}
51914f43e8fSLeo Liu 
52057f01856SColin Ian King 	return 0;
52114f43e8fSLeo Liu }
52214f43e8fSLeo Liu 
jpeg_v2_5_set_clockgating_state(void * handle,enum amd_clockgating_state state)52314f43e8fSLeo Liu static int jpeg_v2_5_set_clockgating_state(void *handle,
52414f43e8fSLeo Liu 					  enum amd_clockgating_state state)
52514f43e8fSLeo Liu {
52614f43e8fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
527a9d4fe2fSNirmoy Das 	bool enable = (state == AMD_CG_STATE_GATE);
52814f43e8fSLeo Liu 	int i;
52914f43e8fSLeo Liu 
53014f43e8fSLeo Liu 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
53114f43e8fSLeo Liu 		if (adev->jpeg.harvest_config & (1 << i))
53214f43e8fSLeo Liu 			continue;
53314f43e8fSLeo Liu 
53414f43e8fSLeo Liu 		if (enable) {
5356c1cb08eSJames Zhu 			if (!jpeg_v2_5_is_idle(handle))
53614f43e8fSLeo Liu 				return -EBUSY;
53714f43e8fSLeo Liu 			jpeg_v2_5_enable_clock_gating(adev, i);
53814f43e8fSLeo Liu 		} else {
53914f43e8fSLeo Liu 			jpeg_v2_5_disable_clock_gating(adev, i);
54014f43e8fSLeo Liu 		}
54114f43e8fSLeo Liu 	}
54214f43e8fSLeo Liu 
54314f43e8fSLeo Liu 	return 0;
54414f43e8fSLeo Liu }
54514f43e8fSLeo Liu 
jpeg_v2_5_set_powergating_state(void * handle,enum amd_powergating_state state)54614f43e8fSLeo Liu static int jpeg_v2_5_set_powergating_state(void *handle,
54714f43e8fSLeo Liu 					  enum amd_powergating_state state)
54814f43e8fSLeo Liu {
54914f43e8fSLeo Liu 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
55014f43e8fSLeo Liu 	int ret;
55114f43e8fSLeo Liu 
55214f43e8fSLeo Liu 	if (state == adev->jpeg.cur_state)
55314f43e8fSLeo Liu 		return 0;
55414f43e8fSLeo Liu 
55514f43e8fSLeo Liu 	if (state == AMD_PG_STATE_GATE)
55614f43e8fSLeo Liu 		ret = jpeg_v2_5_stop(adev);
55714f43e8fSLeo Liu 	else
55814f43e8fSLeo Liu 		ret = jpeg_v2_5_start(adev);
55914f43e8fSLeo Liu 
56014f43e8fSLeo Liu 	if (!ret)
56114f43e8fSLeo Liu 		adev->jpeg.cur_state = state;
56214f43e8fSLeo Liu 
56314f43e8fSLeo Liu 	return ret;
56414f43e8fSLeo Liu }
56514f43e8fSLeo Liu 
jpeg_v2_5_set_interrupt_state(struct amdgpu_device * adev,struct amdgpu_irq_src * source,unsigned type,enum amdgpu_interrupt_state state)56614f43e8fSLeo Liu static int jpeg_v2_5_set_interrupt_state(struct amdgpu_device *adev,
56714f43e8fSLeo Liu 					struct amdgpu_irq_src *source,
56814f43e8fSLeo Liu 					unsigned type,
56914f43e8fSLeo Liu 					enum amdgpu_interrupt_state state)
57014f43e8fSLeo Liu {
57114f43e8fSLeo Liu 	return 0;
57214f43e8fSLeo Liu }
57314f43e8fSLeo Liu 
jpeg_v2_6_set_ras_interrupt_state(struct amdgpu_device * adev,struct amdgpu_irq_src * source,unsigned int type,enum amdgpu_interrupt_state state)574674f90f8SHoratio Zhang static int jpeg_v2_6_set_ras_interrupt_state(struct amdgpu_device *adev,
575674f90f8SHoratio Zhang 					struct amdgpu_irq_src *source,
576674f90f8SHoratio Zhang 					unsigned int type,
577674f90f8SHoratio Zhang 					enum amdgpu_interrupt_state state)
578674f90f8SHoratio Zhang {
579674f90f8SHoratio Zhang 	return 0;
580674f90f8SHoratio Zhang }
581674f90f8SHoratio Zhang 
jpeg_v2_5_process_interrupt(struct amdgpu_device * adev,struct amdgpu_irq_src * source,struct amdgpu_iv_entry * entry)58214f43e8fSLeo Liu static int jpeg_v2_5_process_interrupt(struct amdgpu_device *adev,
58314f43e8fSLeo Liu 				      struct amdgpu_irq_src *source,
58414f43e8fSLeo Liu 				      struct amdgpu_iv_entry *entry)
58514f43e8fSLeo Liu {
58614f43e8fSLeo Liu 	uint32_t ip_instance;
58714f43e8fSLeo Liu 
58814f43e8fSLeo Liu 	switch (entry->client_id) {
58914f43e8fSLeo Liu 	case SOC15_IH_CLIENTID_VCN:
59014f43e8fSLeo Liu 		ip_instance = 0;
59114f43e8fSLeo Liu 		break;
59214f43e8fSLeo Liu 	case SOC15_IH_CLIENTID_VCN1:
59314f43e8fSLeo Liu 		ip_instance = 1;
59414f43e8fSLeo Liu 		break;
59514f43e8fSLeo Liu 	default:
59614f43e8fSLeo Liu 		DRM_ERROR("Unhandled client id: %d\n", entry->client_id);
59714f43e8fSLeo Liu 		return 0;
59814f43e8fSLeo Liu 	}
59914f43e8fSLeo Liu 
60014f43e8fSLeo Liu 	DRM_DEBUG("IH: JPEG TRAP\n");
60114f43e8fSLeo Liu 
60214f43e8fSLeo Liu 	switch (entry->src_id) {
60314f43e8fSLeo Liu 	case VCN_2_0__SRCID__JPEG_DECODE:
604bc224553SJames Zhu 		amdgpu_fence_process(adev->jpeg.inst[ip_instance].ring_dec);
60514f43e8fSLeo Liu 		break;
60614f43e8fSLeo Liu 	default:
60714f43e8fSLeo Liu 		DRM_ERROR("Unhandled interrupt: %d %d\n",
60814f43e8fSLeo Liu 			  entry->src_id, entry->src_data[0]);
60914f43e8fSLeo Liu 		break;
61014f43e8fSLeo Liu 	}
61114f43e8fSLeo Liu 
61214f43e8fSLeo Liu 	return 0;
61314f43e8fSLeo Liu }
61414f43e8fSLeo Liu 
61514f43e8fSLeo Liu static const struct amd_ip_funcs jpeg_v2_5_ip_funcs = {
61614f43e8fSLeo Liu 	.name = "jpeg_v2_5",
61714f43e8fSLeo Liu 	.early_init = jpeg_v2_5_early_init,
61814f43e8fSLeo Liu 	.late_init = NULL,
61914f43e8fSLeo Liu 	.sw_init = jpeg_v2_5_sw_init,
62014f43e8fSLeo Liu 	.sw_fini = jpeg_v2_5_sw_fini,
62114f43e8fSLeo Liu 	.hw_init = jpeg_v2_5_hw_init,
62214f43e8fSLeo Liu 	.hw_fini = jpeg_v2_5_hw_fini,
62314f43e8fSLeo Liu 	.suspend = jpeg_v2_5_suspend,
62414f43e8fSLeo Liu 	.resume = jpeg_v2_5_resume,
62514f43e8fSLeo Liu 	.is_idle = jpeg_v2_5_is_idle,
62614f43e8fSLeo Liu 	.wait_for_idle = jpeg_v2_5_wait_for_idle,
62714f43e8fSLeo Liu 	.check_soft_reset = NULL,
62814f43e8fSLeo Liu 	.pre_soft_reset = NULL,
62914f43e8fSLeo Liu 	.soft_reset = NULL,
63014f43e8fSLeo Liu 	.post_soft_reset = NULL,
63114f43e8fSLeo Liu 	.set_clockgating_state = jpeg_v2_5_set_clockgating_state,
63214f43e8fSLeo Liu 	.set_powergating_state = jpeg_v2_5_set_powergating_state,
633e21d253bSSunil Khatri 	.dump_ip_state = NULL,
63440356542SSunil Khatri 	.print_ip_state = NULL,
63514f43e8fSLeo Liu };
63614f43e8fSLeo Liu 
637ff6885acSJames Zhu static const struct amd_ip_funcs jpeg_v2_6_ip_funcs = {
638ff6885acSJames Zhu 	.name = "jpeg_v2_6",
639ff6885acSJames Zhu 	.early_init = jpeg_v2_5_early_init,
640ff6885acSJames Zhu 	.late_init = NULL,
641ff6885acSJames Zhu 	.sw_init = jpeg_v2_5_sw_init,
642ff6885acSJames Zhu 	.sw_fini = jpeg_v2_5_sw_fini,
643ff6885acSJames Zhu 	.hw_init = jpeg_v2_5_hw_init,
644ff6885acSJames Zhu 	.hw_fini = jpeg_v2_5_hw_fini,
645ff6885acSJames Zhu 	.suspend = jpeg_v2_5_suspend,
646ff6885acSJames Zhu 	.resume = jpeg_v2_5_resume,
647ff6885acSJames Zhu 	.is_idle = jpeg_v2_5_is_idle,
648ff6885acSJames Zhu 	.wait_for_idle = jpeg_v2_5_wait_for_idle,
649ff6885acSJames Zhu 	.check_soft_reset = NULL,
650ff6885acSJames Zhu 	.pre_soft_reset = NULL,
651ff6885acSJames Zhu 	.soft_reset = NULL,
652ff6885acSJames Zhu 	.post_soft_reset = NULL,
653ff6885acSJames Zhu 	.set_clockgating_state = jpeg_v2_5_set_clockgating_state,
654ff6885acSJames Zhu 	.set_powergating_state = jpeg_v2_5_set_powergating_state,
655e21d253bSSunil Khatri 	.dump_ip_state = NULL,
65640356542SSunil Khatri 	.print_ip_state = NULL,
657ff6885acSJames Zhu };
658ff6885acSJames Zhu 
65914f43e8fSLeo Liu static const struct amdgpu_ring_funcs jpeg_v2_5_dec_ring_vm_funcs = {
66014f43e8fSLeo Liu 	.type = AMDGPU_RING_TYPE_VCN_JPEG,
66114f43e8fSLeo Liu 	.align_mask = 0xf,
66214f43e8fSLeo Liu 	.get_rptr = jpeg_v2_5_dec_ring_get_rptr,
66314f43e8fSLeo Liu 	.get_wptr = jpeg_v2_5_dec_ring_get_wptr,
66414f43e8fSLeo Liu 	.set_wptr = jpeg_v2_5_dec_ring_set_wptr,
665*3a23aa0bSDavid (Ming Qiang) Wu 	.parse_cs = jpeg_v2_dec_ring_parse_cs,
66614f43e8fSLeo Liu 	.emit_frame_size =
66714f43e8fSLeo Liu 		SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
66814f43e8fSLeo Liu 		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
66914f43e8fSLeo Liu 		8 + /* jpeg_v2_5_dec_ring_emit_vm_flush */
67014f43e8fSLeo Liu 		18 + 18 + /* jpeg_v2_5_dec_ring_emit_fence x2 vm fence */
67114f43e8fSLeo Liu 		8 + 16,
67214f43e8fSLeo Liu 	.emit_ib_size = 22, /* jpeg_v2_5_dec_ring_emit_ib */
67314f43e8fSLeo Liu 	.emit_ib = jpeg_v2_0_dec_ring_emit_ib,
67414f43e8fSLeo Liu 	.emit_fence = jpeg_v2_0_dec_ring_emit_fence,
67514f43e8fSLeo Liu 	.emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,
67614f43e8fSLeo Liu 	.test_ring = amdgpu_jpeg_dec_ring_test_ring,
67714f43e8fSLeo Liu 	.test_ib = amdgpu_jpeg_dec_ring_test_ib,
67814f43e8fSLeo Liu 	.insert_nop = jpeg_v2_0_dec_ring_nop,
67914f43e8fSLeo Liu 	.insert_start = jpeg_v2_0_dec_ring_insert_start,
68014f43e8fSLeo Liu 	.insert_end = jpeg_v2_0_dec_ring_insert_end,
68114f43e8fSLeo Liu 	.pad_ib = amdgpu_ring_generic_pad_ib,
68214f43e8fSLeo Liu 	.begin_use = amdgpu_jpeg_ring_begin_use,
68314f43e8fSLeo Liu 	.end_use = amdgpu_jpeg_ring_end_use,
68414f43e8fSLeo Liu 	.emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,
68514f43e8fSLeo Liu 	.emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,
68614f43e8fSLeo Liu 	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
68714f43e8fSLeo Liu };
68814f43e8fSLeo Liu 
689ff6885acSJames Zhu static const struct amdgpu_ring_funcs jpeg_v2_6_dec_ring_vm_funcs = {
690ff6885acSJames Zhu 	.type = AMDGPU_RING_TYPE_VCN_JPEG,
691ff6885acSJames Zhu 	.align_mask = 0xf,
692ff6885acSJames Zhu 	.get_rptr = jpeg_v2_5_dec_ring_get_rptr,
693ff6885acSJames Zhu 	.get_wptr = jpeg_v2_5_dec_ring_get_wptr,
694ff6885acSJames Zhu 	.set_wptr = jpeg_v2_5_dec_ring_set_wptr,
695*3a23aa0bSDavid (Ming Qiang) Wu 	.parse_cs = jpeg_v2_dec_ring_parse_cs,
696ff6885acSJames Zhu 	.emit_frame_size =
697ff6885acSJames Zhu 		SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
698ff6885acSJames Zhu 		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
699ff6885acSJames Zhu 		8 + /* jpeg_v2_5_dec_ring_emit_vm_flush */
700ff6885acSJames Zhu 		18 + 18 + /* jpeg_v2_5_dec_ring_emit_fence x2 vm fence */
701ff6885acSJames Zhu 		8 + 16,
702ff6885acSJames Zhu 	.emit_ib_size = 22, /* jpeg_v2_5_dec_ring_emit_ib */
703ff6885acSJames Zhu 	.emit_ib = jpeg_v2_0_dec_ring_emit_ib,
704ff6885acSJames Zhu 	.emit_fence = jpeg_v2_0_dec_ring_emit_fence,
705ff6885acSJames Zhu 	.emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,
706ff6885acSJames Zhu 	.test_ring = amdgpu_jpeg_dec_ring_test_ring,
707ff6885acSJames Zhu 	.test_ib = amdgpu_jpeg_dec_ring_test_ib,
708ff6885acSJames Zhu 	.insert_nop = jpeg_v2_0_dec_ring_nop,
709c6051149SJames Zhu 	.insert_start = jpeg_v2_6_dec_ring_insert_start,
710c6051149SJames Zhu 	.insert_end = jpeg_v2_6_dec_ring_insert_end,
711ff6885acSJames Zhu 	.pad_ib = amdgpu_ring_generic_pad_ib,
712ff6885acSJames Zhu 	.begin_use = amdgpu_jpeg_ring_begin_use,
713ff6885acSJames Zhu 	.end_use = amdgpu_jpeg_ring_end_use,
714ff6885acSJames Zhu 	.emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,
715ff6885acSJames Zhu 	.emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,
716ff6885acSJames Zhu 	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
717ff6885acSJames Zhu };
718ff6885acSJames Zhu 
jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device * adev)71914f43e8fSLeo Liu static void jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev)
72014f43e8fSLeo Liu {
72114f43e8fSLeo Liu 	int i;
72214f43e8fSLeo Liu 
72314f43e8fSLeo Liu 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
72414f43e8fSLeo Liu 		if (adev->jpeg.harvest_config & (1 << i))
72514f43e8fSLeo Liu 			continue;
726ff6885acSJames Zhu 		if (adev->asic_type == CHIP_ARCTURUS)
727bc224553SJames Zhu 			adev->jpeg.inst[i].ring_dec->funcs = &jpeg_v2_5_dec_ring_vm_funcs;
728ff6885acSJames Zhu 		else  /* CHIP_ALDEBARAN */
729bc224553SJames Zhu 			adev->jpeg.inst[i].ring_dec->funcs = &jpeg_v2_6_dec_ring_vm_funcs;
730bc224553SJames Zhu 		adev->jpeg.inst[i].ring_dec->me = i;
73114f43e8fSLeo Liu 	}
73214f43e8fSLeo Liu }
73314f43e8fSLeo Liu 
73414f43e8fSLeo Liu static const struct amdgpu_irq_src_funcs jpeg_v2_5_irq_funcs = {
73514f43e8fSLeo Liu 	.set = jpeg_v2_5_set_interrupt_state,
73614f43e8fSLeo Liu 	.process = jpeg_v2_5_process_interrupt,
73714f43e8fSLeo Liu };
73814f43e8fSLeo Liu 
739674f90f8SHoratio Zhang static const struct amdgpu_irq_src_funcs jpeg_v2_6_ras_irq_funcs = {
740674f90f8SHoratio Zhang 	.set = jpeg_v2_6_set_ras_interrupt_state,
741674f90f8SHoratio Zhang 	.process = amdgpu_jpeg_process_poison_irq,
742674f90f8SHoratio Zhang };
743674f90f8SHoratio Zhang 
jpeg_v2_5_set_irq_funcs(struct amdgpu_device * adev)74414f43e8fSLeo Liu static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev)
74514f43e8fSLeo Liu {
74614f43e8fSLeo Liu 	int i;
74714f43e8fSLeo Liu 
74814f43e8fSLeo Liu 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
74914f43e8fSLeo Liu 		if (adev->jpeg.harvest_config & (1 << i))
75014f43e8fSLeo Liu 			continue;
75114f43e8fSLeo Liu 
75214f43e8fSLeo Liu 		adev->jpeg.inst[i].irq.num_types = 1;
75314f43e8fSLeo Liu 		adev->jpeg.inst[i].irq.funcs = &jpeg_v2_5_irq_funcs;
754674f90f8SHoratio Zhang 
755674f90f8SHoratio Zhang 		adev->jpeg.inst[i].ras_poison_irq.num_types = 1;
756674f90f8SHoratio Zhang 		adev->jpeg.inst[i].ras_poison_irq.funcs = &jpeg_v2_6_ras_irq_funcs;
75714f43e8fSLeo Liu 	}
75814f43e8fSLeo Liu }
75914f43e8fSLeo Liu 
7600b0fb6daSchenxuebing const struct amdgpu_ip_block_version jpeg_v2_5_ip_block = {
76114f43e8fSLeo Liu 		.type = AMD_IP_BLOCK_TYPE_JPEG,
76214f43e8fSLeo Liu 		.major = 2,
76314f43e8fSLeo Liu 		.minor = 5,
76414f43e8fSLeo Liu 		.rev = 0,
76514f43e8fSLeo Liu 		.funcs = &jpeg_v2_5_ip_funcs,
76614f43e8fSLeo Liu };
767ff6885acSJames Zhu 
7680b0fb6daSchenxuebing const struct amdgpu_ip_block_version jpeg_v2_6_ip_block = {
769ff6885acSJames Zhu 		.type = AMD_IP_BLOCK_TYPE_JPEG,
770ff6885acSJames Zhu 		.major = 2,
771ff6885acSJames Zhu 		.minor = 6,
772ff6885acSJames Zhu 		.rev = 0,
773ff6885acSJames Zhu 		.funcs = &jpeg_v2_6_ip_funcs,
774ff6885acSJames Zhu };
775749831acSMohammad Zafar Ziya 
jpeg_v2_6_query_poison_by_instance(struct amdgpu_device * adev,uint32_t instance,uint32_t sub_block)776749831acSMohammad Zafar Ziya static uint32_t jpeg_v2_6_query_poison_by_instance(struct amdgpu_device *adev,
777749831acSMohammad Zafar Ziya 		uint32_t instance, uint32_t sub_block)
778749831acSMohammad Zafar Ziya {
779749831acSMohammad Zafar Ziya 	uint32_t poison_stat = 0, reg_value = 0;
780749831acSMohammad Zafar Ziya 
781749831acSMohammad Zafar Ziya 	switch (sub_block) {
782749831acSMohammad Zafar Ziya 	case AMDGPU_JPEG_V2_6_JPEG0:
783749831acSMohammad Zafar Ziya 		reg_value = RREG32_SOC15(JPEG, instance, mmUVD_RAS_JPEG0_STATUS);
784749831acSMohammad Zafar Ziya 		poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG0_STATUS, POISONED_PF);
785749831acSMohammad Zafar Ziya 		break;
786749831acSMohammad Zafar Ziya 	case AMDGPU_JPEG_V2_6_JPEG1:
787749831acSMohammad Zafar Ziya 		reg_value = RREG32_SOC15(JPEG, instance, mmUVD_RAS_JPEG1_STATUS);
788749831acSMohammad Zafar Ziya 		poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG1_STATUS, POISONED_PF);
789749831acSMohammad Zafar Ziya 		break;
790749831acSMohammad Zafar Ziya 	default:
791749831acSMohammad Zafar Ziya 		break;
792749831acSMohammad Zafar Ziya 	}
793749831acSMohammad Zafar Ziya 
794749831acSMohammad Zafar Ziya 	if (poison_stat)
795749831acSMohammad Zafar Ziya 		dev_info(adev->dev, "Poison detected in JPEG%d sub_block%d\n",
796749831acSMohammad Zafar Ziya 			instance, sub_block);
797749831acSMohammad Zafar Ziya 
798749831acSMohammad Zafar Ziya 	return poison_stat;
799749831acSMohammad Zafar Ziya }
800749831acSMohammad Zafar Ziya 
jpeg_v2_6_query_ras_poison_status(struct amdgpu_device * adev)801749831acSMohammad Zafar Ziya static bool jpeg_v2_6_query_ras_poison_status(struct amdgpu_device *adev)
802749831acSMohammad Zafar Ziya {
803749831acSMohammad Zafar Ziya 	uint32_t inst = 0, sub = 0, poison_stat = 0;
804749831acSMohammad Zafar Ziya 
805749831acSMohammad Zafar Ziya 	for (inst = 0; inst < adev->jpeg.num_jpeg_inst; inst++)
806749831acSMohammad Zafar Ziya 		for (sub = 0; sub < AMDGPU_JPEG_V2_6_MAX_SUB_BLOCK; sub++)
807749831acSMohammad Zafar Ziya 			poison_stat +=
808749831acSMohammad Zafar Ziya 			jpeg_v2_6_query_poison_by_instance(adev, inst, sub);
809749831acSMohammad Zafar Ziya 
810749831acSMohammad Zafar Ziya 	return !!poison_stat;
811749831acSMohammad Zafar Ziya }
812749831acSMohammad Zafar Ziya 
813749831acSMohammad Zafar Ziya const struct amdgpu_ras_block_hw_ops jpeg_v2_6_ras_hw_ops = {
814749831acSMohammad Zafar Ziya 	.query_poison_status = jpeg_v2_6_query_ras_poison_status,
815749831acSMohammad Zafar Ziya };
816749831acSMohammad Zafar Ziya 
817749831acSMohammad Zafar Ziya static struct amdgpu_jpeg_ras jpeg_v2_6_ras = {
818749831acSMohammad Zafar Ziya 	.ras_block = {
819749831acSMohammad Zafar Ziya 		.hw_ops = &jpeg_v2_6_ras_hw_ops,
820674f90f8SHoratio Zhang 		.ras_late_init = amdgpu_jpeg_ras_late_init,
821749831acSMohammad Zafar Ziya 	},
822749831acSMohammad Zafar Ziya };
823749831acSMohammad Zafar Ziya 
jpeg_v2_5_set_ras_funcs(struct amdgpu_device * adev)824749831acSMohammad Zafar Ziya static void jpeg_v2_5_set_ras_funcs(struct amdgpu_device *adev)
825749831acSMohammad Zafar Ziya {
8264e8303cfSLijo Lazar 	switch (amdgpu_ip_version(adev, JPEG_HWIP, 0)) {
827749831acSMohammad Zafar Ziya 	case IP_VERSION(2, 6, 0):
828749831acSMohammad Zafar Ziya 		adev->jpeg.ras = &jpeg_v2_6_ras;
829749831acSMohammad Zafar Ziya 		break;
830749831acSMohammad Zafar Ziya 	default:
831749831acSMohammad Zafar Ziya 		break;
832749831acSMohammad Zafar Ziya 	}
833749831acSMohammad Zafar Ziya }
834