drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
Extension
.c
Size
15772 bytes
Lines
463
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

if (enable) {
				if (state != REPLAY_STATE_0)
					break;
			} else {
				if (state == REPLAY_STATE_0)
					break;
			}

			/* must *not* be fsleep - this can be called from high irq levels */
			udelay(500);
		}

		/* assert if max retry hit */
		if (retry_count >= 1000)
			ASSERT(0);
	}
}

/*
 * Set REPLAY power optimization flags.
 */
static void dmub_replay_set_power_opt(struct dmub_replay *dmub, unsigned int power_opt, uint8_t panel_inst)
{
	union dmub_rb_cmd cmd;
	struct dc_context *dc = dmub->ctx;

	memset(&cmd, 0, sizeof(cmd));
	cmd.replay_set_power_opt.header.type = DMUB_CMD__REPLAY;
	cmd.replay_set_power_opt.header.sub_type = DMUB_CMD__SET_REPLAY_POWER_OPT;
	cmd.replay_set_power_opt.header.payload_bytes = sizeof(struct dmub_cmd_replay_set_power_opt_data);
	cmd.replay_set_power_opt.replay_set_power_opt_data.power_opt = power_opt;
	cmd.replay_set_power_opt.replay_set_power_opt_data.panel_inst = panel_inst;

	dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}

/*
 * Setup Replay by programming phy registers and sending replay hw context values to firmware.
 */
static bool dmub_replay_copy_settings(struct dmub_replay *dmub,
	struct dc_link *link,
	struct replay_context *replay_context,
	uint8_t panel_inst)
{
	union dmub_rb_cmd cmd;
	struct dc_context *dc = dmub->ctx;
	struct dmub_cmd_replay_copy_settings_data *copy_settings_data
		= &cmd.replay_copy_settings.replay_copy_settings_data;
	struct pipe_ctx *pipe_ctx = NULL;
	struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx;
	int i = 0;

	for (i = 0; i < MAX_PIPES; i++) {
		if (res_ctx &&
			res_ctx->pipe_ctx[i].stream &&
			res_ctx->pipe_ctx[i].stream->link &&
			res_ctx->pipe_ctx[i].stream->link == link &&
			res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) {
			pipe_ctx = &res_ctx->pipe_ctx[i];
			//TODO: refactor for multi edp support
			break;
		}
	}

	if (!pipe_ctx)
		return false;

	memset(&cmd, 0, sizeof(cmd));
	cmd.replay_copy_settings.header.type = DMUB_CMD__REPLAY;
	cmd.replay_copy_settings.header.sub_type = DMUB_CMD__REPLAY_COPY_SETTINGS;
	cmd.replay_copy_settings.header.payload_bytes = sizeof(struct dmub_cmd_replay_copy_settings_data);

	// HW insts
	copy_settings_data->aux_inst				= replay_context->aux_inst;
	copy_settings_data->digbe_inst				= replay_context->digbe_inst;
	copy_settings_data->digfe_inst				= replay_context->digfe_inst;

	if (pipe_ctx->plane_res.dpp)
		copy_settings_data->dpp_inst			= (uint8_t)pipe_ctx->plane_res.dpp->inst;
	else
		copy_settings_data->dpp_inst			= 0;

	if (pipe_ctx->stream_res.tg)
		copy_settings_data->otg_inst			= (uint8_t)pipe_ctx->stream_res.tg->inst;
	else
		copy_settings_data->otg_inst			= 0;

	copy_settings_data->dpphy_inst				= link->link_enc->transmitter;

	// Misc

Annotation

Implementation Notes