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

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

File Facts

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

#include "../dmub_srv.h"
#include "dmub_reg.h"
#include "dmub_dcn20.h"

#include "dcn/dcn_2_0_0_offset.h"
#include "dcn/dcn_2_0_0_sh_mask.h"
#include "soc15_hw_ip.h"
#include "vega10_ip_offset.h"

#define BASE_INNER(seg) DCN_BASE__INST0_SEG##seg
#define CTX dmub
#define REGS dmub->regs

/* Registers. */

const struct dmub_srv_common_regs dmub_srv_dcn20_regs = {
#define DMUB_SR(reg) REG_OFFSET(reg),
	{
		DMUB_COMMON_REGS()
		DMCUB_INTERNAL_REGS()
	},
#undef DMUB_SR

#define DMUB_SF(reg, field) FD_MASK(reg, field),
	{ DMUB_COMMON_FIELDS() },
#undef DMUB_SF

#define DMUB_SF(reg, field) FD_SHIFT(reg, field),
	{ DMUB_COMMON_FIELDS() },
#undef DMUB_SF
};

/* Shared functions. */

static void dmub_dcn20_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_dcn20_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;
}

bool dmub_dcn20_use_cached_inbox(struct dmub_srv *dmub)
{
	/* Cached inbox is not supported in this fw version range */
	return !(dmub->fw_version >= DMUB_FW_VERSION(1, 0, 0) &&
		 dmub->fw_version <= DMUB_FW_VERSION(1, 10, 0));
}

void dmub_dcn20_reset(struct dmub_srv *dmub)
{
	union dmub_gpint_data_register cmd;
	const uint32_t timeout = 30;
	uint32_t in_reset, scratch, i;

	REG_GET(DMCUB_CNTL, DMCUB_SOFT_RESET, &in_reset);

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

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

		/**
		 * Timeout covers both the ACK and the wait
		 * for remaining work to finish.
		 *
		 * This is mostly bound by the PHY disable sequence.
		 * Each register check will be greater than 1us, so
		 * don't bother using udelay.

Annotation

Implementation Notes