diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3858-drm-amdgpu-psp-HDCP-init.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3858-drm-amdgpu-psp-HDCP-init.patch | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3858-drm-amdgpu-psp-HDCP-init.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3858-drm-amdgpu-psp-HDCP-init.patch new file mode 100644 index 00000000..d85d9133 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3858-drm-amdgpu-psp-HDCP-init.patch @@ -0,0 +1,363 @@ +From 6be93ad7952cf7f0da502252c3937ef9396a8bec Mon Sep 17 00:00:00 2001 +From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> +Date: Wed, 19 Jun 2019 14:37:29 -0400 +Subject: [PATCH 3858/4256] drm/amdgpu: psp HDCP init + +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> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 189 +++++++++++++++++++++- + drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 17 ++ + drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 3 + + drivers/gpu/drm/amd/amdgpu/psp_v10_0.c | 33 +++- + 4 files changed, 240 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +index a0c5aae2daef..3301c390b151 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +@@ -770,6 +770,181 @@ static int psp_ras_initialize(struct psp_context *psp) + } + // ras end + ++// HDCP start ++static void psp_prep_hdcp_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, ++ uint64_t hdcp_ta_mc, ++ uint64_t hdcp_mc_shared, ++ uint32_t hdcp_ta_size, ++ uint32_t shared_size) ++{ ++ cmd->cmd_id = GFX_CMD_ID_LOAD_TA; ++ cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(hdcp_ta_mc); ++ cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(hdcp_ta_mc); ++ cmd->cmd.cmd_load_ta.app_len = hdcp_ta_size; ++ ++ cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = ++ lower_32_bits(hdcp_mc_shared); ++ cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = ++ upper_32_bits(hdcp_mc_shared); ++ cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size; ++} ++ ++static int psp_hdcp_init_shared_buf(struct psp_context *psp) ++{ ++ int ret; ++ ++ /* ++ * Allocate 16k memory aligned to 4k from Frame Buffer (local ++ * physical) for hdcp ta <-> Driver ++ */ ++ ret = amdgpu_bo_create_kernel(psp->adev, PSP_HDCP_SHARED_MEM_SIZE, ++ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, ++ &psp->hdcp_context.hdcp_shared_bo, ++ &psp->hdcp_context.hdcp_shared_mc_addr, ++ &psp->hdcp_context.hdcp_shared_buf); ++ ++ return ret; ++} ++ ++static int psp_hdcp_load(struct psp_context *psp) ++{ ++ int ret; ++ struct psp_gfx_cmd_resp *cmd; ++ ++ /* ++ * TODO: bypass the loading in sriov for now ++ */ ++ if (amdgpu_sriov_vf(psp->adev)) ++ return 0; ++ ++ cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); ++ if (!cmd) ++ return -ENOMEM; ++ ++ memset(psp->fw_pri_buf, 0, PSP_1_MEG); ++ memcpy(psp->fw_pri_buf, psp->ta_hdcp_start_addr, ++ psp->ta_hdcp_ucode_size); ++ ++ psp_prep_hdcp_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr, ++ psp->hdcp_context.hdcp_shared_mc_addr, ++ psp->ta_hdcp_ucode_size, ++ PSP_HDCP_SHARED_MEM_SIZE); ++ ++ ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); ++ ++ if (!ret) { ++ psp->hdcp_context.hdcp_initialized = 1; ++ psp->hdcp_context.session_id = cmd->resp.session_id; ++ } ++ ++ kfree(cmd); ++ ++ return ret; ++} ++static int psp_hdcp_initialize(struct psp_context *psp) ++{ ++ int ret; ++ ++ if (!psp->hdcp_context.hdcp_initialized) { ++ ret = psp_hdcp_init_shared_buf(psp); ++ if (ret) ++ return ret; ++ } ++ ++ ret = psp_hdcp_load(psp); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++static void psp_prep_hdcp_ta_unload_cmd_buf(struct psp_gfx_cmd_resp *cmd, ++ uint32_t hdcp_session_id) ++{ ++ cmd->cmd_id = GFX_CMD_ID_UNLOAD_TA; ++ cmd->cmd.cmd_unload_ta.session_id = hdcp_session_id; ++} ++ ++static int psp_hdcp_unload(struct psp_context *psp) ++{ ++ int ret; ++ struct psp_gfx_cmd_resp *cmd; ++ ++ /* ++ * TODO: bypass the unloading in sriov for now ++ */ ++ if (amdgpu_sriov_vf(psp->adev)) ++ return 0; ++ ++ cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); ++ if (!cmd) ++ return -ENOMEM; ++ ++ psp_prep_hdcp_ta_unload_cmd_buf(cmd, psp->hdcp_context.session_id); ++ ++ ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); ++ ++ kfree(cmd); ++ ++ return ret; ++} ++ ++static void psp_prep_hdcp_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, ++ uint32_t ta_cmd_id, ++ uint32_t hdcp_session_id) ++{ ++ cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD; ++ cmd->cmd.cmd_invoke_cmd.session_id = hdcp_session_id; ++ cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id; ++ /* Note: cmd_invoke_cmd.buf is not used for now */ ++} ++ ++int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id) ++{ ++ int ret; ++ struct psp_gfx_cmd_resp *cmd; ++ ++ /* ++ * TODO: bypass the loading in sriov for now ++ */ ++ if (amdgpu_sriov_vf(psp->adev)) ++ return 0; ++ ++ cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); ++ if (!cmd) ++ return -ENOMEM; ++ ++ psp_prep_hdcp_ta_invoke_cmd_buf(cmd, ta_cmd_id, ++ psp->hdcp_context.session_id); ++ ++ ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); ++ ++ kfree(cmd); ++ ++ return ret; ++} ++ ++static int psp_hdcp_terminate(struct psp_context *psp) ++{ ++ int ret; ++ ++ if (!psp->hdcp_context.hdcp_initialized) ++ return 0; ++ ++ ret = psp_hdcp_unload(psp); ++ if (ret) ++ return ret; ++ ++ psp->hdcp_context.hdcp_initialized = 0; ++ ++ /* free hdcp shared memory */ ++ amdgpu_bo_free_kernel(&psp->hdcp_context.hdcp_shared_bo, ++ &psp->hdcp_context.hdcp_shared_mc_addr, ++ &psp->hdcp_context.hdcp_shared_buf); ++ ++ return 0; ++} ++// HDCP end ++ + static int psp_hw_start(struct psp_context *psp) + { + struct amdgpu_device *adev = psp->adev; +@@ -843,6 +1018,11 @@ static int psp_hw_start(struct psp_context *psp) + if (ret) + dev_err(psp->adev->dev, + "RAS: Failed to initialize RAS\n"); ++ ++ ret = psp_hdcp_initialize(psp); ++ if (ret) ++ dev_err(psp->adev->dev, ++ "HDCP: Failed to initialize HDCP\n"); + } + + return 0; +@@ -1209,8 +1389,10 @@ static int psp_hw_fini(void *handle) + psp->xgmi_context.initialized == 1) + psp_xgmi_terminate(psp); + +- if (psp->adev->psp.ta_fw) ++ if (psp->adev->psp.ta_fw) { + psp_ras_terminate(psp); ++ psp_hdcp_terminate(psp); ++ } + + psp_ring_destroy(psp, PSP_RING_TYPE__KM); + +@@ -1252,6 +1434,11 @@ static int psp_suspend(void *handle) + DRM_ERROR("Failed to terminate ras ta\n"); + return ret; + } ++ ret = psp_hdcp_terminate(psp); ++ if (ret) { ++ DRM_ERROR("Failed to terminate hdcp ta\n"); ++ return ret; ++ } + } + + ret = psp_ring_stop(psp, PSP_RING_TYPE__KM); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +index bc0947f6bc8a..6788e1601945 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +@@ -37,6 +37,8 @@ + #define PSP_RAS_SHARED_MEM_SIZE 0x4000 + #define PSP_1_MEG 0x100000 + #define PSP_TMR_SIZE 0x400000 ++#define PSP_HDCP_SHARED_MEM_SIZE 0x4000 ++#define PSP_SHARED_MEM_SIZE 0x4000 + + struct psp_context; + struct psp_xgmi_node_info; +@@ -142,6 +144,14 @@ struct psp_ras_context { + struct amdgpu_ras *ras; + }; + ++struct psp_hdcp_context { ++ bool hdcp_initialized; ++ uint32_t session_id; ++ struct amdgpu_bo *hdcp_shared_bo; ++ uint64_t hdcp_shared_mc_addr; ++ void *hdcp_shared_buf; ++}; ++ + struct psp_context + { + struct amdgpu_device *adev; +@@ -206,8 +216,14 @@ struct psp_context + uint32_t ta_ras_ucode_version; + uint32_t ta_ras_ucode_size; + uint8_t *ta_ras_start_addr; ++ ++ uint32_t ta_hdcp_ucode_version; ++ uint32_t ta_hdcp_ucode_size; ++ uint8_t *ta_hdcp_start_addr; ++ + struct psp_xgmi_context xgmi_context; + struct psp_ras_context ras; ++ struct psp_hdcp_context hdcp_context; + struct mutex mutex; + }; + +@@ -279,6 +295,7 @@ int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id); + int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id); + int psp_ras_enable_features(struct psp_context *psp, + union ta_ras_cmd_input *info, bool enable); ++int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id); + + int psp_rlc_autoload_start(struct psp_context *psp); + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +index b34f00d42049..c2b593ab7495 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +@@ -108,6 +108,9 @@ struct ta_firmware_header_v1_0 { + uint32_t ta_ras_ucode_version; + uint32_t ta_ras_offset_bytes; + uint32_t ta_ras_size_bytes; ++ uint32_t ta_hdcp_ucode_version; ++ uint32_t ta_hdcp_offset_bytes; ++ uint32_t ta_hdcp_size_bytes; + }; + + /* version_major=1, version_minor=0 */ +diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c +index e5fff6b30137..a43d7bafe954 100644 +--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c +@@ -45,7 +45,7 @@ static int psp_v10_0_init_microcode(struct psp_context *psp) + char fw_name[30]; + int err = 0; + const struct psp_firmware_header_v1_0 *hdr; +- ++ const struct ta_firmware_header_v1_0 *ta_hdr; + DRM_DEBUG("\n"); + + switch (adev->asic_type) { +@@ -76,7 +76,38 @@ static int psp_v10_0_init_microcode(struct psp_context *psp) + adev->psp.asd_start_addr = (uint8_t *)hdr + + le32_to_cpu(hdr->header.ucode_array_offset_bytes); + ++ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name); ++ err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev); ++ if (err) { ++ release_firmware(adev->psp.ta_fw); ++ adev->psp.ta_fw = NULL; ++ dev_info(adev->dev, ++ "psp v10.0: Failed to load firmware \"%s\"\n", ++ fw_name); ++ } else { ++ err = amdgpu_ucode_validate(adev->psp.ta_fw); ++ if (err) ++ goto out2; ++ ++ ta_hdr = (const struct ta_firmware_header_v1_0 *) ++ adev->psp.ta_fw->data; ++ adev->psp.ta_hdcp_ucode_version = ++ le32_to_cpu(ta_hdr->ta_hdcp_ucode_version); ++ adev->psp.ta_hdcp_ucode_size = ++ le32_to_cpu(ta_hdr->ta_hdcp_size_bytes); ++ adev->psp.ta_hdcp_start_addr = ++ (uint8_t *)ta_hdr + ++ le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); ++ ++ adev->psp.ta_fw_version = ++ le32_to_cpu(ta_hdr->header.ucode_version); ++ } ++ + return 0; ++ ++out2: ++ release_firmware(adev->psp.ta_fw); ++ adev->psp.ta_fw = NULL; + out: + if (err) { + dev_err(adev->dev, +-- +2.17.1 + |