OSDN Git Service

drm/amd/display: Make DMCUB bss/data firmware blob optional
authorNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Sun, 5 Apr 2020 20:41:14 +0000 (16:41 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 9 Apr 2020 14:43:17 +0000 (10:43 -0400)
[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>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c

index 8d09f07..47b04f0 100644 (file)
@@ -825,8 +825,9 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
                                fw_inst_const_size);
        }
 
-       memcpy(fb_info->fb[DMUB_WINDOW_2_BSS_DATA].cpu_addr, fw_bss_data,
-              fw_bss_data_size);
+       if (fw_bss_data_size)
+               memcpy(fb_info->fb[DMUB_WINDOW_2_BSS_DATA].cpu_addr,
+                      fw_bss_data, fw_bss_data_size);
 
        /* Copy firmware bios info into FB memory. */
        memcpy(fb_info->fb[DMUB_WINDOW_3_VBIOS].cpu_addr, adev->bios,
@@ -1265,6 +1266,10 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
                adev->dm.dmub_fw->data +
                le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
                le32_to_cpu(hdr->inst_const_bytes);
+       region_params.fw_inst_const =
+               adev->dm.dmub_fw->data +
+               le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
+               PSP_HEADER_BYTES;
 
        status = dmub_srv_calc_region_info(dmub_srv, &region_params,
                                           &region_info);
index af67846..e40d1cd 100644 (file)
@@ -151,6 +151,7 @@ struct dmub_srv_region_params {
        uint32_t inst_const_size;
        uint32_t bss_data_size;
        uint32_t vbios_size;
+       const uint8_t *fw_inst_const;
        const uint8_t *fw_bss_data;
 };
 
index 63bb9e2..45638d6 100644 (file)
@@ -186,14 +186,22 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
 
        dmub_dcn20_get_fb_base_offset(dmub, &fb_base, &fb_offset);
 
-       dmub_dcn20_translate_addr(&cw2->offset, fb_base, fb_offset, &offset);
-
-       REG_WRITE(DMCUB_REGION3_CW2_OFFSET, offset.u.low_part);
-       REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, offset.u.high_part);
-       REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, cw2->region.base);
-       REG_SET_2(DMCUB_REGION3_CW2_TOP_ADDRESS, 0,
-                 DMCUB_REGION3_CW2_TOP_ADDRESS, cw2->region.top,
-                 DMCUB_REGION3_CW2_ENABLE, 1);
+       if (cw2->region.base != cw2->region.top) {
+               dmub_dcn20_translate_addr(&cw2->offset, fb_base, fb_offset,
+                                         &offset);
+
+               REG_WRITE(DMCUB_REGION3_CW2_OFFSET, offset.u.low_part);
+               REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, offset.u.high_part);
+               REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, cw2->region.base);
+               REG_SET_2(DMCUB_REGION3_CW2_TOP_ADDRESS, 0,
+                         DMCUB_REGION3_CW2_TOP_ADDRESS, cw2->region.top,
+                         DMCUB_REGION3_CW2_ENABLE, 1);
+       } else {
+               REG_WRITE(DMCUB_REGION3_CW2_OFFSET, 0);
+               REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, 0);
+               REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, 0);
+               REG_WRITE(DMCUB_REGION3_CW2_TOP_ADDRESS, 0);
+       }
 
        dmub_dcn20_translate_addr(&cw3->offset, fb_base, fb_offset, &offset);
 
index 0be8a54..0a1a851 100644 (file)
@@ -91,17 +91,29 @@ void dmub_flush_buffer_mem(const struct dmub_fb *fb)
 }
 
 static const struct dmub_fw_meta_info *
-dmub_get_fw_meta_info(const uint8_t *fw_bss_data, uint32_t fw_bss_data_size)
+dmub_get_fw_meta_info(const struct dmub_srv_region_params *params)
 {
        const union dmub_fw_meta *meta;
+       const uint8_t *blob = NULL;
+       uint32_t blob_size = 0;
+
+       if (params->fw_bss_data) {
+               /* Legacy metadata region. */
+               blob = params->fw_bss_data;
+               blob_size = params->bss_data_size;
+       } else if (params->fw_inst_const) {
+               /* Combined metadata region. */
+               blob = params->fw_inst_const;
+               blob_size = params->inst_const_size;
+       }
 
-       if (fw_bss_data == NULL)
+       if (!blob || !blob_size)
                return NULL;
 
-       if (fw_bss_data_size < sizeof(union dmub_fw_meta) + DMUB_FW_META_OFFSET)
+       if (blob_size < sizeof(union dmub_fw_meta) + DMUB_FW_META_OFFSET)
                return NULL;
 
-       meta = (const union dmub_fw_meta *)(fw_bss_data + fw_bss_data_size -
+       meta = (const union dmub_fw_meta *)(blob + blob_size -
                                            DMUB_FW_META_OFFSET -
                                            sizeof(union dmub_fw_meta));
 
@@ -247,8 +259,7 @@ dmub_srv_calc_region_info(struct dmub_srv *dmub,
        mail->base = dmub_align(bios->top, 256);
        mail->top = mail->base + DMUB_MAILBOX_SIZE;
 
-       fw_info = dmub_get_fw_meta_info(params->fw_bss_data,
-                                       params->bss_data_size);
+       fw_info = dmub_get_fw_meta_info(params);
 
        if (fw_info) {
                fw_state_size = fw_info->fw_region_size;