drivers/gpu/drm/amd/display/dc/dml/dcn303/dcn303_fpu.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/dc/dml/dcn303/dcn303_fpu.c
Extension
.c
Size
14670 bytes
Lines
382
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]) {
			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]) {
			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++) {
			dcn303_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;
				} else {
					/* condition where (dcfclk_sta_targets[i] >= optimal_dcfclk_for_uclk[j]):
					 * This is required for dcn303 because it just so happens that the memory
					 * bandwidth is low enough such that all the optimal DCFCLK for each UCLK
					 * is lower than the smallest DCFCLK STA target. In this case we need to
					 * populate the optimal UCLK for each DCFCLK STA target to be the max UCLK.
					 */
					if (j == num_uclk_states - 1) {
						optimal_uclk_for_dcfclk_sta_targets[i] =
								bw_params->clk_table.entries[j].memclk_mhz * 16;
					}
				}
			}
		}

		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_03_soc.num_states = num_states;
		for (i = 0; i < dcn3_03_soc.num_states; i++) {
			dcn3_03_soc.clock_limits[i].state = i;
			dcn3_03_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i];
			dcn3_03_soc.clock_limits[i].fabricclk_mhz = dcfclk_mhz[i];

Annotation

Implementation Notes