drm/amd/powerplay: add uploading pptable and resetting powerplay support

Necessary for re-initializing dpm with new pptables at runtime.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Eric Huang <JinHuiEric.Huang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Eric Huang 2016-06-01 17:08:07 -04:00 committed by Alex Deucher
parent 76ad42c192
commit 4dcf9e6f2e
4 changed files with 63 additions and 9 deletions

View file

@ -744,12 +744,12 @@ static int pp_dpm_get_pp_table(void *handle, char **table)
PP_CHECK_HW(hwmgr);
if (hwmgr->hwmgr_func->get_pp_table == NULL) {
printk(KERN_INFO "%s was not implemented.\n", __func__);
return 0;
}
if (!hwmgr->soft_pp_table)
return -EINVAL;
return hwmgr->hwmgr_func->get_pp_table(hwmgr, table);
*table = (char *)hwmgr->soft_pp_table;
return hwmgr->soft_pp_table_size;
}
static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
@ -763,12 +763,23 @@ static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
PP_CHECK_HW(hwmgr);
if (hwmgr->hwmgr_func->set_pp_table == NULL) {
printk(KERN_INFO "%s was not implemented.\n", __func__);
return 0;
if (!hwmgr->hardcode_pp_table) {
hwmgr->hardcode_pp_table =
kzalloc(hwmgr->soft_pp_table_size, GFP_KERNEL);
if (!hwmgr->hardcode_pp_table)
return -ENOMEM;
/* to avoid powerplay crash when hardcode pptable is empty */
memcpy(hwmgr->hardcode_pp_table, hwmgr->soft_pp_table,
hwmgr->soft_pp_table_size);
}
return hwmgr->hwmgr_func->set_pp_table(hwmgr, buf, size);
memcpy(hwmgr->hardcode_pp_table, buf, size);
hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
return amd_powerplay_reset(handle);
}
static int pp_dpm_force_clock_level(void *handle,
@ -993,6 +1004,44 @@ int amd_powerplay_fini(void *handle)
return 0;
}
int amd_powerplay_reset(void *handle)
{
struct pp_instance *instance = (struct pp_instance *)handle;
struct pp_eventmgr *eventmgr;
struct pem_event_data event_data = { {0} };
int ret;
if (instance == NULL)
return -EINVAL;
eventmgr = instance->eventmgr;
if (!eventmgr || !eventmgr->pp_eventmgr_fini)
return -EINVAL;
eventmgr->pp_eventmgr_fini(eventmgr);
ret = pp_sw_fini(handle);
if (ret)
return ret;
kfree(instance->hwmgr->ps);
ret = pp_sw_init(handle);
if (ret)
return ret;
hw_init_power_state_table(instance->hwmgr);
if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL)
return -EINVAL;
ret = eventmgr->pp_eventmgr_init(eventmgr);
if (ret)
return ret;
return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data);
}
/* export this function to DAL */
int amd_powerplay_display_configuration_change(void *handle,

View file

@ -95,6 +95,8 @@ int hwmgr_fini(struct pp_hwmgr *hwmgr)
return -EINVAL;
/* do hwmgr finish*/
kfree(hwmgr->hardcode_pp_table);
kfree(hwmgr->backend);
kfree(hwmgr->start_thermal_controller.function_list);

View file

@ -360,6 +360,8 @@ int amd_powerplay_init(struct amd_pp_init *pp_init,
int amd_powerplay_fini(void *handle);
int amd_powerplay_reset(void *handle);
int amd_powerplay_display_configuration_change(void *handle,
const struct amd_pp_display_configuration *input);

View file

@ -584,6 +584,7 @@ struct pp_hwmgr {
struct pp_smumgr *smumgr;
const void *soft_pp_table;
uint32_t soft_pp_table_size;
void *hardcode_pp_table;
bool need_pp_table_upload;
enum amd_dpm_forced_level dpm_level;
bool block_hw_access;