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

drm/amdgpu/vcn1.0: use its own idle handler and begin use funcs

Because VCN1.0 power management and DPG mode are managed together with
JPEG1.0 under both HW and FW, so separated them from general VCN code.
Also the multiple instances case got removed, since VCN1.0 HW just have
a single instance.

v2: override work func with vcn1.0's own

Signed-off-by: Leo Liu <leo.liu@amd.com>
Reviewed-by: James Zhu <James.Zhu@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Leo Liu and committed by
Alex Deucher
d58ed707 aaff8b44

+95 -6
-3
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
··· 39 39 #include "vcn/vcn_1_0_offset.h" 40 40 #include "vcn/vcn_1_0_sh_mask.h" 41 41 42 - /* 1 second timeout */ 43 - #define VCN_IDLE_TIMEOUT msecs_to_jiffies(1000) 44 - 45 42 /* Firmware Names */ 46 43 #define FIRMWARE_RAVEN "amdgpu/raven_vcn.bin" 47 44 #define FIRMWARE_PICASSO "amdgpu/picasso_vcn.bin"
+3
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
··· 56 56 #define VCN_VID_IP_ADDRESS_2_0 0x0 57 57 #define VCN_AON_IP_ADDRESS_2_0 0x30000 58 58 59 + /* 1 second timeout */ 60 + #define VCN_IDLE_TIMEOUT msecs_to_jiffies(1000) 61 + 59 62 #define RREG32_SOC15_DPG_MODE(ip, inst, reg, mask, sram_sel) \ 60 63 ({ WREG32_SOC15(ip, inst, mmUVD_DPG_LMA_MASK, mask); \ 61 64 WREG32_SOC15(ip, inst, mmUVD_DPG_LMA_CTL, \
+2 -1
drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
··· 25 25 #include "amdgpu_jpeg.h" 26 26 #include "soc15.h" 27 27 #include "soc15d.h" 28 + #include "vcn_v1_0.h" 28 29 29 30 #include "vcn/vcn_1_0_offset.h" 30 31 #include "vcn/vcn_1_0_sh_mask.h" ··· 562 561 .insert_start = jpeg_v1_0_decode_ring_insert_start, 563 562 .insert_end = jpeg_v1_0_decode_ring_insert_end, 564 563 .pad_ib = amdgpu_ring_generic_pad_ib, 565 - .begin_use = amdgpu_vcn_ring_begin_use, 564 + .begin_use = vcn_v1_0_ring_begin_use, 566 565 .end_use = amdgpu_vcn_ring_end_use, 567 566 .emit_wreg = jpeg_v1_0_decode_ring_emit_wreg, 568 567 .emit_reg_wait = jpeg_v1_0_decode_ring_emit_reg_wait,
+88 -2
drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
··· 25 25 26 26 #include "amdgpu.h" 27 27 #include "amdgpu_vcn.h" 28 + #include "amdgpu_pm.h" 28 29 #include "soc15.h" 29 30 #include "soc15d.h" 30 31 #include "soc15_common.h" ··· 51 50 static int vcn_v1_0_set_powergating_state(void *handle, enum amd_powergating_state state); 52 51 static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev, 53 52 struct dpg_pause_state *new_state); 53 + 54 + static void vcn_v1_0_idle_work_handler(struct work_struct *work); 54 55 55 56 /** 56 57 * vcn_v1_0_early_init - set function pointers ··· 107 104 r = amdgpu_vcn_sw_init(adev); 108 105 if (r) 109 106 return r; 107 + 108 + /* Override the work func */ 109 + adev->vcn.idle_work.work.func = vcn_v1_0_idle_work_handler; 110 110 111 111 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { 112 112 const struct common_firmware_header *hdr; ··· 1764 1758 return ret; 1765 1759 } 1766 1760 1761 + static void vcn_v1_0_idle_work_handler(struct work_struct *work) 1762 + { 1763 + struct amdgpu_device *adev = 1764 + container_of(work, struct amdgpu_device, vcn.idle_work.work); 1765 + unsigned int fences = 0, i; 1766 + 1767 + for (i = 0; i < adev->vcn.num_enc_rings; ++i) 1768 + fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]); 1769 + 1770 + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { 1771 + struct dpg_pause_state new_state; 1772 + 1773 + if (fences) 1774 + new_state.fw_based = VCN_DPG_STATE__PAUSE; 1775 + else 1776 + new_state.fw_based = VCN_DPG_STATE__UNPAUSE; 1777 + 1778 + if (amdgpu_fence_count_emitted(&adev->jpeg.inst->ring_dec)) 1779 + new_state.jpeg = VCN_DPG_STATE__PAUSE; 1780 + else 1781 + new_state.jpeg = VCN_DPG_STATE__UNPAUSE; 1782 + 1783 + adev->vcn.pause_dpg_mode(adev, &new_state); 1784 + } 1785 + 1786 + fences += amdgpu_fence_count_emitted(&adev->jpeg.inst->ring_dec); 1787 + fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_dec); 1788 + 1789 + if (fences == 0) { 1790 + amdgpu_gfx_off_ctrl(adev, true); 1791 + if (adev->pm.dpm_enabled) 1792 + amdgpu_dpm_enable_uvd(adev, false); 1793 + else 1794 + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN, 1795 + AMD_PG_STATE_GATE); 1796 + } else { 1797 + schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT); 1798 + } 1799 + } 1800 + 1801 + void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring) 1802 + { 1803 + struct amdgpu_device *adev = ring->adev; 1804 + bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work); 1805 + 1806 + if (set_clocks) { 1807 + amdgpu_gfx_off_ctrl(adev, false); 1808 + if (adev->pm.dpm_enabled) 1809 + amdgpu_dpm_enable_uvd(adev, true); 1810 + else 1811 + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN, 1812 + AMD_PG_STATE_UNGATE); 1813 + } 1814 + 1815 + if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { 1816 + struct dpg_pause_state new_state; 1817 + unsigned int fences = 0, i; 1818 + 1819 + for (i = 0; i < adev->vcn.num_enc_rings; ++i) 1820 + fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]); 1821 + 1822 + if (fences) 1823 + new_state.fw_based = VCN_DPG_STATE__PAUSE; 1824 + else 1825 + new_state.fw_based = VCN_DPG_STATE__UNPAUSE; 1826 + 1827 + if (amdgpu_fence_count_emitted(&adev->jpeg.inst->ring_dec)) 1828 + new_state.jpeg = VCN_DPG_STATE__PAUSE; 1829 + else 1830 + new_state.jpeg = VCN_DPG_STATE__UNPAUSE; 1831 + 1832 + if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) 1833 + new_state.fw_based = VCN_DPG_STATE__PAUSE; 1834 + else if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) 1835 + new_state.jpeg = VCN_DPG_STATE__PAUSE; 1836 + 1837 + adev->vcn.pause_dpg_mode(adev, &new_state); 1838 + } 1839 + } 1840 + 1767 1841 static const struct amd_ip_funcs vcn_v1_0_ip_funcs = { 1768 1842 .name = "vcn_v1_0", 1769 1843 .early_init = vcn_v1_0_early_init, ··· 1890 1804 .insert_start = vcn_v1_0_dec_ring_insert_start, 1891 1805 .insert_end = vcn_v1_0_dec_ring_insert_end, 1892 1806 .pad_ib = amdgpu_ring_generic_pad_ib, 1893 - .begin_use = amdgpu_vcn_ring_begin_use, 1807 + .begin_use = vcn_v1_0_ring_begin_use, 1894 1808 .end_use = amdgpu_vcn_ring_end_use, 1895 1809 .emit_wreg = vcn_v1_0_dec_ring_emit_wreg, 1896 1810 .emit_reg_wait = vcn_v1_0_dec_ring_emit_reg_wait, ··· 1922 1836 .insert_nop = amdgpu_ring_insert_nop, 1923 1837 .insert_end = vcn_v1_0_enc_ring_insert_end, 1924 1838 .pad_ib = amdgpu_ring_generic_pad_ib, 1925 - .begin_use = amdgpu_vcn_ring_begin_use, 1839 + .begin_use = vcn_v1_0_ring_begin_use, 1926 1840 .end_use = amdgpu_vcn_ring_end_use, 1927 1841 .emit_wreg = vcn_v1_0_enc_ring_emit_wreg, 1928 1842 .emit_reg_wait = vcn_v1_0_enc_ring_emit_reg_wait,
+2
drivers/gpu/drm/amd/amdgpu/vcn_v1_0.h
··· 24 24 #ifndef __VCN_V1_0_H__ 25 25 #define __VCN_V1_0_H__ 26 26 27 + void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring); 28 + 27 29 extern const struct amdgpu_ip_block_version vcn_v1_0_ip_block; 28 30 29 31 #endif