Skip to content

Commit 21677d0

Browse files
mcoffinalexdeucher
authored andcommitted
drm/amdgpu/navi10: implement sclk/mclk OD via pp_od_clk_voltage
[Why] Before this patch, there was no way to use pp_od_clk_voltage on navi [How] Similar to the vega20 implementation, but using the common smc_v11_0 headers, implemented the pp_od_clk_voltage API for navi10's pptable implementation Reviewed-by: Evan Quan <[email protected]> Signed-off-by: Matt Coffin <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 9f87516 commit 21677d0

File tree

3 files changed

+209
-0
lines changed

3 files changed

+209
-0
lines changed

drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,4 +250,6 @@ int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_
250250

251251
int smu_v11_0_override_pcie_parameters(struct smu_context *smu);
252252

253+
int smu_v11_0_set_default_od_settings(struct smu_context *smu, bool initialize, size_t overdrive_table_size);
254+
253255
#endif

drivers/gpu/drm/amd/powerplay/navi10_ppt.c

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,10 +1649,188 @@ static int navi10_update_pcie_parameters(struct smu_context *smu,
16491649
SMU_MSG_OverridePcieParameters,
16501650
smu_pcie_arg);
16511651
}
1652+
return ret;
1653+
}
1654+
1655+
static inline void navi10_dump_od_table(OverDriveTable_t *od_table) {
1656+
pr_debug("OD: Gfxclk: (%d, %d)\n", od_table->GfxclkFmin, od_table->GfxclkFmax);
1657+
pr_debug("OD: Gfx1: (%d, %d)\n", od_table->GfxclkFreq1, od_table->GfxclkVolt1);
1658+
pr_debug("OD: Gfx2: (%d, %d)\n", od_table->GfxclkFreq2, od_table->GfxclkVolt2);
1659+
pr_debug("OD: Gfx3: (%d, %d)\n", od_table->GfxclkFreq3, od_table->GfxclkVolt3);
1660+
pr_debug("OD: UclkFmax: %d\n", od_table->UclkFmax);
1661+
pr_debug("OD: OverDrivePct: %d\n", od_table->OverDrivePct);
1662+
}
1663+
1664+
static inline bool navi10_od_feature_is_supported(struct smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODFEATURE_ID feature)
1665+
{
1666+
return od_table->cap[feature];
1667+
}
1668+
1669+
static int navi10_od_setting_check_range(struct smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODSETTING_ID setting, uint32_t value)
1670+
{
1671+
if (value < od_table->min[setting]) {
1672+
pr_warn("OD setting (%d, %d) is less than the minimum allowed (%d)\n", setting, value, od_table->min[setting]);
1673+
return -EINVAL;
1674+
}
1675+
if (value > od_table->max[setting]) {
1676+
pr_warn("OD setting (%d, %d) is greater than the maximum allowed (%d)\n", setting, value, od_table->max[setting]);
1677+
return -EINVAL;
1678+
}
1679+
return 0;
1680+
}
1681+
1682+
static int navi10_setup_od_limits(struct smu_context *smu) {
1683+
struct smu_11_0_overdrive_table *overdrive_table = NULL;
1684+
struct smu_11_0_powerplay_table *powerplay_table = NULL;
1685+
1686+
if (!smu->smu_table.power_play_table) {
1687+
pr_err("powerplay table uninitialized!\n");
1688+
return -ENOENT;
1689+
}
1690+
powerplay_table = (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
1691+
overdrive_table = &powerplay_table->overdrive_table;
1692+
if (!smu->od_settings) {
1693+
smu->od_settings = kmemdup(overdrive_table, sizeof(struct smu_11_0_overdrive_table), GFP_KERNEL);
1694+
} else {
1695+
memcpy(smu->od_settings, overdrive_table, sizeof(struct smu_11_0_overdrive_table));
1696+
}
1697+
return 0;
1698+
}
1699+
1700+
static int navi10_set_default_od_settings(struct smu_context *smu, bool initialize) {
1701+
OverDriveTable_t *od_table;
1702+
int ret = 0;
1703+
1704+
ret = smu_v11_0_set_default_od_settings(smu, initialize, sizeof(OverDriveTable_t));
1705+
if (ret)
1706+
return ret;
1707+
1708+
if (initialize) {
1709+
ret = navi10_setup_od_limits(smu);
1710+
if (ret) {
1711+
pr_err("Failed to retrieve board OD limits\n");
1712+
return ret;
1713+
}
1714+
1715+
}
1716+
1717+
od_table = (OverDriveTable_t *)smu->smu_table.overdrive_table;
1718+
if (od_table) {
1719+
navi10_dump_od_table(od_table);
1720+
}
16521721

16531722
return ret;
16541723
}
16551724

1725+
static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, long input[], uint32_t size) {
1726+
int i;
1727+
int ret = 0;
1728+
struct smu_table_context *table_context = &smu->smu_table;
1729+
OverDriveTable_t *od_table;
1730+
struct smu_11_0_overdrive_table *od_settings;
1731+
od_table = (OverDriveTable_t *)table_context->overdrive_table;
1732+
1733+
if (!smu->od_enabled) {
1734+
pr_warn("OverDrive is not enabled!\n");
1735+
return -EINVAL;
1736+
}
1737+
1738+
if (!smu->od_settings) {
1739+
pr_err("OD board limits are not set!\n");
1740+
return -ENOENT;
1741+
}
1742+
1743+
od_settings = smu->od_settings;
1744+
1745+
switch (type) {
1746+
case PP_OD_EDIT_SCLK_VDDC_TABLE:
1747+
if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODFEATURE_GFXCLK_LIMITS)) {
1748+
pr_warn("GFXCLK_LIMITS not supported!\n");
1749+
return -ENOTSUPP;
1750+
}
1751+
if (!table_context->overdrive_table) {
1752+
pr_err("Overdrive is not initialized\n");
1753+
return -EINVAL;
1754+
}
1755+
for (i = 0; i < size; i += 2) {
1756+
if (i + 2 > size) {
1757+
pr_info("invalid number of input parameters %d\n", size);
1758+
return -EINVAL;
1759+
}
1760+
switch (input[i]) {
1761+
case 0:
1762+
freq_setting = SMU_11_0_ODSETTING_GFXCLKFMIN;
1763+
freq_ptr = &od_table->GfxclkFmin;
1764+
if (input[i + 1] > od_table->GfxclkFmax) {
1765+
pr_info("GfxclkFmin (%ld) must be <= GfxclkFmax (%u)!\n",
1766+
input[i + 1],
1767+
od_table->GfxclkFmin);
1768+
return -EINVAL;
1769+
}
1770+
break;
1771+
case 1:
1772+
freq_setting = SMU_11_0_ODSETTING_GFXCLKFMAX;
1773+
freq_ptr = &od_table->GfxclkFmax;
1774+
if (input[i + 1] < od_table->GfxclkFmin) {
1775+
pr_info("GfxclkFmax (%ld) must be >= GfxclkFmin (%u)!\n",
1776+
input[i + 1],
1777+
od_table->GfxclkFmax);
1778+
return -EINVAL;
1779+
}
1780+
break;
1781+
default:
1782+
pr_info("Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]);
1783+
pr_info("Supported indices: [0:min,1:max]\n");
1784+
return -EINVAL;
1785+
}
1786+
ret = navi10_od_setting_check_range(od_settings, freq_setting, input[i + 1]);
1787+
if (ret)
1788+
return ret;
1789+
*freq_ptr = input[i + 1];
1790+
}
1791+
break;
1792+
case PP_OD_EDIT_MCLK_VDDC_TABLE:
1793+
if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODFEATURE_UCLK_MAX)) {
1794+
pr_warn("UCLK_MAX not supported!\n");
1795+
return -ENOTSUPP;
1796+
}
1797+
if (size < 2) {
1798+
pr_info("invalid number of parameters: %d\n", size);
1799+
return -EINVAL;
1800+
}
1801+
if (input[0] != 1) {
1802+
pr_info("Invalid MCLK_VDDC_TABLE index: %ld\n", input[0]);
1803+
pr_info("Supported indices: [1:max]\n");
1804+
return -EINVAL;
1805+
}
1806+
ret = navi10_od_setting_check_range(od_settings, SMU_11_0_ODSETTING_UCLKFMAX, input[1]);
1807+
if (ret)
1808+
return ret;
1809+
od_table->UclkFmax = input[1];
1810+
break;
1811+
case PP_OD_COMMIT_DPM_TABLE:
1812+
navi10_dump_od_table(od_table);
1813+
ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true);
1814+
if (ret) {
1815+
pr_err("Failed to import overdrive table!\n");
1816+
return ret;
1817+
}
1818+
// no lock needed because smu_od_edit_dpm_table has it
1819+
ret = smu_handle_task(smu, smu->smu_dpm.dpm_level,
1820+
AMD_PP_TASK_READJUST_POWER_STATE,
1821+
false);
1822+
if (ret) {
1823+
return ret;
1824+
}
1825+
break;
1826+
case PP_OD_EDIT_VDDC_CURVE:
1827+
// TODO: implement
1828+
return -ENOSYS;
1829+
default:
1830+
return -ENOSYS;
1831+
}
1832+
return ret;
1833+
}
16561834

