brintos

brintos / linux-shallow public Read only

0
0
Text · 22.0 KiB · 6c5c1a6 Raw
843 lines · c
1/*2 * Copyright 2021 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 */23 24#include "amdgpu.h"25#include "amdgpu_jpeg.h"26#include "amdgpu_pm.h"27#include "soc15.h"28#include "soc15d.h"29#include "jpeg_v2_0.h"30#include "jpeg_v4_0.h"31#include "mmsch_v4_0.h"32 33#include "vcn/vcn_4_0_0_offset.h"34#include "vcn/vcn_4_0_0_sh_mask.h"35#include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"36 37#define regUVD_JPEG_PITCH_INTERNAL_OFFSET                  0x401f38 39static int jpeg_v4_0_start_sriov(struct amdgpu_device *adev);40static void jpeg_v4_0_set_dec_ring_funcs(struct amdgpu_device *adev);41static void jpeg_v4_0_set_irq_funcs(struct amdgpu_device *adev);42static int jpeg_v4_0_set_powergating_state(void *handle,43				enum amd_powergating_state state);44static void jpeg_v4_0_set_ras_funcs(struct amdgpu_device *adev);45 46static void jpeg_v4_0_dec_ring_set_wptr(struct amdgpu_ring *ring);47 48/**49 * jpeg_v4_0_early_init - set function pointers50 *51 * @handle: amdgpu_device pointer52 *53 * Set ring and irq function pointers54 */55static int jpeg_v4_0_early_init(void *handle)56{57	struct amdgpu_device *adev = (struct amdgpu_device *)handle;58 59 60	adev->jpeg.num_jpeg_inst = 1;61	adev->jpeg.num_jpeg_rings = 1;62 63	jpeg_v4_0_set_dec_ring_funcs(adev);64	jpeg_v4_0_set_irq_funcs(adev);65	jpeg_v4_0_set_ras_funcs(adev);66 67	return 0;68}69 70/**71 * jpeg_v4_0_sw_init - sw init for JPEG block72 *73 * @handle: amdgpu_device pointer74 *75 * Load firmware and sw initialization76 */77static int jpeg_v4_0_sw_init(void *handle)78{79	struct amdgpu_device *adev = (struct amdgpu_device *)handle;80	struct amdgpu_ring *ring;81	int r;82 83	/* JPEG TRAP */84	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,85		VCN_4_0__SRCID__JPEG_DECODE, &adev->jpeg.inst->irq);86	if (r)87		return r;88 89	/* JPEG DJPEG POISON EVENT */90	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,91			VCN_4_0__SRCID_DJPEG0_POISON, &adev->jpeg.inst->ras_poison_irq);92	if (r)93		return r;94 95	/* JPEG EJPEG POISON EVENT */96	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,97			VCN_4_0__SRCID_EJPEG0_POISON, &adev->jpeg.inst->ras_poison_irq);98	if (r)99		return r;100 101	r = amdgpu_jpeg_sw_init(adev);102	if (r)103		return r;104 105	r = amdgpu_jpeg_resume(adev);106	if (r)107		return r;108 109	ring = adev->jpeg.inst->ring_dec;110	ring->use_doorbell = true;111	ring->doorbell_index = amdgpu_sriov_vf(adev) ? (((adev->doorbell_index.vcn.vcn_ring0_1) << 1) + 4) : ((adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1);112	ring->vm_hub = AMDGPU_MMHUB0(0);113 114	sprintf(ring->name, "jpeg_dec");115	r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0,116			     AMDGPU_RING_PRIO_DEFAULT, NULL);117	if (r)118		return r;119 120	adev->jpeg.internal.jpeg_pitch[0] = regUVD_JPEG_PITCH_INTERNAL_OFFSET;121	adev->jpeg.inst->external.jpeg_pitch[0] = SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_PITCH);122 123	r = amdgpu_jpeg_ras_sw_init(adev);124	if (r)125		return r;126 127	return 0;128}129 130/**131 * jpeg_v4_0_sw_fini - sw fini for JPEG block132 *133 * @handle: amdgpu_device pointer134 *135 * JPEG suspend and free up sw allocation136 */137static int jpeg_v4_0_sw_fini(void *handle)138{139	struct amdgpu_device *adev = (struct amdgpu_device *)handle;140	int r;141 142	r = amdgpu_jpeg_suspend(adev);143	if (r)144		return r;145 146	r = amdgpu_jpeg_sw_fini(adev);147 148	return r;149}150 151/**152 * jpeg_v4_0_hw_init - start and test JPEG block153 *154 * @handle: amdgpu_device pointer155 *156 */157static int jpeg_v4_0_hw_init(void *handle)158{159	struct amdgpu_device *adev = (struct amdgpu_device *)handle;160	struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;161	int r;162 163	if (amdgpu_sriov_vf(adev)) {164		r = jpeg_v4_0_start_sriov(adev);165		if (r)166			return r;167		ring->wptr = 0;168		ring->wptr_old = 0;169		jpeg_v4_0_dec_ring_set_wptr(ring);170		ring->sched.ready = true;171	} else {172		adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,173						(adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);174 175		WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,176			ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |177			VCN_JPEG_DB_CTRL__EN_MASK);178 179		r = amdgpu_ring_test_helper(ring);180		if (r)181			return r;182	}183 184	return 0;185}186 187/**188 * jpeg_v4_0_hw_fini - stop the hardware block189 *190 * @handle: amdgpu_device pointer191 *192 * Stop the JPEG block, mark ring as not ready any more193 */194static int jpeg_v4_0_hw_fini(void *handle)195{196	struct amdgpu_device *adev = (struct amdgpu_device *)handle;197 198	cancel_delayed_work_sync(&adev->vcn.idle_work);199	if (!amdgpu_sriov_vf(adev)) {200		if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&201			RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))202			jpeg_v4_0_set_powergating_state(adev, AMD_PG_STATE_GATE);203	}204	if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__JPEG))205		amdgpu_irq_put(adev, &adev->jpeg.inst->ras_poison_irq, 0);206 207	return 0;208}209 210/**211 * jpeg_v4_0_suspend - suspend JPEG block212 *213 * @handle: amdgpu_device pointer214 *215 * HW fini and suspend JPEG block216 */217static int jpeg_v4_0_suspend(void *handle)218{219	struct amdgpu_device *adev = (struct amdgpu_device *)handle;220	int r;221 222	r = jpeg_v4_0_hw_fini(adev);223	if (r)224		return r;225 226	r = amdgpu_jpeg_suspend(adev);227 228	return r;229}230 231/**232 * jpeg_v4_0_resume - resume JPEG block233 *234 * @handle: amdgpu_device pointer235 *236 * Resume firmware and hw init JPEG block237 */238static int jpeg_v4_0_resume(void *handle)239{240	struct amdgpu_device *adev = (struct amdgpu_device *)handle;241	int r;242 243	r = amdgpu_jpeg_resume(adev);244	if (r)245		return r;246 247	r = jpeg_v4_0_hw_init(adev);248 249	return r;250}251 252static void jpeg_v4_0_disable_clock_gating(struct amdgpu_device *adev)253{254	uint32_t data = 0;255 256	data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL);257	if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) {258		data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;259		data &= (~JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK);260	} else {261		data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;262	}263 264	data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;265	data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;266	WREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL, data);267 268	data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE);269	data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK270		| JPEG_CGC_GATE__JPEG2_DEC_MASK271		| JPEG_CGC_GATE__JMCIF_MASK272		| JPEG_CGC_GATE__JRBBM_MASK);273	WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data);274}275 276static void jpeg_v4_0_enable_clock_gating(struct amdgpu_device *adev)277{278	uint32_t data = 0;279 280	data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL);281	if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG) {282		data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;283		data |= JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK;284	} else {285		data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;286	}287 288	data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;289	data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;290	WREG32_SOC15(JPEG, 0, regJPEG_CGC_CTRL, data);291 292	data = RREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE);293	data |= (JPEG_CGC_GATE__JPEG_DEC_MASK294		|JPEG_CGC_GATE__JPEG2_DEC_MASK295		|JPEG_CGC_GATE__JMCIF_MASK296		|JPEG_CGC_GATE__JRBBM_MASK);297	WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data);298}299 300static int jpeg_v4_0_disable_static_power_gating(struct amdgpu_device *adev)301{302	if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {303		uint32_t data = 0;304		int r = 0;305 306		data = 1 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT;307		WREG32(SOC15_REG_OFFSET(JPEG, 0, regUVD_PGFSM_CONFIG), data);308 309		r = SOC15_WAIT_ON_RREG(JPEG, 0,310			regUVD_PGFSM_STATUS, UVD_PGFSM_STATUS_UVDJ_PWR_ON,311			UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK);312 313		if (r) {314			DRM_DEV_ERROR(adev->dev, "amdgpu: JPEG disable power gating failed\n");315			return r;316		}317	}318 319	/* disable anti hang mechanism */320	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), 0,321		~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);322 323	/* keep the JPEG in static PG mode */324	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), 0,325		~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK);326 327	return 0;328}329 330static int jpeg_v4_0_enable_static_power_gating(struct amdgpu_device *adev)331{332	/* enable anti hang mechanism */333	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS),334		UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,335		~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);336 337	if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {338		uint32_t data = 0;339		int r = 0;340 341		data = 2 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT;342		WREG32(SOC15_REG_OFFSET(JPEG, 0, regUVD_PGFSM_CONFIG), data);343 344		r = SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_PGFSM_STATUS,345			(2 << UVD_PGFSM_STATUS__UVDJ_PWR_STATUS__SHIFT),346			UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK);347 348		if (r) {349			DRM_DEV_ERROR(adev->dev, "amdgpu: JPEG enable power gating failed\n");350			return r;351		}352	}353 354	return 0;355}356 357/**358 * jpeg_v4_0_start - start JPEG block359 *360 * @adev: amdgpu_device pointer361 *362 * Setup and start the JPEG block363 */364static int jpeg_v4_0_start(struct amdgpu_device *adev)365{366	struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;367	int r;368 369	if (adev->pm.dpm_enabled)370		amdgpu_dpm_enable_jpeg(adev, true);371 372	/* disable power gating */373	r = jpeg_v4_0_disable_static_power_gating(adev);374	if (r)375		return r;376 377	/* JPEG disable CGC */378	jpeg_v4_0_disable_clock_gating(adev);379 380	/* MJPEG global tiling registers */381	WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG,382		adev->gfx.config.gb_addr_config);383 384 385	/* enable JMI channel */386	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL), 0,387		~UVD_JMI_CNTL__SOFT_RESET_MASK);388 389	/* enable System Interrupt for JRBC */390	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regJPEG_SYS_INT_EN),391		JPEG_SYS_INT_EN__DJRBC_MASK,392		~JPEG_SYS_INT_EN__DJRBC_MASK);393 394	WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_VMID, 0);395	WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));396	WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,397		lower_32_bits(ring->gpu_addr));398	WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,399		upper_32_bits(ring->gpu_addr));400	WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_RPTR, 0);401	WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR, 0);402	WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_CNTL, 0x00000002L);403	WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_SIZE, ring->ring_size / 4);404	ring->wptr = RREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR);405 406	return 0;407}408 409static int jpeg_v4_0_start_sriov(struct amdgpu_device *adev)410{411	struct amdgpu_ring *ring;412	uint64_t ctx_addr;413	uint32_t param, resp, expected;414	uint32_t tmp, timeout;415 416	struct amdgpu_mm_table *table = &adev->virt.mm_table;417	uint32_t *table_loc;418	uint32_t table_size;419	uint32_t size, size_dw;420	uint32_t init_status;421 422	struct mmsch_v4_0_cmd_direct_write423		direct_wt = { {0} };424	struct mmsch_v4_0_cmd_end end = { {0} };425	struct mmsch_v4_0_init_header header;426 427	direct_wt.cmd_header.command_type =428		MMSCH_COMMAND__DIRECT_REG_WRITE;429	end.cmd_header.command_type =430		MMSCH_COMMAND__END;431 432	size = sizeof(struct mmsch_v4_0_init_header);433	table_loc = (uint32_t *)table->cpu_addr;434	memcpy(&header, (void *)table_loc, size);435 436	header.version = MMSCH_VERSION;437	header.total_size = RREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_SIZE);438 439	header.jpegdec.init_status = 0;440	header.jpegdec.table_offset = 0;441	header.jpegdec.table_size = 0;442 443	table_loc = (uint32_t *)table->cpu_addr;444	table_loc += header.total_size;445 446	table_size = 0;447 448	ring = adev->jpeg.inst->ring_dec;449 450	MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(JPEG, 0,451		regUVD_LMI_JRBC_RB_64BIT_BAR_LOW),452		lower_32_bits(ring->gpu_addr));453	MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(JPEG, 0,454		regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH),455		upper_32_bits(ring->gpu_addr));456	MMSCH_V4_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(JPEG, 0,457		regUVD_JRBC_RB_SIZE), ring->ring_size / 4);458 459	/* add end packet */460	MMSCH_V4_0_INSERT_END();461 462	/* refine header */463	header.jpegdec.init_status = 0;464	header.jpegdec.table_offset = header.total_size;465	header.jpegdec.table_size = table_size;466	header.total_size += table_size;467 468	/* Update init table header in memory */469	size = sizeof(struct mmsch_v4_0_init_header);470	table_loc = (uint32_t *)table->cpu_addr;471	memcpy((void *)table_loc, &header, size);472 473	/* Perform HDP flush before writing to MMSCH registers */474	amdgpu_device_flush_hdp(adev, NULL);475 476	/* message MMSCH (in VCN[0]) to initialize this client477	 * 1, write to mmsch_vf_ctx_addr_lo/hi register with GPU mc addr478	 * of memory descriptor location479	 */480	ctx_addr = table->gpu_addr;481	WREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_ADDR_LO, lower_32_bits(ctx_addr));482	WREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_ADDR_HI, upper_32_bits(ctx_addr));483 484	/* 2, update vmid of descriptor */485	tmp = RREG32_SOC15(VCN, 0, regMMSCH_VF_VMID);486	tmp &= ~MMSCH_VF_VMID__VF_CTX_VMID_MASK;487	/* use domain0 for MM scheduler */488	tmp |= (0 << MMSCH_VF_VMID__VF_CTX_VMID__SHIFT);489	WREG32_SOC15(VCN, 0, regMMSCH_VF_VMID, tmp);490 491	/* 3, notify mmsch about the size of this descriptor */492	size = header.total_size;493	WREG32_SOC15(VCN, 0, regMMSCH_VF_CTX_SIZE, size);494 495	/* 4, set resp to zero */496	WREG32_SOC15(VCN, 0, regMMSCH_VF_MAILBOX_RESP, 0);497 498	/* 5, kick off the initialization and wait until499	 * MMSCH_VF_MAILBOX_RESP becomes non-zero500	 */501	param = 0x00000001;502	WREG32_SOC15(VCN, 0, regMMSCH_VF_MAILBOX_HOST, param);503	tmp = 0;504	timeout = 1000;505	resp = 0;506	expected = MMSCH_VF_MAILBOX_RESP__OK;507	init_status = ((struct mmsch_v4_0_init_header *)(table_loc))->jpegdec.init_status;508	while (resp != expected) {509		resp = RREG32_SOC15(VCN, 0, regMMSCH_VF_MAILBOX_RESP);510 511		if (resp != 0)512			break;513		udelay(10);514		tmp = tmp + 10;515		if (tmp >= timeout) {516			DRM_ERROR("failed to init MMSCH. TIME-OUT after %d usec"\517				" waiting for regMMSCH_VF_MAILBOX_RESP "\518				"(expected=0x%08x, readback=0x%08x)\n",519				tmp, expected, resp);520			return -EBUSY;521		}522	}523	if (resp != expected && resp != MMSCH_VF_MAILBOX_RESP__INCOMPLETE524			&& init_status != MMSCH_VF_ENGINE_STATUS__PASS) {525		DRM_ERROR("MMSCH init status is incorrect! readback=0x%08x, header init status for jpeg: %x\n", resp, init_status);526		return -EINVAL;527	}528 529	return 0;530 531}532 533/**534 * jpeg_v4_0_stop - stop JPEG block535 *536 * @adev: amdgpu_device pointer537 *538 * stop the JPEG block539 */540static int jpeg_v4_0_stop(struct amdgpu_device *adev)541{542	int r;543 544	/* reset JMI */545	WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL),546		UVD_JMI_CNTL__SOFT_RESET_MASK,547		~UVD_JMI_CNTL__SOFT_RESET_MASK);548 549	jpeg_v4_0_enable_clock_gating(adev);550 551	/* enable power gating */552	r = jpeg_v4_0_enable_static_power_gating(adev);553	if (r)554		return r;555 556	if (adev->pm.dpm_enabled)557		amdgpu_dpm_enable_jpeg(adev, false);558 559	return 0;560}561 562/**563 * jpeg_v4_0_dec_ring_get_rptr - get read pointer564 *565 * @ring: amdgpu_ring pointer566 *567 * Returns the current hardware read pointer568 */569static uint64_t jpeg_v4_0_dec_ring_get_rptr(struct amdgpu_ring *ring)570{571	struct amdgpu_device *adev = ring->adev;572 573	return RREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_RPTR);574}575 576/**577 * jpeg_v4_0_dec_ring_get_wptr - get write pointer578 *579 * @ring: amdgpu_ring pointer580 *581 * Returns the current hardware write pointer582 */583static uint64_t jpeg_v4_0_dec_ring_get_wptr(struct amdgpu_ring *ring)584{585	struct amdgpu_device *adev = ring->adev;586 587	if (ring->use_doorbell)588		return *ring->wptr_cpu_addr;589	else590		return RREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR);591}592 593/**594 * jpeg_v4_0_dec_ring_set_wptr - set write pointer595 *596 * @ring: amdgpu_ring pointer597 *598 * Commits the write pointer to the hardware599 */600static void jpeg_v4_0_dec_ring_set_wptr(struct amdgpu_ring *ring)601{602	struct amdgpu_device *adev = ring->adev;603 604	if (ring->use_doorbell) {605		*ring->wptr_cpu_addr = lower_32_bits(ring->wptr);606		WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));607	} else {608		WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));609	}610}611 612static bool jpeg_v4_0_is_idle(void *handle)613{614	struct amdgpu_device *adev = (struct amdgpu_device *)handle;615	int ret = 1;616 617	ret &= (((RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS) &618		UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==619		UVD_JRBC_STATUS__RB_JOB_DONE_MASK));620 621	return ret;622}623 624static int jpeg_v4_0_wait_for_idle(void *handle)625{626	struct amdgpu_device *adev = (struct amdgpu_device *)handle;627 628	return SOC15_WAIT_ON_RREG(JPEG, 0, regUVD_JRBC_STATUS,629		UVD_JRBC_STATUS__RB_JOB_DONE_MASK,630		UVD_JRBC_STATUS__RB_JOB_DONE_MASK);631}632 633static int jpeg_v4_0_set_clockgating_state(void *handle,634					  enum amd_clockgating_state state)635{636	struct amdgpu_device *adev = (struct amdgpu_device *)handle;637	bool enable = state == AMD_CG_STATE_GATE;638 639	if (enable) {640		if (!jpeg_v4_0_is_idle(handle))641			return -EBUSY;642		jpeg_v4_0_enable_clock_gating(adev);643	} else {644		jpeg_v4_0_disable_clock_gating(adev);645	}646 647	return 0;648}649 650static int jpeg_v4_0_set_powergating_state(void *handle,651					  enum amd_powergating_state state)652{653	struct amdgpu_device *adev = (struct amdgpu_device *)handle;654	int ret;655 656	if (amdgpu_sriov_vf(adev)) {657		adev->jpeg.cur_state = AMD_PG_STATE_UNGATE;658		return 0;659	}660 661	if (state == adev->jpeg.cur_state)662		return 0;663 664	if (state == AMD_PG_STATE_GATE)665		ret = jpeg_v4_0_stop(adev);666	else667		ret = jpeg_v4_0_start(adev);668 669	if (!ret)670		adev->jpeg.cur_state = state;671 672	return ret;673}674 675static int jpeg_v4_0_set_ras_interrupt_state(struct amdgpu_device *adev,676					struct amdgpu_irq_src *source,677					unsigned int type,678					enum amdgpu_interrupt_state state)679{680	return 0;681}682 683static int jpeg_v4_0_process_interrupt(struct amdgpu_device *adev,684				      struct amdgpu_irq_src *source,685				      struct amdgpu_iv_entry *entry)686{687	DRM_DEBUG("IH: JPEG TRAP\n");688 689	switch (entry->src_id) {690	case VCN_4_0__SRCID__JPEG_DECODE:691		amdgpu_fence_process(adev->jpeg.inst->ring_dec);692		break;693	default:694		DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",695			  entry->src_id, entry->src_data[0]);696		break;697	}698 699	return 0;700}701 702static const struct amd_ip_funcs jpeg_v4_0_ip_funcs = {703	.name = "jpeg_v4_0",704	.early_init = jpeg_v4_0_early_init,705	.late_init = NULL,706	.sw_init = jpeg_v4_0_sw_init,707	.sw_fini = jpeg_v4_0_sw_fini,708	.hw_init = jpeg_v4_0_hw_init,709	.hw_fini = jpeg_v4_0_hw_fini,710	.suspend = jpeg_v4_0_suspend,711	.resume = jpeg_v4_0_resume,712	.is_idle = jpeg_v4_0_is_idle,713	.wait_for_idle = jpeg_v4_0_wait_for_idle,714	.check_soft_reset = NULL,715	.pre_soft_reset = NULL,716	.soft_reset = NULL,717	.post_soft_reset = NULL,718	.set_clockgating_state = jpeg_v4_0_set_clockgating_state,719	.set_powergating_state = jpeg_v4_0_set_powergating_state,720	.dump_ip_state = NULL,721	.print_ip_state = NULL,722};723 724static const struct amdgpu_ring_funcs jpeg_v4_0_dec_ring_vm_funcs = {725	.type = AMDGPU_RING_TYPE_VCN_JPEG,726	.align_mask = 0xf,727	.get_rptr = jpeg_v4_0_dec_ring_get_rptr,728	.get_wptr = jpeg_v4_0_dec_ring_get_wptr,729	.set_wptr = jpeg_v4_0_dec_ring_set_wptr,730	.parse_cs = jpeg_v2_dec_ring_parse_cs,731	.emit_frame_size =732		SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +733		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +734		8 + /* jpeg_v4_0_dec_ring_emit_vm_flush */735		18 + 18 + /* jpeg_v4_0_dec_ring_emit_fence x2 vm fence */736		8 + 16,737	.emit_ib_size = 22, /* jpeg_v4_0_dec_ring_emit_ib */738	.emit_ib = jpeg_v2_0_dec_ring_emit_ib,739	.emit_fence = jpeg_v2_0_dec_ring_emit_fence,740	.emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,741	.test_ring = amdgpu_jpeg_dec_ring_test_ring,742	.test_ib = amdgpu_jpeg_dec_ring_test_ib,743	.insert_nop = jpeg_v2_0_dec_ring_nop,744	.insert_start = jpeg_v2_0_dec_ring_insert_start,745	.insert_end = jpeg_v2_0_dec_ring_insert_end,746	.pad_ib = amdgpu_ring_generic_pad_ib,747	.begin_use = amdgpu_jpeg_ring_begin_use,748	.end_use = amdgpu_jpeg_ring_end_use,749	.emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,750	.emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,751	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,752};753 754static void jpeg_v4_0_set_dec_ring_funcs(struct amdgpu_device *adev)755{756	adev->jpeg.inst->ring_dec->funcs = &jpeg_v4_0_dec_ring_vm_funcs;757}758 759static const struct amdgpu_irq_src_funcs jpeg_v4_0_irq_funcs = {760	.process = jpeg_v4_0_process_interrupt,761};762 763static const struct amdgpu_irq_src_funcs jpeg_v4_0_ras_irq_funcs = {764	.set = jpeg_v4_0_set_ras_interrupt_state,765	.process = amdgpu_jpeg_process_poison_irq,766};767 768static void jpeg_v4_0_set_irq_funcs(struct amdgpu_device *adev)769{770	adev->jpeg.inst->irq.num_types = 1;771	adev->jpeg.inst->irq.funcs = &jpeg_v4_0_irq_funcs;772 773	adev->jpeg.inst->ras_poison_irq.num_types = 1;774	adev->jpeg.inst->ras_poison_irq.funcs = &jpeg_v4_0_ras_irq_funcs;775}776 777const struct amdgpu_ip_block_version jpeg_v4_0_ip_block = {778	.type = AMD_IP_BLOCK_TYPE_JPEG,779	.major = 4,780	.minor = 0,781	.rev = 0,782	.funcs = &jpeg_v4_0_ip_funcs,783};784 785static uint32_t jpeg_v4_0_query_poison_by_instance(struct amdgpu_device *adev,786		uint32_t instance, uint32_t sub_block)787{788	uint32_t poison_stat = 0, reg_value = 0;789 790	switch (sub_block) {791	case AMDGPU_JPEG_V4_0_JPEG0:792		reg_value = RREG32_SOC15(JPEG, instance, regUVD_RAS_JPEG0_STATUS);793		poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG0_STATUS, POISONED_PF);794		break;795	case AMDGPU_JPEG_V4_0_JPEG1:796		reg_value = RREG32_SOC15(JPEG, instance, regUVD_RAS_JPEG1_STATUS);797		poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG1_STATUS, POISONED_PF);798		break;799	default:800		break;801	}802 803	if (poison_stat)804		dev_info(adev->dev, "Poison detected in JPEG%d sub_block%d\n",805			instance, sub_block);806 807	return poison_stat;808}809 810static bool jpeg_v4_0_query_ras_poison_status(struct amdgpu_device *adev)811{812	uint32_t inst = 0, sub = 0, poison_stat = 0;813 814	for (inst = 0; inst < adev->jpeg.num_jpeg_inst; inst++)815		for (sub = 0; sub < AMDGPU_JPEG_V4_0_MAX_SUB_BLOCK; sub++)816			poison_stat +=817				jpeg_v4_0_query_poison_by_instance(adev, inst, sub);818 819	return !!poison_stat;820}821 822const struct amdgpu_ras_block_hw_ops jpeg_v4_0_ras_hw_ops = {823	.query_poison_status = jpeg_v4_0_query_ras_poison_status,824};825 826static struct amdgpu_jpeg_ras jpeg_v4_0_ras = {827	.ras_block = {828		.hw_ops = &jpeg_v4_0_ras_hw_ops,829		.ras_late_init = amdgpu_jpeg_ras_late_init,830	},831};832 833static void jpeg_v4_0_set_ras_funcs(struct amdgpu_device *adev)834{835	switch (amdgpu_ip_version(adev, JPEG_HWIP, 0)) {836	case IP_VERSION(4, 0, 0):837		adev->jpeg.ras = &jpeg_v4_0_ras;838		break;839	default:840		break;841	}842}843