mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
bb2746ac91
commit
ed19a9a2bb
|
@ -767,6 +767,181 @@ static int psp_ras_initialize(struct psp_context *psp)
|
||||||
}
|
}
|
||||||
// ras end
|
// 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)
|
static int psp_hw_start(struct psp_context *psp)
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = psp->adev;
|
struct amdgpu_device *adev = psp->adev;
|
||||||
|
@ -840,6 +1015,11 @@ static int psp_hw_start(struct psp_context *psp)
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(psp->adev->dev,
|
dev_err(psp->adev->dev,
|
||||||
"RAS: Failed to initialize RAS\n");
|
"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;
|
return 0;
|
||||||
|
@ -1205,8 +1385,10 @@ static int psp_hw_fini(void *handle)
|
||||||
psp->xgmi_context.initialized == 1)
|
psp->xgmi_context.initialized == 1)
|
||||||
psp_xgmi_terminate(psp);
|
psp_xgmi_terminate(psp);
|
||||||
|
|
||||||
if (psp->adev->psp.ta_fw)
|
if (psp->adev->psp.ta_fw) {
|
||||||
psp_ras_terminate(psp);
|
psp_ras_terminate(psp);
|
||||||
|
psp_hdcp_terminate(psp);
|
||||||
|
}
|
||||||
|
|
||||||
psp_ring_destroy(psp, PSP_RING_TYPE__KM);
|
psp_ring_destroy(psp, PSP_RING_TYPE__KM);
|
||||||
|
|
||||||
|
@ -1248,6 +1430,11 @@ static int psp_suspend(void *handle)
|
||||||
DRM_ERROR("Failed to terminate ras ta\n");
|
DRM_ERROR("Failed to terminate ras ta\n");
|
||||||
return ret;
|
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);
|
ret = psp_ring_stop(psp, PSP_RING_TYPE__KM);
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
#define PSP_RAS_SHARED_MEM_SIZE 0x4000
|
#define PSP_RAS_SHARED_MEM_SIZE 0x4000
|
||||||
#define PSP_1_MEG 0x100000
|
#define PSP_1_MEG 0x100000
|
||||||
#define PSP_TMR_SIZE 0x400000
|
#define PSP_TMR_SIZE 0x400000
|
||||||
|
#define PSP_HDCP_SHARED_MEM_SIZE 0x4000
|
||||||
|
#define PSP_SHARED_MEM_SIZE 0x4000
|
||||||
|
|
||||||
struct psp_context;
|
struct psp_context;
|
||||||
struct psp_xgmi_node_info;
|
struct psp_xgmi_node_info;
|
||||||
|
@ -142,6 +144,14 @@ struct psp_ras_context {
|
||||||
struct amdgpu_ras *ras;
|
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 psp_context
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev;
|
struct amdgpu_device *adev;
|
||||||
|
@ -206,8 +216,14 @@ struct psp_context
|
||||||
uint32_t ta_ras_ucode_version;
|
uint32_t ta_ras_ucode_version;
|
||||||
uint32_t ta_ras_ucode_size;
|
uint32_t ta_ras_ucode_size;
|
||||||
uint8_t *ta_ras_start_addr;
|
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_xgmi_context xgmi_context;
|
||||||
struct psp_ras_context ras;
|
struct psp_ras_context ras;
|
||||||
|
struct psp_hdcp_context hdcp_context;
|
||||||
struct mutex mutex;
|
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_invoke(struct psp_context *psp, uint32_t ta_cmd_id);
|
||||||
int psp_ras_enable_features(struct psp_context *psp,
|
int psp_ras_enable_features(struct psp_context *psp,
|
||||||
union ta_ras_cmd_input *info, bool enable);
|
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);
|
int psp_rlc_autoload_start(struct psp_context *psp);
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,9 @@ struct ta_firmware_header_v1_0 {
|
||||||
uint32_t ta_ras_ucode_version;
|
uint32_t ta_ras_ucode_version;
|
||||||
uint32_t ta_ras_offset_bytes;
|
uint32_t ta_ras_offset_bytes;
|
||||||
uint32_t ta_ras_size_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 */
|
/* version_major=1, version_minor=0 */
|
||||||
|
|
|
@ -48,7 +48,7 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
|
||||||
char fw_name[30];
|
char fw_name[30];
|
||||||
int err = 0;
|
int err = 0;
|
||||||
const struct psp_firmware_header_v1_0 *hdr;
|
const struct psp_firmware_header_v1_0 *hdr;
|
||||||
|
const struct ta_firmware_header_v1_0 *ta_hdr;
|
||||||
DRM_DEBUG("\n");
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
switch (adev->asic_type) {
|
switch (adev->asic_type) {
|
||||||
|
@ -79,7 +79,38 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
|
||||||
adev->psp.asd_start_addr = (uint8_t *)hdr +
|
adev->psp.asd_start_addr = (uint8_t *)hdr +
|
||||||
le32_to_cpu(hdr->header.ucode_array_offset_bytes);
|
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;
|
return 0;
|
||||||
|
|
||||||
|
out2:
|
||||||
|
release_firmware(adev->psp.ta_fw);
|
||||||
|
adev->psp.ta_fw = NULL;
|
||||||
out:
|
out:
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(adev->dev,
|
dev_err(adev->dev,
|
||||||
|
|
Loading…
Reference in New Issue