drm/amd/display: LSDMA support

[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>
This commit is contained in:
Ostrowski Rafal 2025-06-12 09:08:51 +02:00 committed by Alex Deucher
parent 6954103400
commit 00c9c4236d
4 changed files with 260 additions and 0 deletions

View 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;
}

View 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_ */

View 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;
};
/**

View 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);