drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
Extension
.c
Size
20129 bytes
Lines
621
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

void dmub_srv_dcn35_regs_init(struct dmub_srv *dmub, struct dc_context *ctx) {
	struct dmub_srv_dcn35_regs *regs = dmub->regs_dcn35;
#define REG_STRUCT regs

#define DMUB_SR(reg) REG_STRUCT->offset.reg = REG_OFFSET_EXP(reg);
	DMUB_DCN35_REGS()
	DMCUB_INTERNAL_REGS()
#undef DMUB_SR

#define DMUB_SF(reg, field) REG_STRUCT->mask.reg##__##field = FD_MASK(reg, field);
	DMUB_DCN35_FIELDS()
#undef DMUB_SF

#define DMUB_SF(reg, field) REG_STRUCT->shift.reg##__##field = FD_SHIFT(reg, field);
	DMUB_DCN35_FIELDS()
#undef DMUB_SF
#undef REG_STRUCT
}

static void dmub_dcn35_get_fb_base_offset(struct dmub_srv *dmub,
					  uint64_t *fb_base,
					  uint64_t *fb_offset)
{
	uint32_t tmp;

	/*
	if (dmub->soc_fb_info.fb_base || dmub->soc_fb_info.fb_offset) {
		*fb_base = dmub->soc_fb_info.fb_base;
		*fb_offset = dmub->soc_fb_info.fb_offset;
		return;
	}
	*/

	REG_GET(DCN_VM_FB_LOCATION_BASE, FB_BASE, &tmp);
	*fb_base = (uint64_t)tmp << 24;

	REG_GET(DCN_VM_FB_OFFSET, FB_OFFSET, &tmp);
	*fb_offset = (uint64_t)tmp << 24;
}

static inline void dmub_dcn35_translate_addr(const union dmub_addr *addr_in,
					     uint64_t fb_base,
					     uint64_t fb_offset,
					     union dmub_addr *addr_out)
{
	addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset;
}

void dmub_dcn35_reset(struct dmub_srv *dmub)
{
	union dmub_gpint_data_register cmd;
	const uint32_t timeout = 100000;
	uint32_t in_reset, is_enabled, scratch, i, pwait_mode;

	REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset);
	REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled);

	if (in_reset == 0 && is_enabled != 0) {
		cmd.bits.status = 1;
		cmd.bits.command_code = DMUB_GPINT__STOP_FW;
		cmd.bits.param = 0;

		dmub->hw_funcs.set_gpint(dmub, cmd);

		for (i = 0; i < timeout; ++i) {
			if (dmub->hw_funcs.is_gpint_acked(dmub, cmd))
				break;

			udelay(1);
		}

		for (i = 0; i < timeout; ++i) {
			scratch = REG_READ(DMCUB_SCRATCH7);
			if (scratch == DMUB_GPINT__STOP_FW_RESPONSE)
				break;

			udelay(1);
		}

		for (i = 0; i < timeout; ++i) {
			REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &pwait_mode);
			if (pwait_mode & (1 << 0))
				break;

			udelay(1);
		}
		/* Force reset in case we timed out, DMCUB is likely hung. */
	}

	if (is_enabled) {

Annotation

Implementation Notes