drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c
Extension
.c
Size
47573 bytes
Lines
1656
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 (low > 2 || high > 2) {
			pr_info("Currently sclk only support 3 levels on RV\n");
			return -EINVAL;
		}

		smum_send_msg_to_smc_with_parameter(hwmgr,
						PPSMC_MSG_SetHardMinGfxClk,
						low == 2 ? data->gfx_max_freq_limit/100 :
						low == 1 ? SMU10_UMD_PSTATE_GFXCLK :
						data->gfx_min_freq_limit/100,
						NULL);

		smum_send_msg_to_smc_with_parameter(hwmgr,
						PPSMC_MSG_SetSoftMaxGfxClk,
						high == 0 ? data->gfx_min_freq_limit/100 :
						high == 1 ? SMU10_UMD_PSTATE_GFXCLK :
						data->gfx_max_freq_limit/100,
						NULL);
		break;

	case PP_MCLK:
		if (low > mclk_table->count - 1 || high > mclk_table->count - 1)
			return -EINVAL;

		smum_send_msg_to_smc_with_parameter(hwmgr,
						PPSMC_MSG_SetHardMinFclkByFreq,
						mclk_table->entries[low].clk/100,
						NULL);

		smum_send_msg_to_smc_with_parameter(hwmgr,
						PPSMC_MSG_SetSoftMaxFclkByFreq,
						mclk_table->entries[high].clk/100,
						NULL);
		break;

	case PP_PCIE:
	default:
		break;
	}
	return 0;
}

static int smu10_emit_clock_levels(struct pp_hwmgr *hwmgr,
				   enum pp_clock_type type, char *buf,
				   int *offset)
{
	struct smu10_hwmgr *data = (struct smu10_hwmgr *)(hwmgr->backend);
	struct smu10_voltage_dependency_table *mclk_table =
			data->clock_vol_info.vdd_dep_on_fclk;
	uint32_t i, now, size = *offset;
	uint32_t min_freq, max_freq = 0;
	int ret = 0;

	switch (type) {
	case PP_SCLK:
		ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency, &now);
		if (ret)
			return ret;

	/* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */
		if (now == data->gfx_max_freq_limit/100)
			i = 2;
		else if (now == data->gfx_min_freq_limit/100)
			i = 0;
		else
			i = 1;

		size += sysfs_emit_at(buf, size, "0: %uMhz %s\n",
				      data->gfx_min_freq_limit / 100,
				      i == 0 ? "*" : "");
		size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
				      i == 1 ? now : SMU10_UMD_PSTATE_GFXCLK,
				      i == 1 ? "*" : "");
		size += sysfs_emit_at(buf, size, "2: %uMhz %s\n",
				      data->gfx_max_freq_limit / 100,
				      i == 2 ? "*" : "");
		break;
	case PP_MCLK:
		ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency, &now);
		if (ret)
			return ret;

		for (i = 0; i < mclk_table->count; i++)
			size += sysfs_emit_at(
				buf, size, "%d: %uMhz %s\n", i,
				mclk_table->entries[i].clk / 100,
				((mclk_table->entries[i].clk / 100) == now) ?
					"*" :
					"");
		break;

Annotation

Implementation Notes