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

drm/amd/display: Make DMCUB bss/data firmware blob optional

[Why]
By moving everything out of .data into the other regions we can drop
the requirement for the second blob and unify it all into the inst/const
blob.

[How]
We need to still support the blob being there and not being there for
backwards compatibility.

Look for the DMCUB metadata section in the end of the inst/const blob
instead of bss/data is missing.

Clear CW2 if we don't have the data blob so we don't hang when
transitioning between data blob/blobless firmwares.

Don't memcpy the blob into CW2 region if it doesn't exist.

Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Nicholas Kazlauskas and committed by
Alex Deucher
a576b345 8ccf0e20

+40 -15
+7 -2
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 825 825 fw_inst_const_size); 826 826 } 827 827 828 - memcpy(fb_info->fb[DMUB_WINDOW_2_BSS_DATA].cpu_addr, fw_bss_data, 829 - fw_bss_data_size); 828 + if (fw_bss_data_size) 829 + memcpy(fb_info->fb[DMUB_WINDOW_2_BSS_DATA].cpu_addr, 830 + fw_bss_data, fw_bss_data_size); 830 831 831 832 /* Copy firmware bios info into FB memory. */ 832 833 memcpy(fb_info->fb[DMUB_WINDOW_3_VBIOS].cpu_addr, adev->bios, ··· 1266 1265 adev->dm.dmub_fw->data + 1267 1266 le32_to_cpu(hdr->header.ucode_array_offset_bytes) + 1268 1267 le32_to_cpu(hdr->inst_const_bytes); 1268 + region_params.fw_inst_const = 1269 + adev->dm.dmub_fw->data + 1270 + le32_to_cpu(hdr->header.ucode_array_offset_bytes) + 1271 + PSP_HEADER_BYTES; 1269 1272 1270 1273 status = dmub_srv_calc_region_info(dmub_srv, &region_params, 1271 1274 &region_info);
+1
drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h
··· 151 151 uint32_t inst_const_size; 152 152 uint32_t bss_data_size; 153 153 uint32_t vbios_size; 154 + const uint8_t *fw_inst_const; 154 155 const uint8_t *fw_bss_data; 155 156 }; 156 157
+15 -7
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
··· 186 186 187 187 dmub_dcn20_get_fb_base_offset(dmub, &fb_base, &fb_offset); 188 188 189 - dmub_dcn20_translate_addr(&cw2->offset, fb_base, fb_offset, &offset); 189 + if (cw2->region.base != cw2->region.top) { 190 + dmub_dcn20_translate_addr(&cw2->offset, fb_base, fb_offset, 191 + &offset); 190 192 191 - REG_WRITE(DMCUB_REGION3_CW2_OFFSET, offset.u.low_part); 192 - REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, offset.u.high_part); 193 - REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, cw2->region.base); 194 - REG_SET_2(DMCUB_REGION3_CW2_TOP_ADDRESS, 0, 195 - DMCUB_REGION3_CW2_TOP_ADDRESS, cw2->region.top, 196 - DMCUB_REGION3_CW2_ENABLE, 1); 193 + REG_WRITE(DMCUB_REGION3_CW2_OFFSET, offset.u.low_part); 194 + REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, offset.u.high_part); 195 + REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, cw2->region.base); 196 + REG_SET_2(DMCUB_REGION3_CW2_TOP_ADDRESS, 0, 197 + DMCUB_REGION3_CW2_TOP_ADDRESS, cw2->region.top, 198 + DMCUB_REGION3_CW2_ENABLE, 1); 199 + } else { 200 + REG_WRITE(DMCUB_REGION3_CW2_OFFSET, 0); 201 + REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, 0); 202 + REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, 0); 203 + REG_WRITE(DMCUB_REGION3_CW2_TOP_ADDRESS, 0); 204 + } 197 205 198 206 dmub_dcn20_translate_addr(&cw3->offset, fb_base, fb_offset, &offset); 199 207
+17 -6
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
··· 91 91 } 92 92 93 93 static const struct dmub_fw_meta_info * 94 - dmub_get_fw_meta_info(const uint8_t *fw_bss_data, uint32_t fw_bss_data_size) 94 + dmub_get_fw_meta_info(const struct dmub_srv_region_params *params) 95 95 { 96 96 const union dmub_fw_meta *meta; 97 + const uint8_t *blob = NULL; 98 + uint32_t blob_size = 0; 97 99 98 - if (fw_bss_data == NULL) 100 + if (params->fw_bss_data) { 101 + /* Legacy metadata region. */ 102 + blob = params->fw_bss_data; 103 + blob_size = params->bss_data_size; 104 + } else if (params->fw_inst_const) { 105 + /* Combined metadata region. */ 106 + blob = params->fw_inst_const; 107 + blob_size = params->inst_const_size; 108 + } 109 + 110 + if (!blob || !blob_size) 99 111 return NULL; 100 112 101 - if (fw_bss_data_size < sizeof(union dmub_fw_meta) + DMUB_FW_META_OFFSET) 113 + if (blob_size < sizeof(union dmub_fw_meta) + DMUB_FW_META_OFFSET) 102 114 return NULL; 103 115 104 - meta = (const union dmub_fw_meta *)(fw_bss_data + fw_bss_data_size - 116 + meta = (const union dmub_fw_meta *)(blob + blob_size - 105 117 DMUB_FW_META_OFFSET - 106 118 sizeof(union dmub_fw_meta)); 107 119 ··· 259 247 mail->base = dmub_align(bios->top, 256); 260 248 mail->top = mail->base + DMUB_MAILBOX_SIZE; 261 249 262 - fw_info = dmub_get_fw_meta_info(params->fw_bss_data, 263 - params->bss_data_size); 250 + fw_info = dmub_get_fw_meta_info(params); 264 251 265 252 if (fw_info) { 266 253 fw_state_size = fw_info->fw_region_size;