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

drm/amdgpu: psp DTM init

DTM is the display topology manager. This is needed to communicate with
psp about the display configurations.

This patch adds
-Loading the firmware
-The functions and definitions for communication with the firmware

v2: Fix formatting

Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Bhawanpreet Lakha and committed by
Alex Deucher
143f2305 ed19a9a2

+181 -2
+154
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
··· 942 942 } 943 943 // HDCP end 944 944 945 + // DTM start 946 + static void psp_prep_dtm_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, 947 + uint64_t dtm_ta_mc, 948 + uint64_t dtm_mc_shared, 949 + uint32_t dtm_ta_size, 950 + uint32_t shared_size) 951 + { 952 + cmd->cmd_id = GFX_CMD_ID_LOAD_TA; 953 + cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(dtm_ta_mc); 954 + cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(dtm_ta_mc); 955 + cmd->cmd.cmd_load_ta.app_len = dtm_ta_size; 956 + 957 + cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(dtm_mc_shared); 958 + cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(dtm_mc_shared); 959 + cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size; 960 + } 961 + 962 + static int psp_dtm_init_shared_buf(struct psp_context *psp) 963 + { 964 + int ret; 965 + 966 + /* 967 + * Allocate 16k memory aligned to 4k from Frame Buffer (local 968 + * physical) for dtm ta <-> Driver 969 + */ 970 + ret = amdgpu_bo_create_kernel(psp->adev, PSP_DTM_SHARED_MEM_SIZE, 971 + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, 972 + &psp->dtm_context.dtm_shared_bo, 973 + &psp->dtm_context.dtm_shared_mc_addr, 974 + &psp->dtm_context.dtm_shared_buf); 975 + 976 + return ret; 977 + } 978 + 979 + static int psp_dtm_load(struct psp_context *psp) 980 + { 981 + int ret; 982 + struct psp_gfx_cmd_resp *cmd; 983 + 984 + /* 985 + * TODO: bypass the loading in sriov for now 986 + */ 987 + if (amdgpu_sriov_vf(psp->adev)) 988 + return 0; 989 + 990 + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 991 + if (!cmd) 992 + return -ENOMEM; 993 + 994 + memset(psp->fw_pri_buf, 0, PSP_1_MEG); 995 + memcpy(psp->fw_pri_buf, psp->ta_dtm_start_addr, psp->ta_dtm_ucode_size); 996 + 997 + psp_prep_dtm_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr, 998 + psp->dtm_context.dtm_shared_mc_addr, 999 + psp->ta_dtm_ucode_size, 1000 + PSP_DTM_SHARED_MEM_SIZE); 1001 + 1002 + ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 1003 + 1004 + if (!ret) { 1005 + psp->dtm_context.dtm_initialized = 1; 1006 + psp->dtm_context.session_id = cmd->resp.session_id; 1007 + } 1008 + 1009 + kfree(cmd); 1010 + 1011 + return ret; 1012 + } 1013 + 1014 + static int psp_dtm_initialize(struct psp_context *psp) 1015 + { 1016 + int ret; 1017 + 1018 + if (!psp->dtm_context.dtm_initialized) { 1019 + ret = psp_dtm_init_shared_buf(psp); 1020 + if (ret) 1021 + return ret; 1022 + } 1023 + 1024 + ret = psp_dtm_load(psp); 1025 + if (ret) 1026 + return ret; 1027 + 1028 + return 0; 1029 + } 1030 + 1031 + static void psp_prep_dtm_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, 1032 + uint32_t ta_cmd_id, 1033 + uint32_t dtm_session_id) 1034 + { 1035 + cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD; 1036 + cmd->cmd.cmd_invoke_cmd.session_id = dtm_session_id; 1037 + cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id; 1038 + /* Note: cmd_invoke_cmd.buf is not used for now */ 1039 + } 1040 + 1041 + int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 1042 + { 1043 + int ret; 1044 + struct psp_gfx_cmd_resp *cmd; 1045 + 1046 + /* 1047 + * TODO: bypass the loading in sriov for now 1048 + */ 1049 + if (amdgpu_sriov_vf(psp->adev)) 1050 + return 0; 1051 + 1052 + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 1053 + if (!cmd) 1054 + return -ENOMEM; 1055 + 1056 + psp_prep_dtm_ta_invoke_cmd_buf(cmd, ta_cmd_id, 1057 + psp->dtm_context.session_id); 1058 + 1059 + ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 1060 + 1061 + kfree(cmd); 1062 + 1063 + return ret; 1064 + } 1065 + 1066 + static int psp_dtm_terminate(struct psp_context *psp) 1067 + { 1068 + int ret; 1069 + 1070 + if (!psp->dtm_context.dtm_initialized) 1071 + return 0; 1072 + 1073 + ret = psp_hdcp_unload(psp); 1074 + if (ret) 1075 + return ret; 1076 + 1077 + psp->dtm_context.dtm_initialized = 0; 1078 + 1079 + /* free hdcp shared memory */ 1080 + amdgpu_bo_free_kernel(&psp->dtm_context.dtm_shared_bo, 1081 + &psp->dtm_context.dtm_shared_mc_addr, 1082 + &psp->dtm_context.dtm_shared_buf); 1083 + 1084 + return 0; 1085 + } 1086 + // DTM end 1087 + 945 1088 static int psp_hw_start(struct psp_context *psp) 946 1089 { 947 1090 struct amdgpu_device *adev = psp->adev; ··· 1163 1020 if (ret) 1164 1021 dev_err(psp->adev->dev, 1165 1022 "HDCP: Failed to initialize HDCP\n"); 1023 + 1024 + ret = psp_dtm_initialize(psp); 1025 + if (ret) 1026 + dev_err(psp->adev->dev, 1027 + "DTM: Failed to initialize DTM\n"); 1166 1028 } 1167 1029 1168 1030 return 0; ··· 1535 1387 1536 1388 if (psp->adev->psp.ta_fw) { 1537 1389 psp_ras_terminate(psp); 1390 + psp_dtm_terminate(psp); 1538 1391 psp_hdcp_terminate(psp); 1539 1392 } 1540 1393 ··· 1582 1433 ret = psp_hdcp_terminate(psp); 1583 1434 if (ret) { 1584 1435 DRM_ERROR("Failed to terminate hdcp ta\n"); 1436 + return ret; 1437 + } 1438 + ret = psp_dtm_terminate(psp); 1439 + if (ret) { 1440 + DRM_ERROR("Failed to terminate dtm ta\n"); 1585 1441 return ret; 1586 1442 } 1587 1443 }
+15
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
··· 38 38 #define PSP_1_MEG 0x100000 39 39 #define PSP_TMR_SIZE 0x400000 40 40 #define PSP_HDCP_SHARED_MEM_SIZE 0x4000 41 + #define PSP_DTM_SHARED_MEM_SIZE 0x4000 41 42 #define PSP_SHARED_MEM_SIZE 0x4000 42 43 43 44 struct psp_context; ··· 153 152 void *hdcp_shared_buf; 154 153 }; 155 154 155 + struct psp_dtm_context { 156 + bool dtm_initialized; 157 + uint32_t session_id; 158 + struct amdgpu_bo *dtm_shared_bo; 159 + uint64_t dtm_shared_mc_addr; 160 + void *dtm_shared_buf; 161 + }; 162 + 156 163 struct psp_context 157 164 { 158 165 struct amdgpu_device *adev; ··· 230 221 uint32_t ta_hdcp_ucode_size; 231 222 uint8_t *ta_hdcp_start_addr; 232 223 224 + uint32_t ta_dtm_ucode_version; 225 + uint32_t ta_dtm_ucode_size; 226 + uint8_t *ta_dtm_start_addr; 227 + 233 228 struct psp_xgmi_context xgmi_context; 234 229 struct psp_ras_context ras; 235 230 struct psp_hdcp_context hdcp_context; 231 + struct psp_dtm_context dtm_context; 236 232 struct mutex mutex; 237 233 }; 238 234 ··· 310 296 int psp_ras_enable_features(struct psp_context *psp, 311 297 union ta_ras_cmd_input *info, bool enable); 312 298 int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id); 299 + int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id); 313 300 314 301 int psp_rlc_autoload_start(struct psp_context *psp); 315 302
+3
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
··· 111 111 uint32_t ta_hdcp_ucode_version; 112 112 uint32_t ta_hdcp_offset_bytes; 113 113 uint32_t ta_hdcp_size_bytes; 114 + uint32_t ta_dtm_ucode_version; 115 + uint32_t ta_dtm_offset_bytes; 116 + uint32_t ta_dtm_size_bytes; 114 117 }; 115 118 116 119 /* version_major=1, version_minor=0 */
+9 -2
drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
··· 102 102 (uint8_t *)ta_hdr + 103 103 le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); 104 104 105 - adev->psp.ta_fw_version = 106 - le32_to_cpu(ta_hdr->header.ucode_version); 105 + adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); 106 + 107 + adev->psp.ta_dtm_ucode_version = 108 + le32_to_cpu(ta_hdr->ta_dtm_ucode_version); 109 + adev->psp.ta_dtm_ucode_size = 110 + le32_to_cpu(ta_hdr->ta_dtm_size_bytes); 111 + adev->psp.ta_dtm_start_addr = 112 + (uint8_t *)adev->psp.ta_hdcp_start_addr + 113 + le32_to_cpu(ta_hdr->ta_dtm_offset_bytes); 107 114 } 108 115 109 116 return 0;