16571835
static const struct pptable_funcs navi10_ppt_funcs = {
16581836
.tables_init = navi10_tables_init,
@@ -1742,6 +1920,8 @@ static const struct pptable_funcs navi10_ppt_funcs = {
17421920
.get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
17431921
.set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
17441922
.override_pcie_parameters = smu_v11_0_override_pcie_parameters,
1923+
.set_default_od_settings = navi10_set_default_od_settings,
1924+
.od_edit_dpm_table = navi10_od_edit_dpm_table,
17451925
};
17461926

17471927
void navi10_set_ppt_funcs(struct smu_context *smu)

drivers/gpu/drm/amd/powerplay/smu_v11_0.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1779,3 +1779,30 @@ int smu_v11_0_override_pcie_parameters(struct smu_context *smu)
17791779
return ret;
17801780

17811781
}
1782+
1783+
int smu_v11_0_set_default_od_settings(struct smu_context *smu, bool initialize, size_t overdrive_table_size)
1784+
{
1785+
struct smu_table_context *table_context = &smu->smu_table;
1786+
int ret = 0;
1787+
1788+
if (initialize) {
1789+
if (table_context->overdrive_table) {
1790+
return -EINVAL;
1791+
}
1792+
table_context->overdrive_table = kzalloc(overdrive_table_size, GFP_KERNEL);
1793+
if (!table_context->overdrive_table) {
1794+
return -ENOMEM;
1795+
}
1796+
ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, false);
1797+
if (ret) {
1798+
pr_err("Failed to export overdrive table!\n");
1799+
return ret;
1800+
}
1801+
}
1802+
ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, true);
1803+
if (ret) {
1804+
pr_err("Failed to import overdrive table!\n");
1805+
return ret;
1806+
}
1807+
return ret;
1808+
}

0 commit comments

Comments
 (0)