drm/amd/powerplay: modify smu_update_table to use SMU_TABLE_xxx as the input
[linux-2.6-block.git] / drivers / gpu / drm / amd / powerplay / amdgpu_smu.c
index c058c784180eecf8daab0840ec5ee8120fd6f296..fd628fc3c2551db3a7e1df796d691964f74d713b 100644 (file)
 #include "atom.h"
 #include "amd_pcie.h"
 
+int smu_get_smc_version(struct smu_context *smu, uint32_t *if_version, uint32_t *smu_version)
+{
+       int ret = 0;
+
+       if (!if_version && !smu_version)
+               return -EINVAL;
+
+       if (if_version) {
+               ret = smu_send_smc_msg(smu, SMU_MSG_GetDriverIfVersion);
+               if (ret)
+                       return ret;
+
+               ret = smu_read_smc_arg(smu, if_version);
+               if (ret)
+                       return ret;
+       }
+
+       if (smu_version) {
+               ret = smu_send_smc_msg(smu, SMU_MSG_GetSmuVersion);
+               if (ret)
+                       return ret;
+
+               ret = smu_read_smc_arg(smu, smu_version);
+               if (ret)
+                       return ret;
+       }
+
+       return ret;
+}
+
 int smu_dpm_set_power_gate(struct smu_context *smu, uint32_t block_type,
                           bool gate)
 {
@@ -97,20 +127,18 @@ int smu_common_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
        return ret;
 }
 
