Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdgpu/vcn2.5: add dpg pause mode

Add dpg pause mode support for vcn2.5

Signed-off-by: James Zhu <James.Zhu@amd.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

James Zhu and committed by
Alex Deucher
8484df96 d2a2c64f

+70
+70
drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
··· 55 55 static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev); 56 56 static int vcn_v2_5_set_powergating_state(void *handle, 57 57 enum amd_powergating_state state); 58 + static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev, 59 + int inst_idx, struct dpg_pause_state *new_state); 58 60 static int vcn_v2_5_sriov_start(struct amdgpu_device *adev); 59 61 60 62 static int amdgpu_ih_clientid_vcns[] = { ··· 213 211 if (r) 214 212 return r; 215 213 } 214 + 215 + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) 216 + adev->vcn.pause_dpg_mode = vcn_v2_5_pause_dpg_mode; 216 217 217 218 return 0; 218 219 } ··· 1327 1322 return 0; 1328 1323 } 1329 1324 1325 + static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev, 1326 + int inst_idx, struct dpg_pause_state *new_state) 1327 + { 1328 + struct amdgpu_ring *ring; 1329 + uint32_t reg_data = 0; 1330 + int ret_code; 1331 + 1332 + /* pause/unpause if state is changed */ 1333 + if (adev->vcn.pause_state.fw_based != new_state->fw_based) { 1334 + DRM_DEBUG("dpg pause state changed %d -> %d", 1335 + adev->vcn.pause_state.fw_based, new_state->fw_based); 1336 + reg_data = RREG32_SOC15(UVD, inst_idx, mmUVD_DPG_PAUSE) & 1337 + (~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK); 1338 + 1339 + if (new_state->fw_based == VCN_DPG_STATE__PAUSE) { 1340 + ret_code = 0; 1341 + SOC15_WAIT_ON_RREG(UVD, inst_idx, mmUVD_POWER_STATUS, 0x1, 1342 + UVD_POWER_STATUS__UVD_POWER_STATUS_MASK, ret_code); 1343 + 1344 + if (!ret_code) { 1345 + /* pause DPG */ 1346 + reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK; 1347 + WREG32_SOC15(UVD, inst_idx, mmUVD_DPG_PAUSE, reg_data); 1348 + 1349 + /* wait for ACK */ 1350 + SOC15_WAIT_ON_RREG(UVD, inst_idx, mmUVD_DPG_PAUSE, 1351 + UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK, 1352 + UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK, ret_code); 1353 + 1354 + /* Restore */ 1355 + ring = &adev->vcn.inst[inst_idx].ring_enc[0]; 1356 + WREG32_SOC15(UVD, inst_idx, mmUVD_RB_BASE_LO, ring->gpu_addr); 1357 + WREG32_SOC15(UVD, inst_idx, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); 1358 + WREG32_SOC15(UVD, inst_idx, mmUVD_RB_SIZE, ring->ring_size / 4); 1359 + WREG32_SOC15(UVD, inst_idx, mmUVD_RB_RPTR, lower_32_bits(ring->wptr)); 1360 + WREG32_SOC15(UVD, inst_idx, mmUVD_RB_WPTR, lower_32_bits(ring->wptr)); 1361 + 1362 + ring = &adev->vcn.inst[inst_idx].ring_enc[1]; 1363 + WREG32_SOC15(UVD, inst_idx, mmUVD_RB_BASE_LO2, ring->gpu_addr); 1364 + WREG32_SOC15(UVD, inst_idx, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); 1365 + WREG32_SOC15(UVD, inst_idx, mmUVD_RB_SIZE2, ring->ring_size / 4); 1366 + WREG32_SOC15(UVD, inst_idx, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr)); 1367 + WREG32_SOC15(UVD, inst_idx, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr)); 1368 + 1369 + WREG32_SOC15(UVD, inst_idx, mmUVD_RBC_RB_WPTR, 1370 + RREG32_SOC15(UVD, inst_idx, mmUVD_SCRATCH2) & 0x7FFFFFFF); 1371 + 1372 + SOC15_WAIT_ON_RREG(UVD, inst_idx, mmUVD_POWER_STATUS, 1373 + 0x0, UVD_POWER_STATUS__UVD_POWER_STATUS_MASK, ret_code); 1374 + } 1375 + } else { 1376 + /* unpause dpg, no need to wait */ 1377 + reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK; 1378 + WREG32_SOC15(UVD, inst_idx, mmUVD_DPG_PAUSE, reg_data); 1379 + } 1380 + adev->vcn.pause_state.fw_based = new_state->fw_based; 1381 + } 1382 + 1383 + return 0; 1384 + } 1385 + 1330 1386 /** 1331 1387 * vcn_v2_5_dec_ring_get_rptr - get read pointer 1332 1388 * ··· 1429 1363 static void vcn_v2_5_dec_ring_set_wptr(struct amdgpu_ring *ring) 1430 1364 { 1431 1365 struct amdgpu_device *adev = ring->adev; 1366 + 1367 + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) 1368 + WREG32_SOC15(UVD, ring->me, mmUVD_SCRATCH2, 1369 + lower_32_bits(ring->wptr) | 0x80000000); 1432 1370 1433 1371 if (ring->use_doorbell) { 1434 1372 adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr);