drivers/gpu/drm/amd/display/dc/dml/dcn302/dcn302_fpu.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/dc/dml/dcn302/dcn302_fpu.c
Extension
.c
Size
14022 bytes
Lines
369
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 (max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
			/* If max DCFCLK is greater than the max DCFCLK STA target, insert into the DCFCLK STA target array */
			dcfclk_sta_targets[num_dcfclk_sta_targets] = max_dcfclk_mhz;
			num_dcfclk_sta_targets++;
		} else if (max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
			/* If max DCFCLK is less than the max DCFCLK STA target, cap values and remove duplicates */
			for (i = 0; i < num_dcfclk_sta_targets; i++) {
				if (dcfclk_sta_targets[i] > max_dcfclk_mhz) {
					dcfclk_sta_targets[i] = max_dcfclk_mhz;
					break;
				}
			}
			/* Update size of array since we "removed" duplicates */
			num_dcfclk_sta_targets = i + 1;
		}

		num_uclk_states = bw_params->clk_table.num_entries;

		/* Calculate optimal dcfclk for each uclk */
		for (i = 0; i < num_uclk_states; i++) {
			dcn302_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16,
					&optimal_dcfclk_for_uclk[i], NULL);
			if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz)
				optimal_dcfclk_for_uclk[i] = bw_params->clk_table.entries[0].dcfclk_mhz;
		}

		/* Calculate optimal uclk for each dcfclk sta target */
		for (i = 0; i < num_dcfclk_sta_targets; i++) {
			for (j = 0; j < num_uclk_states; j++) {
				if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) {
					optimal_uclk_for_dcfclk_sta_targets[i] =
							bw_params->clk_table.entries[j].memclk_mhz * 16;
					break;
				}
			}
		}

		i = 0;
		j = 0;
		/* create the final dcfclk and uclk table */
		while (i < num_dcfclk_sta_targets && j < num_uclk_states && num_states < DC__VOLTAGE_STATES) {
			if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) {
				dcfclk_mhz[num_states] = dcfclk_sta_targets[i];
				dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];
			} else {
				if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) {
					dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];
					dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;
				} else {
					j = num_uclk_states;
				}
			}
		}

		while (i < num_dcfclk_sta_targets && num_states < DC__VOLTAGE_STATES) {
			dcfclk_mhz[num_states] = dcfclk_sta_targets[i];
			dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];
		}

		while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES &&
				optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) {
			dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];
			dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;
		}

		/* bw_params->clk_table.entries[MAX_NUM_DPM_LVL].
		 * MAX_NUM_DPM_LVL is 8.
		 * dcn3_02_soc.clock_limits[DC__VOLTAGE_STATES].
		 * DC__VOLTAGE_STATES is 40.
		 */
		if (num_states > MAX_NUM_DPM_LVL) {
			ASSERT(0);
			return;
		}

		dcn3_02_soc.num_states = num_states;
		for (i = 0; i < dcn3_02_soc.num_states; i++) {
			dcn3_02_soc.clock_limits[i].state = i;
			dcn3_02_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i];
			dcn3_02_soc.clock_limits[i].fabricclk_mhz = dcfclk_mhz[i];
			dcn3_02_soc.clock_limits[i].dram_speed_mts = dram_speed_mts[i];

			/* Fill all states with max values of all other clocks */
			dcn3_02_soc.clock_limits[i].dispclk_mhz = max_dispclk_mhz;
			dcn3_02_soc.clock_limits[i].dppclk_mhz  = max_dppclk_mhz;
			dcn3_02_soc.clock_limits[i].phyclk_mhz  = max_phyclk_mhz;
			/* Populate from bw_params for DTBCLK, SOCCLK */
			if (!bw_params->clk_table.entries[i].dtbclk_mhz && i > 0)
				dcn3_02_soc.clock_limits[i].dtbclk_mhz  = dcn3_02_soc.clock_limits[i-1].dtbclk_mhz;
			else

Annotation

Implementation Notes