-int smu_update_table_with_arg(struct smu_context *smu, uint16_t table_id, uint16_t exarg,
+int smu_update_table(struct smu_context *smu, enum smu_table_id table_index,
                     void *table_data, bool drv2smu)
 {
        struct smu_table_context *smu_table = &smu->smu_table;
        struct smu_table *table = NULL;
        int ret = 0;
-       uint32_t table_index;
+       int table_id = smu_table_get_index(smu, table_index);
 
        if (!table_data || table_id >= smu_table->table_count)
                return -EINVAL;
 
-       table_index = (exarg << 16) | table_id;
-
-       table = &smu_table->tables[table_id];
+       table = &smu_table->tables[table_index];
 
        if (drv2smu)
                memcpy(table->cpu_addr, table_data, table->size);
@@ -126,7 +154,7 @@ int smu_update_table_with_arg(struct smu_context *smu, uint16_t table_id, uint16
        ret = smu_send_smc_msg_with_param(smu, drv2smu ?
                                          SMU_MSG_TransferTableDram2Smu :
                                          SMU_MSG_TransferTableSmu2Dram,
-                                         table_index);
+                                         table_id);
        if (ret)
                return ret;
 
@@ -138,13 +166,12 @@ int smu_update_table_with_arg(struct smu_context *smu, uint16_t table_id, uint16
 
 bool is_support_sw_smu(struct amdgpu_device *adev)
 {
-       if (amdgpu_dpm != 1)
-               return false;
-
-       if (adev->asic_type >= CHIP_VEGA20 && adev->asic_type != CHIP_RAVEN)
+       if (adev->asic_type == CHIP_VEGA20)
+               return (amdgpu_dpm == 2) ? true : false;
+       else if (adev->asic_type >= CHIP_NAVI10)
                return true;
-
-       return false;
+       else
+               return false;
 }
 
 int smu_sys_get_pp_table(struct smu_context *smu, void **table)
@@ -168,6 +195,8 @@ int smu_sys_set_pp_table(struct smu_context *smu,  void *buf, size_t size)
        ATOM_COMMON_TABLE_HEADER *header = (ATOM_COMMON_TABLE_HEADER *)buf;
        int ret = 0;
 
+       if (!smu->pm_enabled)
+               return -EINVAL;
        if (header->usStructureSize != size) {
                pr_err("pp table size not matched !\n");
                return -EIO;
@@ -201,31 +230,36 @@ int smu_feature_init_dpm(struct smu_context *smu)
 {
        struct smu_feature *feature = &smu->smu_feature;
        int ret = 0;
-       uint32_t unallowed_feature_mask[SMU_FEATURE_MAX/32];
+       uint32_t allowed_feature_mask[SMU_FEATURE_MAX/32];
 
+       if (!smu->pm_enabled)
+               return ret;
        mutex_lock(&feature->mutex);
-       bitmap_fill(feature->allowed, SMU_FEATURE_MAX);
+       bitmap_zero(feature->allowed, SMU_FEATURE_MAX);
        mutex_unlock(&feature->mutex);
 
-       ret = smu_get_unallowed_feature_mask(smu, unallowed_feature_mask,
+       ret = smu_get_allowed_feature_mask(smu, allowed_feature_mask,
                                             SMU_FEATURE_MAX/32);
        if (ret)
                return ret;
 
        mutex_lock(&feature->mutex);
-       bitmap_andnot(feature->allowed, feature->allowed,
-                     (unsigned long *)unallowed_feature_mask,
+       bitmap_or(feature->allowed, feature->allowed,
+                     (unsigned long *)allowed_feature_mask,
                      feature->feature_num);
        mutex_unlock(&feature->mutex);
 
        return ret;
 }
 
-int smu_feature_is_enabled(struct smu_context *smu, int feature_id)
+int smu_feature_is_enabled(struct smu_context *smu, enum smu_feature_mask mask)
 {
        struct smu_feature *feature = &smu->smu_feature;
+       uint32_t feature_id;
        int ret = 0;
 
+       feature_id = smu_feature_get_index(smu, mask);
+
        WARN_ON(feature_id > feature->feature_num);
 
        mutex_lock(&feature->mutex);
@@ -235,11 +269,15 @@ int smu_feature_is_enabled(struct smu_context *smu, int feature_id)
        return ret;
 }
 
-int smu_feature_set_enabled(struct smu_context *smu, int feature_id, bool enable)
+int smu_feature_set_enabled(struct smu_context *smu, enum smu_feature_mask mask,
+                           bool enable)
 {
        struct smu_feature *feature = &smu->smu_feature;
+       uint32_t feature_id;
        int ret = 0;
 
+       feature_id = smu_feature_get_index(smu, mask);
+
        WARN_ON(feature_id > feature->feature_num);
 
        mutex_lock(&feature->mutex);
@@ -258,11 +296,14 @@ failed:
        return ret;
 }
 
-int smu_feature_is_supported(struct smu_context *smu, int feature_id)
+int smu_feature_is_supported(struct smu_context *smu, enum smu_feature_mask mask)
 {
        struct smu_feature *feature = &smu->smu_feature;
+       uint32_t feature_id;
        int ret = 0;
 
+       feature_id = smu_feature_get_index(smu, mask);
+
        WARN_ON(feature_id > feature->feature_num);
 
        mutex_lock(&feature->mutex);
@@ -272,15 +313,19 @@ int smu_feature_is_supported(struct smu_context *smu, int feature_id)
        return ret;
 }
 
-int smu_feature_set_supported(struct smu_context *smu, int feature_id,
+int smu_feature_set_supported(struct smu_context *smu,
+                             enum smu_feature_mask mask,
                              bool enable)
 {
        struct smu_feature *feature = &smu->smu_feature;
+       uint32_t feature_id;
        int ret = 0;
 
+       feature_id = smu_feature_get_index(smu, mask);
+
        WARN_ON(feature_id > feature->feature_num);
 
-       mutex_unlock(&feature->mutex);
+       mutex_lock(&feature->mutex);
        if (enable)
                test_and_set_bit(feature_id, feature->supported);
        else
@@ -296,7 +341,7 @@ static int smu_set_funcs(struct amdgpu_device *adev)
 
        switch (adev->asic_type) {
        case CHIP_VEGA20:
-               adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
+       case CHIP_NAVI10:
                if (adev->pm.pp_feature & PP_OVERDRIVE_MASK)
                        smu->od_enabled = true;
                smu_v11_0_set_smu_funcs(smu);
@@ -314,6 +359,7 @@ static int smu_early_init(void *handle)
        struct smu_context *smu = &adev->smu;
 
        smu->adev = adev;
+       smu->pm_enabled = !!amdgpu_dpm;
        mutex_init(&smu->mutex);
 
        return smu_set_funcs(adev);
@@ -323,6 +369,9 @@ static int smu_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        struct smu_context *smu = &adev->smu;
+
+       if (!smu->pm_enabled)
+               return 0;
        mutex_lock(&smu->mutex);
        smu_handle_task(&adev->smu,
                        smu->smu_dpm.dpm_level,
@@ -406,9 +455,6 @@ static int smu_sw_init(void *handle)
        struct smu_context *smu = &adev->smu;
        int ret;
 
-       if (!is_support_sw_smu(adev))
-               return -EINVAL;
-
        smu->pool_size = adev->pm.smu_prv_buffer_size;
        smu->smu_feature.feature_num = SMU_FEATURE_MAX;
        mutex_init(&smu->smu_feature.mutex);
@@ -460,9 +506,6 @@ static int smu_sw_fini(void *handle)
        struct smu_context *smu = &adev->smu;
        int ret;
 
-       if (!is_support_sw_smu(adev))
-               return -EINVAL;
-
        ret = smu_smc_table_sw_fini(smu);
        if (ret) {
                pr_err("Failed to sw fini smc table!\n");
@@ -595,16 +638,12 @@ static int smu_smc_table_hw_init(struct smu_context *smu,
                return ret;
 
        if (initialize) {
-               ret = smu_read_pptable_from_vbios(smu);
-               if (ret)
-                       return ret;
-
                /* get boot_values from vbios to set revision, gfxclk, and etc. */
                ret = smu_get_vbios_bootup_values(smu);
                if (ret)
                        return ret;
 
-               ret = smu_get_clk_info_from_vbios(smu);
+               ret = smu_setup_pptable(smu);
                if (ret)
                        return ret;
 
@@ -612,10 +651,6 @@ static int smu_smc_table_hw_init(struct smu_context *smu,
                 * check if the format_revision in vbios is up to pptable header
                 * version, and the structure size is not 0.
                 */
-               ret = smu_get_clk_info_from_vbios(smu);
-               if (ret)
-                       return ret;
-
                ret = smu_check_pptable(smu);
                if (ret)
                        return ret;
@@ -716,6 +751,9 @@ static int smu_smc_table_hw_init(struct smu_context *smu,
         */
        ret = smu_set_tool_table_location(smu);
 
+       if (!smu_is_dpm_running(smu))
+               pr_info("dpm has been disabled\n");
+
        return ret;
 }
 
@@ -788,19 +826,12 @@ static int smu_hw_init(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        struct smu_context *smu = &adev->smu;
 
-       if (!is_support_sw_smu(adev))
-               return -EINVAL;
-
-       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
-               ret = smu_load_microcode(smu);
-               if (ret)
+       if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+               ret = smu_check_fw_status(smu);
+               if (ret) {
+                       pr_err("SMC firmware status is not correct\n");
                        return ret;
-       }
-
-       ret = smu_check_fw_status(smu);
-       if (ret) {
-               pr_err("SMC firmware status is not correct\n");
-               return ret;
+               }
        }
 
        mutex_lock(&smu->mutex);
@@ -831,7 +862,10 @@ static int smu_hw_init(void *handle)
 
        mutex_unlock(&smu->mutex);
 
-       adev->pm.dpm_enabled = true;
+       if (!smu->pm_enabled)
+               adev->pm.dpm_enabled = false;
+       else
+               adev->pm.dpm_enabled = true;
 
        pr_info("SMU is initialized successfully!\n");
 
@@ -849,9 +883,6 @@ static int smu_hw_fini(void *handle)
        struct smu_table_context *table_context = &smu->smu_table;
        int ret = 0;
 
-       if (!is_support_sw_smu(adev))
-               return -EINVAL;
-
        kfree(table_context->driver_pptable);
        table_context->driver_pptable = NULL;
 
@@ -906,9 +937,6 @@ static int smu_suspend(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        struct smu_context *smu = &adev->smu;
 
-       if (!is_support_sw_smu(adev))
-               return -EINVAL;
-
        ret = smu_system_features_control(smu, false);
        if (ret)
                return ret;
@@ -924,9 +952,6 @@ static int smu_resume(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        struct smu_context *smu = &adev->smu;
 
-       if (!is_support_sw_smu(adev))
-               return -EINVAL;
-
        pr_info("SMU is resuming...\n");
 
        mutex_lock(&smu->mutex);
@@ -955,7 +980,7 @@ int smu_display_configuration_change(struct smu_context *smu,
        int index = 0;
        int num_of_active_display = 0;
 
-       if (!is_support_sw_smu(smu->adev))
+       if (!smu->pm_enabled || !is_support_sw_smu(smu->adev))
                return -EINVAL;
 
        if (!display_config)
@@ -1083,7 +1108,7 @@ static int smu_enable_umd_pstate(void *handle,
 
        struct smu_context *smu = (struct smu_context*)(handle);
        struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
-       if (!smu_dpm_ctx->dpm_context)
+       if (!smu->pm_enabled || !smu_dpm_ctx->dpm_context)
                return -EINVAL;
 
        if (!(smu_dpm_ctx->dpm_level & profile_mode_mask)) {
@@ -1126,6 +1151,8 @@ int smu_adjust_power_state_dynamic(struct smu_context *smu,
        long workload;
        struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
 
+       if (!smu->pm_enabled)
+               return -EINVAL;
        if (!skip_display_settings) {
                ret = smu_display_config_changed(smu);
                if (ret) {
@@ -1134,6 +1161,8 @@ int smu_adjust_power_state_dynamic(struct smu_context *smu,
                }
        }
 
+       if (!smu->pm_enabled)
+               return -EINVAL;
        ret = smu_apply_clocks_adjust_rules(smu);
        if (ret) {
                pr_err("Failed to apply clocks adjust rules!");