From: Tom Chung <[email protected]> [Why] We need to reserve a memory buffer for boot time crc test during resume.
[How] Create a buffer during boot up and send the buffer info to DMUB. Reviewed-by: Wayne Lin <[email protected]> Signed-off-by: Tom Chung <[email protected]> Signed-off-by: Chuanyu Tseng <[email protected]> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 58 +++++++++++++++++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 21 +++++++ drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 27 +++++++++ drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 9 +++ 4 files changed, 115 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ff09a5371cb2..b1ac05abca07 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2286,6 +2286,11 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) &adev->dm.dmub_bo_gpu_addr, &adev->dm.dmub_bo_cpu_addr); + if (adev->dm.boot_time_crc_info.bo_ptr) + amdgpu_bo_free_kernel(&adev->dm.boot_time_crc_info.bo_ptr, + &adev->dm.boot_time_crc_info.gpu_addr, + &adev->dm.boot_time_crc_info.cpu_addr); + if (adev->dm.hpd_rx_offload_wq && adev->dm.dc) { for (i = 0; i < adev->dm.dc->caps.max_links; i++) { if (adev->dm.hpd_rx_offload_wq[i].wq) { @@ -2735,6 +2740,54 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev) return ret; } +static void amdgpu_dm_boot_time_crc_init(struct amdgpu_device *adev) +{ + struct dm_boot_time_crc_info *bootcrc_info = NULL; + struct dmub_srv *dmub = NULL; + union dmub_fw_boot_options option = {0}; + int ret = 0; + const uint32_t fb_size = 3 * 1024 * 1024; /* 3MB for DCC pattern */ + + if (!adev || !adev->dm.dc || !adev->dm.dc->ctx || + !adev->dm.dc->ctx->dmub_srv) { + return; + } + + dmub = adev->dm.dc->ctx->dmub_srv->dmub; + bootcrc_info = &adev->dm.boot_time_crc_info; + + if (!dmub || !dmub->hw_funcs.get_fw_boot_option) { + drm_dbg(adev_to_drm(adev), "failed to init boot time crc buffer\n"); + return; + } + + option = dmub->hw_funcs.get_fw_boot_option(dmub); + + /* Return if boot time CRC is not enabled */ + if (option.bits.bootcrc_en_at_S0i3 == 0) + return; + + /* Create a buffer for boot time CRC */ + ret = amdgpu_bo_create_kernel(adev, fb_size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT, + &bootcrc_info->bo_ptr, + &bootcrc_info->gpu_addr, + &bootcrc_info->cpu_addr); + + if (ret) { + drm_dbg(adev_to_drm(adev), "failed to create boot time crc buffer\n"); + } else { + bootcrc_info->size = fb_size; + + drm_dbg(adev_to_drm(adev), "boot time crc buffer created addr 0x%llx, size %u\n", + bootcrc_info->gpu_addr, bootcrc_info->size); + + /* Send the buffer info to DMUB */ + dc_dmub_srv_boot_time_crc_init(adev->dm.dc, + bootcrc_info->gpu_addr, bootcrc_info->size); + } +} + static int dm_late_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; @@ -2746,6 +2799,11 @@ static int dm_late_init(struct amdgpu_ip_block *ip_block) dmcu = adev->dm.dc->res_pool->dmcu; + /* Init the boot time CRC (skip in resume) */ + if ((adev->in_suspend == 0) && + (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(3, 6, 0))) + amdgpu_dm_boot_time_crc_init(adev); + for (i = 0; i < 16; i++) linear_lut[i] = 0xFFFF * i / 15; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 800813671748..83fefd902355 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -123,6 +123,20 @@ struct dm_compressor_info { uint64_t gpu_addr; }; +/** + * struct dm_boot_time_crc_info - Buffer info used by boot time CRC + * @cpu_addr: MMIO cpu addr + * @bo_ptr: Pointer to the buffer object + * @gpu_addr: MMIO gpu addr + * @size: Size of the buffer + */ +struct dm_boot_time_crc_info { + void *cpu_addr; + struct amdgpu_bo *bo_ptr; + uint64_t gpu_addr; + uint32_t size; +}; + typedef void (*dmub_notify_interrupt_callback_t)(struct amdgpu_device *adev, struct dmub_notification *notify); /** @@ -698,6 +712,13 @@ struct amdgpu_display_manager { struct completion replied; char reply_data[0x40]; // Cannot include dmub_cmd here } fused_io[8]; + + /** + * @dm_boot_time_crc_info: + * + * Buffer info for the boot time crc. + */ + struct dm_boot_time_crc_info boot_time_crc_info; }; enum dsc_clock_force_state { diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index e4dd5ca70987..d6a08064456b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -2349,6 +2349,33 @@ bool dc_dmub_srv_is_cursor_offload_enabled(const struct dc *dc) return dc->ctx->dmub_srv && dc->ctx->dmub_srv->cursor_offload_enabled; } +void dc_dmub_srv_boot_time_crc_init(const struct dc *dc, uint64_t gpu_addr, uint32_t size) +{ + struct dc_dmub_srv *dc_dmub_srv; + struct dc_context *dc_ctx; + union dmub_rb_cmd cmd = {0}; + bool result = false; + + if (!dc || !dc->ctx || !dc->ctx->dmub_srv || size == 0) + return; + + dc_dmub_srv = dc->ctx->dmub_srv; + dc_ctx = dc_dmub_srv->ctx; + + memset(&cmd, 0, sizeof(cmd)); + cmd.boot_time_crc_init.header.type = DMUB_CMD__BOOT_TIME_CRC; + cmd.boot_time_crc_init.header.sub_type = DMUB_CMD__BOOT_TIME_CRC_INIT_MEM; + cmd.boot_time_crc_init.header.payload_bytes = + sizeof(struct dmub_rb_cmd_boot_time_crc_init); + cmd.boot_time_crc_init.data.buffer_addr.quad_part = gpu_addr; + cmd.boot_time_crc_init.data.buffer_size = size; + + result = dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); + + if (!result) + DC_ERROR("Boot time crc init failed in DMUB"); +} + void dc_dmub_srv_release_hw(const struct dc *dc) { struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h index 72e0a41f39f0..6579cf9cce3c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -361,6 +361,15 @@ void dc_dmub_srv_program_cursor_now(struct dc *dc, const struct pipe_ctx *pipe); */ bool dc_dmub_srv_is_cursor_offload_enabled(const struct dc *dc); +/** + * dc_dmub_srv_boot_time_crc_init() - Initializes DMUB boot time CRC. + * + * @dc - pointer to DC object + * @gpu_addr - address for the boot time CRC buffer + * @size - size of the boot time CRC buffer + */ +void dc_dmub_srv_boot_time_crc_init(const struct dc *dc, uint64_t gpu_addr, uint32_t size); + /** * dc_dmub_srv_release_hw() - Notifies DMUB service that HW access is no longer required. * -- 2.43.0
