amdgpu/pm: Implement emit_clk_levels for vega10
authorDarren Powell <darren.powell@amd.com>
Tue, 8 Mar 2022 02:40:35 +0000 (21:40 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 28 Mar 2022 16:54:32 +0000 (12:54 -0400)
   (v1)
     - implement emit_clk_levels for vega10, based on print_clk_levels,
       but using sysfs_emit rather than sprintf
     - modify local int vars to use uint32_t to match arg type of
       called functions
     - add return of error codes
     - refactor OD_XXX cases to return early with -EOPNOTSUPP if
       !(hwmgr->od_enabled)

Signed-off-by: Darren Powell <darren.powell@amd.com>
Reviewed-by: Evan Quan <evan.quan@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c

index 37324f2..99bfe5e 100644 (file)
@@ -4625,6 +4625,152 @@ static int vega10_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr)
                >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
 }
 
+static int vega10_emit_clock_levels(struct pp_hwmgr *hwmgr,
+                                   enum pp_clock_type type, char *buf, int *offset)
+{
+       struct vega10_hwmgr *data = hwmgr->backend;
+       struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
+       struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
+       struct vega10_single_dpm_table *soc_table = &(data->dpm_table.soc_table);
+       struct vega10_single_dpm_table *dcef_table = &(data->dpm_table.dcef_table);
+       struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep = NULL;
+       uint32_t gen_speed, lane_width, current_gen_speed, current_lane_width;
+       PPTable_t *pptable = &(data->smc_state_table.pp_table);
+
+       uint32_t i, now, count = 0;
+       int ret = 0;
+
+       switch (type) {
+       case PP_SCLK:
+               if (data->registry_data.sclk_dpm_key_disabled)
+                       return -EOPNOTSUPP;
+
+               ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex, &now);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               if (hwmgr->pp_one_vf &&
+                   (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK))
+                       count = 5;
+               else
+                       count = sclk_table->count;
+               for (i = 0; i < count; i++)
+                       *offset += sysfs_emit_at(buf, *offset, "%d: %uMhz %s\n",
+                                       i, sclk_table->dpm_levels[i].value / 100,
+                                       (i == now) ? "*" : "");
+               break;
+       case PP_MCLK:
+               if (data->registry_data.mclk_dpm_key_disabled)
+                       return -EOPNOTSUPP;
+
+               ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &now);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               for (i = 0; i < mclk_table->count; i++)
+                       *offset += sysfs_emit_at(buf, *offset, "%d: %uMhz %s\n",
+                                       i, mclk_table->dpm_levels[i].value / 100,
+                                       (i == now) ? "*" : "");
+               break;
+       case PP_SOCCLK:
+               if (data->registry_data.socclk_dpm_key_disabled)
+                       return -EOPNOTSUPP;
+
+               ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex, &now);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               for (i = 0; i < soc_table->count; i++)
+                       *offset += sysfs_emit_at(buf, *offset, "%d: %uMhz %s\n",
+                                       i, soc_table->dpm_levels[i].value / 100,
+                                       (i == now) ? "*" : "");
+               break;
+       case PP_DCEFCLK:
+               if (data->registry_data.dcefclk_dpm_key_disabled)
+                       return -EOPNOTSUPP;
+
+               ret = smum_send_msg_to_smc_with_parameter(hwmgr,
+                                                         PPSMC_MSG_GetClockFreqMHz,
+                                                         CLK_DCEFCLK, &now);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               for (i = 0; i < dcef_table->count; i++)
+                       *offset += sysfs_emit_at(buf, *offset, "%d: %uMhz %s\n",
+                                       i, dcef_table->dpm_levels[i].value / 100,
+                                       (dcef_table->dpm_levels[i].value / 100 == now) ?
+                                       "*" : "");
+               break;
+       case PP_PCIE:
+               current_gen_speed =
+                       vega10_get_current_pcie_link_speed_level(hwmgr);
+               current_lane_width =
+                       vega10_get_current_pcie_link_width_level(hwmgr);
+               for (i = 0; i < NUM_LINK_LEVELS; i++) {
+                       gen_speed = pptable->PcieGenSpeed[i];
+                       lane_width = pptable->PcieLaneCount[i];
+
+                       *offset += sysfs_emit_at(buf, *offset, "%d: %s %s %s\n", i,
+                                       (gen_speed == 0) ? "2.5GT/s," :
+                                       (gen_speed == 1) ? "5.0GT/s," :
+                                       (gen_speed == 2) ? "8.0GT/s," :
+                                       (gen_speed == 3) ? "16.0GT/s," : "",
+                                       (lane_width == 1) ? "x1" :
+                                       (lane_width == 2) ? "x2" :
+                                       (lane_width == 3) ? "x4" :
+                                       (lane_width == 4) ? "x8" :
+                                       (lane_width == 5) ? "x12" :
+                                       (lane_width == 6) ? "x16" : "",
+                                       (current_gen_speed == gen_speed) &&
+                                       (current_lane_width == lane_width) ?
+                                       "*" : "");
+               }
+               break;
+
+       case OD_SCLK:
+               if (!hwmgr->od_enabled)
+                       return -EOPNOTSUPP;
+
+               *offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_SCLK");
+               podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk;
+               for (i = 0; i < podn_vdd_dep->count; i++)
+                       *offset += sysfs_emit_at(buf, *offset, "%d: %10uMhz %10umV\n",
+                                                i, podn_vdd_dep->entries[i].clk / 100,
+                                                podn_vdd_dep->entries[i].vddc);
+               break;
+       case OD_MCLK:
+               if (!hwmgr->od_enabled)
+                       return -EOPNOTSUPP;
+
+               *offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_MCLK");
+               podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk;
+               for (i = 0; i < podn_vdd_dep->count; i++)
+                       *offset += sysfs_emit_at(buf, *offset, "%d: %10uMhz %10umV\n",
+                                                i, podn_vdd_dep->entries[i].clk/100,
+                                                podn_vdd_dep->entries[i].vddc);
+               break;
+       case OD_RANGE:
+               if (!hwmgr->od_enabled)
+                       return -EOPNOTSUPP;
+
+               *offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_RANGE");
+               *offset += sysfs_emit_at(buf, *offset, "SCLK: %7uMHz %10uMHz\n",
+                                        data->golden_dpm_table.gfx_table.dpm_levels[0].value/100,
+                               hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
+               *offset += sysfs_emit_at(buf, *offset, "MCLK: %7uMHz %10uMHz\n",
+                                        data->golden_dpm_table.mem_table.dpm_levels[0].value/100,
+                               hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
+               *offset += sysfs_emit_at(buf, *offset, "VDDC: %7umV %11umV\n",
+                                        data->odn_dpm_table.min_vddc,
+                                        data->odn_dpm_table.max_vddc);
+               break;
+       default:
+               ret = -ENOENT;
+               break;
+       }
+       return ret;
+}
+
 static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
                enum pp_clock_type type, char *buf)
 {
@@ -5559,6 +5705,7 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .set_watermarks_for_clocks_ranges = vega10_set_watermarks_for_clocks_ranges,
        .display_clock_voltage_request = vega10_display_clock_voltage_request,
        .force_clock_level = vega10_force_clock_level,
+       .emit_clock_levels = vega10_emit_clock_levels,
        .print_clock_levels = vega10_print_clock_levels,
        .display_config_changed = vega10_display_configuration_changed_task,
        .powergate_uvd = vega10_power_gate_uvd,