diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2014-06-25 22:41:34 (GMT) |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2014-08-05 12:53:23 (GMT) |
commit | 629bd33c75196ca89625148614e9e34b42f4f460 (patch) | |
tree | f73eb3f18e2e57f4e8b8ee6df1d3c7ed91d9a8a9 /drivers/gpu/drm/radeon/si_smc.c | |
parent | de5158226d47829f85c07dd5bca59d96213e1e08 (diff) | |
download | linux-629bd33c75196ca89625148614e9e34b42f4f460.tar.xz |
drm/radeon/si: Add support for new ucode format (v3)
This adds SI support for the new ucode format.
v2: add size validation, integrate debug info
v3: update to latest version
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/si_smc.c')
-rw-r--r-- | drivers/gpu/drm/radeon/si_smc.c | 62 |
1 files changed, 37 insertions, 25 deletions
diff --git a/drivers/gpu/drm/radeon/si_smc.c b/drivers/gpu/drm/radeon/si_smc.c index e80efcf..73dbc79 100644 --- a/drivers/gpu/drm/radeon/si_smc.c +++ b/drivers/gpu/drm/radeon/si_smc.c @@ -219,36 +219,48 @@ int si_load_smc_ucode(struct radeon_device *rdev, u32 limit) if (!rdev->smc_fw) return -EINVAL; - switch (rdev->family) { - case CHIP_TAHITI: - ucode_start_address = TAHITI_SMC_UCODE_START; - ucode_size = TAHITI_SMC_UCODE_SIZE; - break; - case CHIP_PITCAIRN: - ucode_start_address = PITCAIRN_SMC_UCODE_START; - ucode_size = PITCAIRN_SMC_UCODE_SIZE; - break; - case CHIP_VERDE: - ucode_start_address = VERDE_SMC_UCODE_START; - ucode_size = VERDE_SMC_UCODE_SIZE; - break; - case CHIP_OLAND: - ucode_start_address = OLAND_SMC_UCODE_START; - ucode_size = OLAND_SMC_UCODE_SIZE; - break; - case CHIP_HAINAN: - ucode_start_address = HAINAN_SMC_UCODE_START; - ucode_size = HAINAN_SMC_UCODE_SIZE; - break; - default: - DRM_ERROR("unknown asic in smc ucode loader\n"); - BUG(); + if (rdev->new_fw) { + const struct smc_firmware_header_v1_0 *hdr = + (const struct smc_firmware_header_v1_0 *)rdev->smc_fw->data; + + radeon_ucode_print_smc_hdr(&hdr->header); + + ucode_start_address = le32_to_cpu(hdr->ucode_start_addr); + ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes); + src = (const u8 *) + (rdev->smc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + } else { + switch (rdev->family) { + case CHIP_TAHITI: + ucode_start_address = TAHITI_SMC_UCODE_START; + ucode_size = TAHITI_SMC_UCODE_SIZE; + break; + case CHIP_PITCAIRN: + ucode_start_address = PITCAIRN_SMC_UCODE_START; + ucode_size = PITCAIRN_SMC_UCODE_SIZE; + break; + case CHIP_VERDE: + ucode_start_address = VERDE_SMC_UCODE_START; + ucode_size = VERDE_SMC_UCODE_SIZE; + break; + case CHIP_OLAND: + ucode_start_address = OLAND_SMC_UCODE_START; + ucode_size = OLAND_SMC_UCODE_SIZE; + break; + case CHIP_HAINAN: + ucode_start_address = HAINAN_SMC_UCODE_START; + ucode_size = HAINAN_SMC_UCODE_SIZE; + break; + default: + DRM_ERROR("unknown asic in smc ucode loader\n"); + BUG(); + } + src = (const u8 *)rdev->smc_fw->data; } if (ucode_size & 3) return -EINVAL; - src = (const u8 *)rdev->smc_fw->data; spin_lock_irqsave(&rdev->smc_idx_lock, flags); WREG32(SMC_IND_INDEX_0, ucode_start_address); WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0); |