drm/amd/pm: add callbacks to read/write sysfs file pp_power_profile_mode
authorXiaomeng Hou <Xiaomeng.Hou@amd.com>
Mon, 29 Mar 2021 13:27:49 +0000 (21:27 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 4 Jun 2021 20:03:23 +0000 (16:03 -0400)
Implement the sysfs API for getting/setting pp_power_profile_mode for
yellow carp.

Signed-off-by: Xiaomeng Hou <Xiaomeng.Hou@amd.com>
Reviewed-by: Huang Rui <ray.huang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c

index 080dd76..db12524 100644 (file)
@@ -135,6 +135,14 @@ static struct cmn2asic_mapping yellow_carp_table_map[SMU_TABLE_COUNT] = {
        TAB_MAP_VALID(CUSTOM_DPM),
        TAB_MAP_VALID(DPMCLOCKS),
 };
+
+static struct cmn2asic_mapping yellow_carp_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
+       WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,         WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
+       WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,                WORKLOAD_PPLIB_VIDEO_BIT),
+       WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,                   WORKLOAD_PPLIB_VR_BIT),
+       WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,              WORKLOAD_PPLIB_COMPUTE_BIT),
+       WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,               WORKLOAD_PPLIB_CUSTOM_BIT),
+};
        
 static int yellow_carp_init_smc_tables(struct smu_context *smu)
 {
@@ -463,6 +471,81 @@ static int yellow_carp_set_watermarks_table(struct smu_context *smu,
        return 0;
 }
 
+static int yellow_carp_get_power_profile_mode(struct smu_context *smu,
+                                               char *buf)
+{
+       static const char *profile_name[] = {
+                                       "BOOTUP_DEFAULT",
+                                       "3D_FULL_SCREEN",
+                                       "POWER_SAVING",
+                                       "VIDEO",
+                                       "VR",
+                                       "COMPUTE",
+                                       "CUSTOM"};
+       uint32_t i, size = 0;
+       int16_t workload_type = 0;
+
+       if (!buf)
+               return -EINVAL;
+
+       for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
+               /*
+                * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT.
+                * Not all profile modes are supported on yellow carp.
+                */
+               workload_type = smu_cmn_to_asic_specific_index(smu,
+                                                              CMN2ASIC_MAPPING_WORKLOAD,
+                                                              i);
+
+               if (workload_type < 0)
+                       continue;
+
+               size += sprintf(buf + size, "%2d %14s%s\n",
+                       i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
+       }
+
+       return size;
+}
+
+static int yellow_carp_set_power_profile_mode(struct smu_context *smu,
+                                               long *input, uint32_t size)
+{
+       int workload_type, ret;
+       uint32_t profile_mode = input[size];
+
+       if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
+               dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
+               return -EINVAL;
+       }
+
+       if (profile_mode == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT ||
+                       profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING)
+               return 0;
+
+       /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
+       workload_type = smu_cmn_to_asic_specific_index(smu,
+                                                      CMN2ASIC_MAPPING_WORKLOAD,
+                                                      profile_mode);
+       if (workload_type < 0) {
+               dev_dbg(smu->adev->dev, "Unsupported power profile mode %d on YELLOWCARP\n",
+                                       profile_mode);
+               return -EINVAL;
+       }
+
+       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
+                                   1 << workload_type,
+                                   NULL);
+       if (ret) {
+               dev_err_once(smu->adev->dev, "Fail to set workload type %d\n",
+                                       workload_type);
+               return ret;
+       }
+
+       smu->power_profile_mode = profile_mode;
+
+       return 0;
+}
+
 static int yellow_carp_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
                                        long input[], uint32_t size)
 {
@@ -940,6 +1023,8 @@ static const struct pptable_funcs yellow_carp_ppt_funcs = {
        .read_sensor = yellow_carp_read_sensor,
        .is_dpm_running = yellow_carp_is_dpm_running,
        .set_watermarks_table = yellow_carp_set_watermarks_table,
+       .get_power_profile_mode = yellow_carp_get_power_profile_mode,
+       .set_power_profile_mode = yellow_carp_set_power_profile_mode,
        .get_enabled_mask = smu_cmn_get_enabled_32_bits_mask,
        .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
        .set_driver_table_location = smu_v13_0_1_set_driver_table_location,
@@ -958,5 +1043,6 @@ void yellow_carp_set_ppt_funcs(struct smu_context *smu)
        smu->message_map = yellow_carp_message_map;
        smu->feature_map = yellow_carp_feature_mask_map;
        smu->table_map = yellow_carp_table_map;
+       smu->workload_map = yellow_carp_workload_map;
        smu->is_apu = true;
 }