Commit 00c9c423 authored by Ostrowski Rafal's avatar Ostrowski Rafal Committed by Alex Deucher
Browse files

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: default avatarAlvin Lee <alvin.lee2@amd.com>
Signed-off-by: default avatarOstrowski Rafal <rostrows@amd.com>
Signed-off-by: default avatarFangzhi Zuo <jerry.zuo@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 69541034
Loading
Loading
Loading
Loading
+199 −0
Original line number Diff line number Diff line
@@ -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;
}
+55 −0
Original line number Diff line number Diff line
@@ -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_ */
+2 −0
Original line number Diff line number Diff line
@@ -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;
};

/**
+4 −0
Original line number Diff line number Diff line
@@ -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);