drivers/gpu/drm/amd/display/dc/dc_helper.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dc/dc_helper.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/dc/dc_helper.c
Extension
.c
Size
22503 bytes
Lines
768
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct dc_reg_value_masks {
	uint32_t value;
	uint32_t mask;
};

static inline void set_reg_field_value_masks(
	struct dc_reg_value_masks *field_value_mask,
	uint32_t value,
	uint32_t mask,
	uint8_t shift)
{
	ASSERT(mask != 0);

	field_value_mask->value = (field_value_mask->value & ~mask) | (mask & (value << shift));
	field_value_mask->mask = field_value_mask->mask | mask;
}

static void set_reg_field_values(struct dc_reg_value_masks *field_value_mask,
		uint32_t addr, int n,
		uint8_t shift1, uint32_t mask1, uint32_t field_value1,
		va_list ap)
{
	(void)addr;
	uint32_t shift, mask, field_value;
	int i = 1;

	/* gather all bits value/mask getting updated in this register */
	set_reg_field_value_masks(field_value_mask,
			field_value1, mask1, shift1);

	while (i < n) {
		shift = va_arg(ap, uint32_t);
		mask = va_arg(ap, uint32_t);
		field_value = va_arg(ap, uint32_t);

		set_reg_field_value_masks(field_value_mask,
				field_value, mask, (uint8_t)shift);
		i++;
	}
}

static void dmub_flush_buffer_execute(
		struct dc_reg_helper_state *offload,
		const struct dc_context *ctx)
{
	submit_dmub_read_modify_write(offload, ctx);
}

static void dmub_flush_burst_write_buffer_execute(
		struct dc_reg_helper_state *offload,
		const struct dc_context *ctx)
{
	submit_dmub_burst_write(offload, ctx);
}

static bool dmub_reg_value_burst_set_pack(const struct dc_context *ctx, uint32_t addr,
		uint32_t reg_val)
{
	struct dc_reg_helper_state *offload = &ctx->dmub_srv->reg_helper_offload;
	struct dmub_rb_cmd_burst_write *cmd_buf = &offload->cmd_data.burst_write;

	/* flush command if buffer is full */
	if (offload->reg_seq_count == DMUB_BURST_WRITE_VALUES__MAX)
		dmub_flush_burst_write_buffer_execute(offload, ctx);

	if (offload->cmd_data.cmd_common.header.type == DMUB_CMD__REG_SEQ_BURST_WRITE &&
			addr != cmd_buf->addr) {
		dmub_flush_burst_write_buffer_execute(offload, ctx);
		return false;
	}

	cmd_buf->header.type = DMUB_CMD__REG_SEQ_BURST_WRITE;
	cmd_buf->header.sub_type = 0;
	cmd_buf->addr = addr;
	cmd_buf->write_values[offload->reg_seq_count] = reg_val;
	offload->reg_seq_count++;

	return true;
}

static uint32_t dmub_reg_value_pack(const struct dc_context *ctx, uint32_t addr,
		struct dc_reg_value_masks *field_value_mask)
{
	struct dc_reg_helper_state *offload = &ctx->dmub_srv->reg_helper_offload;
	struct dmub_rb_cmd_read_modify_write *cmd_buf = &offload->cmd_data.read_modify_write;
	struct dmub_cmd_read_modify_write_sequence *seq;

	/* flush command if buffer is full */
	if (offload->cmd_data.cmd_common.header.type != DMUB_CMD__REG_SEQ_BURST_WRITE &&
			offload->reg_seq_count == DMUB_READ_MODIFY_WRITE_SEQ__MAX)

Annotation

Implementation Notes