/* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs
* not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ]
*/
-uint16_t fiji_clock_stretcher_lookup_table[2][4] = { {600, 1050, 3, 0},
- {600, 1050, 6, 1} };
+static const uint16_t fiji_clock_stretcher_lookup_table[2][4] =
+{ {600, 1050, 3, 0}, {600, 1050, 6, 1} };
/* [FF, SS] type, [] 4 voltage ranges, and
* [Floor Freq, Boundary Freq, VID min , VID max]
*/
-uint32_t fiji_clock_stretcher_ddt_table[2][4][4] =
+static const uint32_t fiji_clock_stretcher_ddt_table[2][4][4] =
{ { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
{ {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } };
/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%]
* (coming from PWR_CKS_CNTL.stretch_amount reg spec)
*/
-uint8_t fiji_clock_stretch_amount_conversion[2][6] = { {0, 1, 3, 2, 4, 5},
- {0, 2, 4, 5, 6, 5} };
+static const uint8_t fiji_clock_stretch_amount_conversion[2][6] =
+{ {0, 1, 3, 2, 4, 5}, {0, 2, 4, 5, 6, 5} };
-const unsigned long PhwFiji_Magic = (unsigned long)(PHM_VIslands_Magic);
+static const unsigned long PhwFiji_Magic = (unsigned long)(PHM_VIslands_Magic);
struct fiji_power_state *cast_phw_fiji_power_state(
struct pp_hw_power_state *hw_ps)
table_info->vdd_dep_on_mclk;
PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL,
- "VDD dependency on SCLK table is missing. \
+ "VDD dependency on SCLK table is missing. \
This table is mandatory", return -EINVAL);
PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,
- "VDD dependency on SCLK table has to have is missing. \
+ "VDD dependency on SCLK table has to have is missing. \
This table is mandatory", return -EINVAL);
PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL,
- "VDD dependency on MCLK table is missing. \
+ "VDD dependency on MCLK table is missing. \
This table is mandatory", return -EINVAL);
PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,
"VDD dependency on MCLK table has to have is missing. \
return 0;
}
+static int fiji_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
+{
+ struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+ if (data->soft_pp_table) {
+ kfree(data->soft_pp_table);
+ data->soft_pp_table = NULL;
+ }
+
+ return phm_hwmgr_backend_fini(hwmgr);
+}
+
static int fiji_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
{
struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
data->pcie_lane_cap = (uint32_t)sys_info.value;
} else {
/* Ignore return value in here, we are cleaning up a mess. */
- tonga_hwmgr_backend_fini(hwmgr);
+ fiji_hwmgr_backend_fini(hwmgr);
}
return 0;
return 0;
}
+
+static uint8_t fiji_get_sleep_divider_id_from_clock(struct pp_hwmgr *hwmgr,
+ uint32_t clock, uint32_t clock_insr)
+{
+ uint8_t i;
+ uint32_t temp;
+ uint32_t min = clock_insr > FIJI_MINIMUM_ENGINE_CLOCK ?
+ clock_insr : FIJI_MINIMUM_ENGINE_CLOCK;
+
+ PP_ASSERT_WITH_CODE((clock >= min), "Engine clock can't satisfy stutter requirement!", return 0);
+ for (i = FIJI_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) {
+ temp = clock / (1UL << i);
+
+ if (temp >= min || i == 0)
+ break;
+ }
+ return i;
+}
/**
* Populates single SMC SCLK structure using the provided engine clock
*
threshold = clock * data->fast_watermark_threshold / 100;
- /*
- * TODO: get minimum clocks from dal configaration
- * PECI_GetMinClockSettings(hwmgr->pPECI, &minClocks);
- */
- /* data->DisplayTiming.minClockInSR = minClocks.engineClockInSR; */
- /* get level->DeepSleepDivId
- if (phm_cap_enabled(hwmgr->platformDescriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep))
- {
- level->DeepSleepDivId = PhwFiji_GetSleepDividerIdFromClock(hwmgr, clock, minClocks.engineClockInSR);
- } */
+ data->display_timing.min_clock_in_sr = hwmgr->display_config.min_core_set_clock_in_sr;
+
+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep))
+ level->DeepSleepDivId = fiji_get_sleep_divider_id_from_clock(hwmgr, clock,
+ hwmgr->display_config.min_core_set_clock_in_sr);
+
/* Default to slow, highest DPM level will be
* set to PPSMC_DISPLAY_WATERMARK_LOW later.
DPM_EVENT_SRC, src);
PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
THERMAL_PROTECTION_DIS,
- phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+ !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_ThermalController));
} else
PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
struct fiji_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
uint32_t mclk = fiji_ps->performance_levels
[fiji_ps->performance_level_count - 1].memory_clock;
- struct PP_Clocks min_clocks = {0};
uint32_t i;
struct cgs_display_info info = {0};
if (i >= sclk_table->count)
data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
else {
- /* TODO: Check SCLK in DAL's minimum clocks
- * in case DeepSleep divider update is required.
- */
- if(data->display_timing.min_clock_in_sr != min_clocks.engineClockInSR)
+ if(data->display_timing.min_clock_in_sr !=
+ hwmgr->display_config.min_core_set_clock_in_sr)
data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK;
}
{
struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
- *table = (char *)&data->smc_state_table;
+ if (!data->soft_pp_table) {
+ data->soft_pp_table = kzalloc(hwmgr->soft_pp_table_size, GFP_KERNEL);
+ if (!data->soft_pp_table)
+ return -ENOMEM;
+ memcpy(data->soft_pp_table, hwmgr->soft_pp_table,
+ hwmgr->soft_pp_table_size);
+ }
- return sizeof(struct SMU73_Discrete_DpmTable);
+ *table = (char *)&data->soft_pp_table;
+
+ return hwmgr->soft_pp_table_size;
}
static int fiji_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_t size)
{
struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
- void *table = (void *)&data->smc_state_table;
+ if (!data->soft_pp_table) {
+ data->soft_pp_table = kzalloc(hwmgr->soft_pp_table_size, GFP_KERNEL);
+ if (!data->soft_pp_table)
+ return -ENOMEM;
+ }
- memcpy(table, buf, size);
+ memcpy(data->soft_pp_table, buf, size);
+
+ hwmgr->soft_pp_table = data->soft_pp_table;
+
+ /* TODO: re-init powerplay to implement modified pptable */
return 0;
}
static int fiji_force_clock_level(struct pp_hwmgr *hwmgr,
- enum pp_clock_type type, int level)
+ enum pp_clock_type type, uint32_t mask)
{
struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
if (!data->sclk_dpm_key_disabled)
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_SCLKDPM_SetEnabledMask,
- (1 << level));
+ data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
break;
+
case PP_MCLK:
if (!data->mclk_dpm_key_disabled)
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_MCLKDPM_SetEnabledMask,
- (1 << level));
+ data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
break;
+
case PP_PCIE:
+ {
+ uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask;
+ uint32_t level = 0;
+
+ while (tmp >>= 1)
+ level++;
+
if (!data->pcie_dpm_key_disabled)
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_PCIeDPM_ForceLevel,
- (1 << level));
+ level);
break;
+ }
default:
break;
}
if (data->display_timing.num_existing_displays != info.display_count)
is_update_required = true;
-/* TO DO NEED TO GET DEEP SLEEP CLOCK FROM DAL
- if (phm_cap_enabled(hwmgr->hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
- cgs_get_min_clock_settings(hwmgr->device, &min_clocks);
- if(min_clocks.engineClockInSR != data->display_timing.minClockInSR)
+
+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
+ if(hwmgr->display_config.min_core_set_clock_in_sr != data->display_timing.min_clock_in_sr)
is_update_required = true;
-*/
+ }
+
return is_update_required;
}
static const struct pp_hwmgr_func fiji_hwmgr_funcs = {
.backend_init = &fiji_hwmgr_backend_init,
- .backend_fini = &tonga_hwmgr_backend_fini,
+ .backend_fini = &fiji_hwmgr_backend_fini,
.asic_setup = &fiji_setup_asic_task,
.dynamic_state_management_enable = &fiji_enable_dpm_tasks,
.force_dpm_level = &fiji_dpm_force_dpm_level,