diff options
author | Tom St Denis <tom.stdenis@amd.com> | 2016-09-15 10:07:34 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-09-19 14:38:26 -0400 |
commit | a6e3695221446cf825d12db9c6ad3502c45fb9de (patch) | |
tree | 8bb5b1275bd20498c5642c4445cee93e20e56cc6 /drivers/gpu/drm/amd | |
parent | 167ac5733c70683c4886a8b3ef347cc6c93a76a6 (diff) |
drm/amd/powerplay: Add read_sensor() callback to hwmgr (v3)
Provides standardized interface to read various sensors.
The API is extensible (by adding to the end of the
amd_pp_sensors enumeration list.
Support has been added to Carrizo/smu7
(v2) Squashed the two sensor patches into one.
(v3) Updated to apply to smu7_hwmgr instead
Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd')
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | 96 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 1 |
5 files changed, 165 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index b1d19409bf86..ee0368381e82 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c | |||
@@ -894,6 +894,25 @@ static int pp_dpm_set_mclk_od(void *handle, uint32_t value) | |||
894 | return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value); | 894 | return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value); |
895 | } | 895 | } |
896 | 896 | ||
897 | static int pp_dpm_read_sensor(void *handle, int idx, int32_t *value) | ||
898 | { | ||
899 | struct pp_hwmgr *hwmgr; | ||
900 | |||
901 | if (!handle) | ||
902 | return -EINVAL; | ||
903 | |||
904 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | ||
905 | |||
906 | PP_CHECK_HW(hwmgr); | ||
907 | |||
908 | if (hwmgr->hwmgr_func->read_sensor == NULL) { | ||
909 | printk(KERN_INFO "%s was not implemented.\n", __func__); | ||
910 | return 0; | ||
911 | } | ||
912 | |||
913 | return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value); | ||
914 | } | ||
915 | |||
897 | const struct amd_powerplay_funcs pp_dpm_funcs = { | 916 | const struct amd_powerplay_funcs pp_dpm_funcs = { |
898 | .get_temperature = pp_dpm_get_temperature, | 917 | .get_temperature = pp_dpm_get_temperature, |
899 | .load_firmware = pp_dpm_load_fw, | 918 | .load_firmware = pp_dpm_load_fw, |
@@ -920,6 +939,7 @@ const struct amd_powerplay_funcs pp_dpm_funcs = { | |||
920 | .set_sclk_od = pp_dpm_set_sclk_od, | 939 | .set_sclk_od = pp_dpm_set_sclk_od, |
921 | .get_mclk_od = pp_dpm_get_mclk_od, | 940 | .get_mclk_od = pp_dpm_get_mclk_od, |
922 | .set_mclk_od = pp_dpm_set_mclk_od, | 941 | .set_mclk_od = pp_dpm_set_mclk_od, |
942 | .read_sensor = pp_dpm_read_sensor, | ||
923 | }; | 943 | }; |
924 | 944 | ||
925 | static int amd_pp_instance_init(struct amd_pp_init *pp_init, | 945 | static int amd_pp_instance_init(struct amd_pp_init *pp_init, |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index 5ecef1732e20..9f3c5a8a903c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | |||
@@ -1857,6 +1857,101 @@ static int cz_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_c | |||
1857 | return 0; | 1857 | return 0; |
1858 | } | 1858 | } |
1859 | 1859 | ||
1860 | static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) | ||
1861 | { | ||
1862 | struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); | ||
1863 | |||
1864 | struct phm_clock_voltage_dependency_table *table = | ||
1865 | hwmgr->dyn_state.vddc_dependency_on_sclk; | ||
1866 | |||
1867 | struct phm_vce_clock_voltage_dependency_table *vce_table = | ||
1868 | hwmgr->dyn_state.vce_clock_voltage_dependency_table; | ||
1869 | |||
1870 | struct phm_uvd_clock_voltage_dependency_table *uvd_table = | ||
1871 | hwmgr->dyn_state.uvd_clock_voltage_dependency_table; | ||
1872 | |||
1873 | uint32_t sclk_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX), | ||
1874 | TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX); | ||
1875 | uint32_t uvd_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), | ||
1876 | TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX); | ||
1877 | uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), | ||
1878 | TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX); | ||
1879 | |||
1880 | uint32_t sclk, vclk, dclk, ecclk, tmp, activity_percent; | ||
1881 | uint16_t vddnb, vddgfx; | ||
1882 | int result; | ||
1883 | |||
1884 | switch (idx) { | ||
1885 | case AMDGPU_PP_SENSOR_GFX_SCLK: | ||
1886 | if (sclk_index < NUM_SCLK_LEVELS) { | ||
1887 | sclk = table->entries[sclk_index].clk; | ||
1888 | *value = sclk; | ||
1889 | return 0; | ||
1890 | } | ||
1891 | return -EINVAL; | ||
1892 | case AMDGPU_PP_SENSOR_VDDNB: | ||
1893 | tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) & | ||
1894 | CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; | ||
1895 | vddnb = cz_convert_8Bit_index_to_voltage(hwmgr, tmp); | ||
1896 | *value = vddnb; | ||
1897 | return 0; | ||
1898 | case AMDGPU_PP_SENSOR_VDDGFX: | ||
1899 | tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) & | ||
1900 | CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; | ||
1901 | vddgfx = cz_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp); | ||
1902 | *value = vddgfx; | ||
1903 | return 0; | ||
1904 | case AMDGPU_PP_SENSOR_UVD_VCLK: | ||
1905 | if (!cz_hwmgr->uvd_power_gated) { | ||
1906 | if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) { | ||
1907 | return -EINVAL; | ||
1908 | } else { | ||
1909 | vclk = uvd_table->entries[uvd_index].vclk; | ||
1910 | *value = vclk; | ||
1911 | return 0; | ||
1912 | } | ||
1913 | } | ||
1914 | *value = 0; | ||
1915 | return 0; | ||
1916 | case AMDGPU_PP_SENSOR_UVD_DCLK: | ||
1917 | if (!cz_hwmgr->uvd_power_gated) { | ||
1918 | if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) { | ||
1919 | return -EINVAL; | ||
1920 | } else { | ||
1921 | dclk = uvd_table->entries[uvd_index].dclk; | ||
1922 | *value = dclk; | ||
1923 | return 0; | ||
1924 | } | ||
1925 | } | ||
1926 | *value = 0; | ||
1927 | return 0; | ||
1928 | case AMDGPU_PP_SENSOR_VCE_ECCLK: | ||
1929 | if (!cz_hwmgr->vce_power_gated) { | ||
1930 | if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) { | ||
1931 | return -EINVAL; | ||
1932 | } else { | ||
1933 | ecclk = vce_table->entries[vce_index].ecclk; | ||
1934 | *value = ecclk; | ||
1935 | return 0; | ||
1936 | } | ||
1937 | } | ||
1938 | *value = 0; | ||
1939 | return 0; | ||
1940 | case AMDGPU_PP_SENSOR_GPU_LOAD: | ||
1941 | result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetAverageGraphicsActivity); | ||
1942 | if (0 == result) { | ||
1943 | activity_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0); | ||
1944 | activity_percent = activity_percent > 100 ? 100 : activity_percent; | ||
1945 | } else { | ||
1946 | activity_percent = 50; | ||
1947 | } | ||
1948 | *value = activity_percent; | ||
1949 | return 0; | ||
1950 | default: | ||
1951 | return -EINVAL; | ||
1952 | } | ||
1953 | } | ||
1954 | |||
1860 | static const struct pp_hwmgr_func cz_hwmgr_funcs = { | 1955 | static const struct pp_hwmgr_func cz_hwmgr_funcs = { |
1861 | .backend_init = cz_hwmgr_backend_init, | 1956 | .backend_init = cz_hwmgr_backend_init, |
1862 | .backend_fini = cz_hwmgr_backend_fini, | 1957 | .backend_fini = cz_hwmgr_backend_fini, |
@@ -1882,6 +1977,7 @@ static const struct pp_hwmgr_func cz_hwmgr_funcs = { | |||
1882 | .get_current_shallow_sleep_clocks = cz_get_current_shallow_sleep_clocks, | 1977 | .get_current_shallow_sleep_clocks = cz_get_current_shallow_sleep_clocks, |
1883 | .get_clock_by_type = cz_get_clock_by_type, | 1978 | .get_clock_by_type = cz_get_clock_by_type, |
1884 | .get_max_high_clocks = cz_get_max_high_clocks, | 1979 | .get_max_high_clocks = cz_get_max_high_clocks, |
1980 | .read_sensor = cz_read_sensor, | ||
1885 | }; | 1981 | }; |
1886 | 1982 | ||
1887 | int cz_hwmgr_init(struct pp_hwmgr *hwmgr) | 1983 | int cz_hwmgr_init(struct pp_hwmgr *hwmgr) |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index f67e1e260b30..07a7d046d6f6 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | |||
@@ -3144,6 +3144,41 @@ smu7_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m) | |||
3144 | seq_printf(m, "vce %sabled\n", data->vce_power_gated ? "dis" : "en"); | 3144 | seq_printf(m, "vce %sabled\n", data->vce_power_gated ? "dis" : "en"); |
3145 | } | 3145 | } |
3146 | 3146 | ||
3147 | static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) | ||
3148 | { | ||
3149 | uint32_t sclk, mclk, activity_percent; | ||
3150 | uint32_t offset; | ||
3151 | struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); | ||
3152 | |||
3153 | switch (idx) { | ||
3154 | case AMDGPU_PP_SENSOR_GFX_SCLK: | ||
3155 | smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency); | ||
3156 | sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); | ||
3157 | *value = sclk; | ||
3158 | return 0; | ||
3159 | case AMDGPU_PP_SENSOR_GFX_MCLK: | ||
3160 | smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency); | ||
3161 | mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); | ||
3162 | *value = mclk; | ||
3163 | return 0; | ||
3164 | case AMDGPU_PP_SENSOR_GPU_LOAD: | ||
3165 | offset = data->soft_regs_start + smum_get_offsetof(hwmgr->smumgr, | ||
3166 | SMU_SoftRegisters, | ||
3167 | AverageGraphicsActivity); | ||
3168 | |||
3169 | activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset); | ||
3170 | activity_percent += 0x80; | ||
3171 | activity_percent >>= 8; | ||
3172 | *value = activity_percent > 100 ? 100 : activity_percent; | ||
3173 | return 0; | ||
3174 | case AMDGPU_PP_SENSOR_GPU_TEMP: | ||
3175 | *value = smu7_thermal_get_temperature(hwmgr); | ||
3176 | return 0; | ||
3177 | default: | ||
3178 | return -EINVAL; | ||
3179 | } | ||
3180 | } | ||
3181 | |||
3147 | static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) | 3182 | static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) |
3148 | { | 3183 | { |
3149 | const struct phm_set_power_state_input *states = | 3184 | const struct phm_set_power_state_input *states = |
@@ -4315,6 +4350,7 @@ static struct pp_hwmgr_func smu7_hwmgr_funcs = { | |||
4315 | .get_mclk_od = smu7_get_mclk_od, | 4350 | .get_mclk_od = smu7_get_mclk_od, |
4316 | .set_mclk_od = smu7_set_mclk_od, | 4351 | .set_mclk_od = smu7_set_mclk_od, |
4317 | .get_clock_by_type = smu7_get_clock_by_type, | 4352 | .get_clock_by_type = smu7_get_clock_by_type, |
4353 | .read_sensor = smu7_read_sensor, | ||
4318 | }; | 4354 | }; |
4319 | 4355 | ||
4320 | uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, | 4356 | uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, |
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index f941acf563a9..dfa0f38a5e76 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | |||
@@ -29,6 +29,17 @@ | |||
29 | #include "amd_shared.h" | 29 | #include "amd_shared.h" |
30 | #include "cgs_common.h" | 30 | #include "cgs_common.h" |
31 | 31 | ||
32 | enum amd_pp_sensors { | ||
33 | AMDGPU_PP_SENSOR_GFX_SCLK = 0, | ||
34 | AMDGPU_PP_SENSOR_VDDNB, | ||
35 | AMDGPU_PP_SENSOR_VDDGFX, | ||
36 | AMDGPU_PP_SENSOR_UVD_VCLK, | ||
37 | AMDGPU_PP_SENSOR_UVD_DCLK, | ||
38 | AMDGPU_PP_SENSOR_VCE_ECCLK, | ||
39 | AMDGPU_PP_SENSOR_GPU_LOAD, | ||
40 | AMDGPU_PP_SENSOR_GFX_MCLK, | ||
41 | AMDGPU_PP_SENSOR_GPU_TEMP, | ||
42 | }; | ||
32 | 43 | ||
33 | enum amd_pp_event { | 44 | enum amd_pp_event { |
34 | AMD_PP_EVENT_INITIALIZE = 0, | 45 | AMD_PP_EVENT_INITIALIZE = 0, |
@@ -347,6 +358,7 @@ struct amd_powerplay_funcs { | |||
347 | int (*set_sclk_od)(void *handle, uint32_t value); | 358 | int (*set_sclk_od)(void *handle, uint32_t value); |
348 | int (*get_mclk_od)(void *handle); | 359 | int (*get_mclk_od)(void *handle); |
349 | int (*set_mclk_od)(void *handle, uint32_t value); | 360 | int (*set_mclk_od)(void *handle, uint32_t value); |
361 | int (*read_sensor)(void *handle, int idx, int32_t *value); | ||
350 | }; | 362 | }; |
351 | 363 | ||
352 | struct amd_powerplay { | 364 | struct amd_powerplay { |
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index c9628b4db2c3..fcd45452380d 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | |||
@@ -359,6 +359,7 @@ struct pp_hwmgr_func { | |||
359 | int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); | 359 | int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); |
360 | int (*get_mclk_od)(struct pp_hwmgr *hwmgr); | 360 | int (*get_mclk_od)(struct pp_hwmgr *hwmgr); |
361 | int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); | 361 | int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); |
362 | int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, int32_t *value); | ||
362 | }; | 363 | }; |
363 | 364 | ||
364 | struct pp_table_func { | 365 | struct pp_table_func { |