@@ -1649,10 +1649,188 @@ static int navi10_update_pcie_parameters(struct smu_context *smu,
1649
1649
SMU_MSG_OverridePcieParameters ,
1650
1650
smu_pcie_arg );
1651
1651
}
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
+ }
1652
1721
1653
1722
return ret ;
1654
1723
}
1655
1724
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
+ }
1656
1834
1657
1835
static const struct pptable_funcs navi10_ppt_funcs = {
1658
1836
.tables_init = navi10_tables_init ,
@@ -1742,6 +1920,8 @@ static const struct pptable_funcs navi10_ppt_funcs = {
1742
1920
.get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq ,
1743
1921
.set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range ,
1744
1922
.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 ,
1745
1925
};
1746
1926
1747
1927
void navi10_set_ppt_funcs (struct smu_context * smu )
0 commit comments