]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/display: LSDMA support
authorOstrowski Rafal <rostrows@amd.com>
Thu, 12 Jun 2025 07:08:51 +0000 (09:08 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 24 Jun 2025 13:57:51 +0000 (09:57 -0400)
[Why]
Driver should be able to send LSDMA commands to DMCUB

[How]
Driver can now send LSDMA commands to DMCUB.
DMCUB should process them and send to LSDMA controller.

Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Ostrowski Rafal <rostrows@amd.com>
Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
drivers/gpu/drm/amd/display/dmub/dmub_srv.h
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c

index 00ea81fa9573be6c69d06174b70b869b699cd460..1f685fc5c55ab115c886cdf9f47f27696bb8de65 100644 (file)
@@ -1984,3 +1984,202 @@ void dc_dmub_srv_ips_query_residency_info(struct dc_dmub_srv *dc_dmub_srv, struc
                                               DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
                        output->histogram[i] = 0;
 }
+
+bool dmub_lsdma_init(struct dc_dmub_srv *dc_dmub_srv)
+{
+       struct dc_context *dc_ctx = dc_dmub_srv->ctx;
+       union dmub_rb_cmd cmd;
+       enum dm_dmub_wait_type wait_type;
+       struct dmub_cmd_lsdma_data *lsdma_data = &cmd.lsdma.lsdma_data;
+       bool result;
+
+       memset(&cmd, 0, sizeof(cmd));
+
+       cmd.cmd_common.header.type     = DMUB_CMD__LSDMA;
+       cmd.cmd_common.header.sub_type = DMUB_CMD__LSDMA_INIT_CONFIG;
+       wait_type                      = DM_DMUB_WAIT_TYPE_NO_WAIT;
+
+       lsdma_data->u.init_data.gpu_addr_base.quad_part = dc_ctx->dmub_srv->dmub->lsdma_rb_fb.gpu_addr;
+       lsdma_data->u.init_data.ring_size               = dc_ctx->dmub_srv->dmub->lsdma_rb_fb.size;
+
+       result = dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, wait_type);
+
+       if (!result)
+               DC_ERROR("LSDMA Init failed in DMUB");
+
+       return result;
+}
+
+bool dmub_lsdma_send_linear_copy_packet(
+       struct dc_dmub_srv *dc_dmub_srv,
+       uint64_t src_addr,
+       uint64_t dst_addr,
+       uint32_t count)
+{
+       struct dc_context *dc_ctx = dc_dmub_srv->ctx;
+       union dmub_rb_cmd cmd;
+       enum dm_dmub_wait_type wait_type;
+       struct dmub_cmd_lsdma_data *lsdma_data = &cmd.lsdma.lsdma_data;
+       bool result;
+
+       memset(&cmd, 0, sizeof(cmd));
+
+       cmd.cmd_common.header.type     = DMUB_CMD__LSDMA;
+       cmd.cmd_common.header.sub_type = DMUB_CMD__LSDMA_LINEAR_COPY;
+       wait_type                      = DM_DMUB_WAIT_TYPE_NO_WAIT;
+
+       lsdma_data->u.linear_copy_data.count   = count - 1; // LSDMA controller expects bytes to copy -1
+       lsdma_data->u.linear_copy_data.src_lo  = src_addr & 0xFFFFFFFF;
+       lsdma_data->u.linear_copy_data.src_hi  = (src_addr >> 32) & 0xFFFFFFFF;
+       lsdma_data->u.linear_copy_data.dst_lo  = dst_addr & 0xFFFFFFFF;
+       lsdma_data->u.linear_copy_data.dst_hi  = (dst_addr >> 32) & 0xFFFFFFFF;
+
+       result = dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, wait_type);
+
+       if (!result)
+               DC_ERROR("LSDMA Linear Copy failed in DMUB");
+
+       return result;
+}
+
+bool dmub_lsdma_send_tiled_to_tiled_copy_command(
+       struct dc_dmub_srv *dc_dmub_srv,
+       struct lsdma_send_tiled_to_tiled_copy_command_params params)
+{
+       struct dc_context *dc_ctx = dc_dmub_srv->ctx;
+       union dmub_rb_cmd cmd;
+       enum dm_dmub_wait_type wait_type;
+       struct dmub_cmd_lsdma_data *lsdma_data = &cmd.lsdma.lsdma_data;
+       bool result;
+
+       memset(&cmd, 0, sizeof(cmd));
+
+       cmd.cmd_common.header.type     = DMUB_CMD__LSDMA;
+       cmd.cmd_common.header.sub_type = DMUB_CMD__LSDMA_TILED_TO_TILED_COPY;
+       wait_type                      = DM_DMUB_WAIT_TYPE_NO_WAIT;
+
+       lsdma_data->u.tiled_copy_data.src_addr_lo      = params.src_addr & 0xFFFFFFFF;
+       lsdma_data->u.tiled_copy_data.src_addr_hi      = (params.src_addr >> 32) & 0xFFFFFFFF;
+       lsdma_data->u.tiled_copy_data.dst_addr_lo      = params.dst_addr & 0xFFFFFFFF;
+       lsdma_data->u.tiled_copy_data.dst_addr_hi      = (params.dst_addr >> 32) & 0xFFFFFFFF;
+       lsdma_data->u.tiled_copy_data.src_x            = params.src_x;
+       lsdma_data->u.tiled_copy_data.src_y            = params.src_y;
+       lsdma_data->u.tiled_copy_data.dst_x            = params.dst_x;
+       lsdma_data->u.tiled_copy_data.dst_y            = params.dst_y;
+       lsdma_data->u.tiled_copy_data.src_width        = params.src_width - 1; // LSDMA controller expects width -1
+       lsdma_data->u.tiled_copy_data.dst_width        = params.dst_width - 1; // LSDMA controller expects width -1
+       lsdma_data->u.tiled_copy_data.src_swizzle_mode = params.swizzle_mode;
+       lsdma_data->u.tiled_copy_data.dst_swizzle_mode = params.swizzle_mode;
+       lsdma_data->u.tiled_copy_data.src_element_size = params.element_size;
+       lsdma_data->u.tiled_copy_data.dst_element_size = params.element_size;
+       lsdma_data->u.tiled_copy_data.rect_x           = params.rect_x;
+       lsdma_data->u.tiled_copy_data.rect_y           = params.rect_y;
+       lsdma_data->u.tiled_copy_data.dcc              = params.dcc;
+       lsdma_data->u.tiled_copy_data.tmz              = params.tmz;
+       lsdma_data->u.tiled_copy_data.read_compress    = params.read_compress;
+       lsdma_data->u.tiled_copy_data.write_compress   = params.write_compress;
+       lsdma_data->u.tiled_copy_data.src_height       = params.src_height - 1; // LSDMA controller expects height -1
+       lsdma_data->u.tiled_copy_data.dst_height       = params.dst_height - 1; // LSDMA controller expects height -1
+       lsdma_data->u.tiled_copy_data.data_format      = params.data_format;
+       lsdma_data->u.tiled_copy_data.max_com          = params.max_com;
+       lsdma_data->u.tiled_copy_data.max_uncom        = params.max_uncom;
+
+       result = dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, wait_type);
+
+       if (!result)
+               DC_ERROR("LSDMA Tiled to Tiled Copy failed in DMUB");
+
+       return result;
+}
+
+bool dmub_lsdma_send_pio_copy_command(
+       struct dc_dmub_srv *dc_dmub_srv,
+       uint64_t src_addr,
+       uint64_t dst_addr,
+       uint32_t byte_count,
+       uint32_t overlap_disable)
+{
+       struct dc_context *dc_ctx = dc_dmub_srv->ctx;
+       union dmub_rb_cmd cmd;
+       enum dm_dmub_wait_type wait_type;
+       struct dmub_cmd_lsdma_data *lsdma_data = &cmd.lsdma.lsdma_data;
+       bool result;
+
+       memset(&cmd, 0, sizeof(cmd));
+
+       cmd.cmd_common.header.type     = DMUB_CMD__LSDMA;
+       cmd.cmd_common.header.sub_type = DMUB_CMD__LSDMA_PIO_COPY;
+       wait_type                      = DM_DMUB_WAIT_TYPE_NO_WAIT;
+
+       lsdma_data->u.pio_copy_data.packet.fields.byte_count      = byte_count;
+       lsdma_data->u.pio_copy_data.packet.fields.overlap_disable = overlap_disable;
+       lsdma_data->u.pio_copy_data.src_lo                        = src_addr & 0xFFFFFFFF;
+       lsdma_data->u.pio_copy_data.src_hi                        = (src_addr >> 32) & 0xFFFFFFFF;
+       lsdma_data->u.pio_copy_data.dst_lo                        = dst_addr & 0xFFFFFFFF;
+       lsdma_data->u.pio_copy_data.dst_hi                        = (dst_addr >> 32) & 0xFFFFFFFF;
+
+       result = dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, wait_type);
+
+       if (!result)
+               DC_ERROR("LSDMA PIO Copy failed in DMUB");
+
+       return result;
+}
+
+bool dmub_lsdma_send_pio_constfill_command(
+       struct dc_dmub_srv *dc_dmub_srv,
+       uint64_t dst_addr,
+       uint32_t byte_count,
+       uint32_t data)
+{
+       struct dc_context *dc_ctx = dc_dmub_srv->ctx;
+       union dmub_rb_cmd cmd;
+       enum dm_dmub_wait_type wait_type;
+       struct dmub_cmd_lsdma_data *lsdma_data = &cmd.lsdma.lsdma_data;
+       bool result;
+
+       memset(&cmd, 0, sizeof(cmd));
+
+       cmd.cmd_common.header.type     = DMUB_CMD__LSDMA;
+       cmd.cmd_common.header.sub_type = DMUB_CMD__LSDMA_PIO_CONSTFILL;
+       wait_type                      = DM_DMUB_WAIT_TYPE_NO_WAIT;
+
+       lsdma_data->u.pio_constfill_data.packet.fields.constant_fill = 1;
+       lsdma_data->u.pio_constfill_data.packet.fields.byte_count    = byte_count;
+       lsdma_data->u.pio_constfill_data.dst_lo                      = dst_addr & 0xFFFFFFFF;
+       lsdma_data->u.pio_constfill_data.dst_hi                      = (dst_addr >> 32) & 0xFFFFFFFF;
+       lsdma_data->u.pio_constfill_data.data                        = data;
+
+       result = dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, wait_type);
+
+       if (!result)
+               DC_ERROR("LSDMA PIO Constfill failed in DMUB");
+
+       return result;
+}
+
+bool dmub_lsdma_send_poll_reg_write_command(struct dc_dmub_srv *dc_dmub_srv, uint32_t reg_addr, uint32_t reg_data)
+{
+       struct dc_context *dc_ctx = dc_dmub_srv->ctx;
+       union dmub_rb_cmd cmd;
+       enum dm_dmub_wait_type wait_type;
+       struct dmub_cmd_lsdma_data *lsdma_data = &cmd.lsdma.lsdma_data;
+       bool result;
+
+       memset(&cmd, 0, sizeof(cmd));
+
+       cmd.cmd_common.header.type     = DMUB_CMD__LSDMA;
+       cmd.cmd_common.header.sub_type = DMUB_CMD__LSDMA_POLL_REG_WRITE;
+       wait_type                      = DM_DMUB_WAIT_TYPE_NO_WAIT;
+
+       lsdma_data->u.reg_write_data.reg_addr = reg_addr;
+       lsdma_data->u.reg_write_data.reg_data = reg_data;
+
+       result = dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, wait_type);
+
+       if (!result)
+               DC_ERROR("LSDMA Poll Reg failed in DMUB");
+
+       return result;
+}
+
index ada5c2fb2db300b13de4c2f4e3de61ceac490deb..178a71e3b7dc41120551d556c3ab8dd9e9506f6e 100644 (file)
@@ -248,4 +248,59 @@ bool dc_dmub_srv_ips_residency_cntl(struct dc_dmub_srv *dc_dmub_srv, bool start_
  * @output: Output struct to copy the the residency info to
  */
 void dc_dmub_srv_ips_query_residency_info(struct dc_dmub_srv *dc_dmub_srv, struct ips_residency_info *output);
+
+bool dmub_lsdma_init(struct dc_dmub_srv *dc_dmub_srv);
+bool dmub_lsdma_send_linear_copy_packet(
+       struct dc_dmub_srv *dc_dmub_srv,
+       uint64_t src_addr,
+       uint64_t dst_addr,
+       uint32_t count);
+bool dmub_lsdma_send_pio_copy_command(
+       struct dc_dmub_srv *dc_dmub_srv,
+       uint64_t src_addr,
+       uint64_t dst_addr,
+       uint32_t byte_count,
+       uint32_t overlap_disable);
+bool dmub_lsdma_send_pio_constfill_command(
+       struct dc_dmub_srv *dc_dmub_srv,
+       uint64_t dst_addr,
+       uint32_t byte_count,
+       uint32_t data);
+
+struct lsdma_send_tiled_to_tiled_copy_command_params {
+       uint64_t src_addr;
+       uint64_t dst_addr;
+
+       uint32_t src_x            : 16;
+       uint32_t src_y            : 16;
+
+       uint32_t dst_x            : 16;
+       uint32_t dst_y            : 16;
+
+       uint32_t src_width        : 16;
+       uint32_t dst_width        : 16;
+
+       uint32_t rect_x           : 16;
+       uint32_t rect_y           : 16;
+
+       uint32_t src_height       : 16;
+       uint32_t dst_height       : 16;
+
+       uint32_t data_format      : 6;
+       uint32_t swizzle_mode     : 5;
+       uint32_t element_size     : 3;
+       uint32_t dcc              : 1;
+       uint32_t tmz              : 1;
+       uint32_t read_compress    : 2;
+       uint32_t write_compress   : 2;
+       uint32_t max_com          : 2;
+       uint32_t max_uncom        : 1;
+       uint32_t padding          : 9;
+};
+
+bool dmub_lsdma_send_tiled_to_tiled_copy_command(
+       struct dc_dmub_srv *dc_dmub_srv,
+       struct lsdma_send_tiled_to_tiled_copy_command_params params);
+bool dmub_lsdma_send_poll_reg_write_command(struct dc_dmub_srv *dc_dmub_srv, uint32_t reg_addr, uint32_t reg_data);
+
 #endif /* _DMUB_DC_SRV_H_ */
index 479db84fcdc2e161f2f159764e2212f343ef74f0..c627093bb849c7b9a3523c330c98ed62cd8110a0 100644 (file)
@@ -131,6 +131,7 @@ enum dmub_window_id {
        DMUB_WINDOW_7_SCRATCH_MEM,
        DMUB_WINDOW_IB_MEM,
        DMUB_WINDOW_SHARED_STATE,
+       DMUB_WINDOW_LSDMA_BUFFER,
        DMUB_WINDOW_TOTAL,
 };
 
@@ -579,6 +580,7 @@ struct dmub_srv {
 
        enum dmub_srv_power_state_type power_state;
        struct dmub_diagnostic_data debug;
+       struct dmub_fb lsdma_rb_fb;
 };
 
 /**
index 5f827104b4f8f4ace0ac421d6997eda94f8a086f..b17a19400c067eede5b370252f0bcd1acf0d9a17 100644 (file)
@@ -68,6 +68,9 @@
 /* Default indirect buffer size. */
 #define DMUB_IB_MEM_SIZE (1280)
 
+/* Default LSDMA ring buffer size. */
+#define DMUB_LSDMA_RB_SIZE (64 * 1024)
+
 /* Number of windows in use. */
 #define DMUB_NUM_WINDOWS (DMUB_WINDOW_TOTAL)
 /* Base addresses. */
@@ -564,6 +567,7 @@ enum dmub_status
        window_sizes[DMUB_WINDOW_7_SCRATCH_MEM] = DMUB_SCRATCH_MEM_SIZE;
        window_sizes[DMUB_WINDOW_IB_MEM] = DMUB_IB_MEM_SIZE;
        window_sizes[DMUB_WINDOW_SHARED_STATE] = max(DMUB_FW_HEADER_SHARED_STATE_SIZE, shared_state_size);
+       window_sizes[DMUB_WINDOW_LSDMA_BUFFER] = DMUB_LSDMA_RB_SIZE;
 
        out->fb_size =
                dmub_srv_calc_regions_for_memory_type(params, out, window_sizes, DMUB_WINDOW_MEMORY_TYPE_FB);