2015-12-02 17:46:21 -05:00
/*
* Copyright 2015 Advanced Micro Devices , Inc .
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE COPYRIGHT HOLDER ( S ) OR AUTHOR ( S ) BE LIABLE FOR ANY CLAIM , DAMAGES OR
* OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE ,
* ARISING FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE .
*
* Authors : AMD
*
*/
# include "atom.h"
# include "amdgpu.h"
# include "amd_shared.h"
# include <linux/module.h>
# include <linux/moduleparam.h>
# include "amdgpu_pm.h"
# include <drm/amdgpu_drm.h>
# include "amdgpu_powerplay.h"
# include "cik_dpm.h"
# include "vi_dpm.h"
static int amdgpu_powerplay_init ( struct amdgpu_device * adev )
{
int ret = 0 ;
struct amd_powerplay * amd_pp ;
amd_pp = & ( adev - > powerplay ) ;
2015-11-10 18:31:08 -05:00
if ( adev - > pp_enabled ) {
2015-12-02 17:46:21 -05:00
# ifdef CONFIG_DRM_AMD_POWERPLAY
struct amd_pp_init * pp_init ;
pp_init = kzalloc ( sizeof ( struct amd_pp_init ) , GFP_KERNEL ) ;
if ( pp_init = = NULL )
return - ENOMEM ;
pp_init - > chip_family = adev - > family ;
pp_init - > chip_id = adev - > asic_type ;
pp_init - > device = amdgpu_cgs_create_device ( adev ) ;
ret = amd_powerplay_init ( pp_init , amd_pp ) ;
kfree ( pp_init ) ;
# endif
} else {
amd_pp - > pp_handle = ( void * ) adev ;
switch ( adev - > asic_type ) {
# ifdef CONFIG_DRM_AMDGPU_CIK
case CHIP_BONAIRE :
case CHIP_HAWAII :
amd_pp - > ip_funcs = & ci_dpm_ip_funcs ;
break ;
case CHIP_KABINI :
case CHIP_MULLINS :
case CHIP_KAVERI :
amd_pp - > ip_funcs = & kv_dpm_ip_funcs ;
break ;
# endif
case CHIP_TOPAZ :
amd_pp - > ip_funcs = & iceland_dpm_ip_funcs ;
break ;
case CHIP_TONGA :
amd_pp - > ip_funcs = & tonga_dpm_ip_funcs ;
break ;
2015-09-29 14:58:53 -04:00
case CHIP_FIJI :
amd_pp - > ip_funcs = & fiji_dpm_ip_funcs ;
break ;
2015-12-02 17:46:21 -05:00
case CHIP_CARRIZO :
2015-11-20 13:33:44 -05:00
case CHIP_STONEY :
2015-12-02 17:46:21 -05:00
amd_pp - > ip_funcs = & cz_dpm_ip_funcs ;
break ;
default :
ret = - EINVAL ;
break ;
}
}
return ret ;
}
static int amdgpu_pp_early_init ( void * handle )
{
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
int ret = 0 ;
2015-10-20 11:05:45 +08:00
# ifdef CONFIG_DRM_AMD_POWERPLAY
2015-10-17 17:57:58 +08:00
switch ( adev - > asic_type ) {
case CHIP_TONGA :
2015-10-20 11:05:45 +08:00
case CHIP_FIJI :
2015-11-10 18:31:08 -05:00
adev - > pp_enabled = ( amdgpu_powerplay = = 0 ) ? false : true ;
2015-10-17 17:57:58 +08:00
break ;
default :
2015-11-10 18:31:08 -05:00
adev - > pp_enabled = ( amdgpu_powerplay > 0 ) ? true : false ;
2015-10-17 17:57:58 +08:00
break ;
}
2015-11-10 18:31:08 -05:00
# else
adev - > pp_enabled = false ;
2015-10-20 11:05:45 +08:00
# endif
2015-10-17 17:57:58 +08:00
2015-12-02 17:46:21 -05:00
ret = amdgpu_powerplay_init ( adev ) ;
if ( ret )
return ret ;
if ( adev - > powerplay . ip_funcs - > early_init )
ret = adev - > powerplay . ip_funcs - > early_init (
adev - > powerplay . pp_handle ) ;
return ret ;
}
2015-12-07 16:42:35 +08:00
static int amdgpu_pp_late_init ( void * handle )
{
int ret = 0 ;
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
if ( adev - > powerplay . ip_funcs - > late_init )
ret = adev - > powerplay . ip_funcs - > late_init (
adev - > powerplay . pp_handle ) ;
return ret ;
}
2015-12-02 17:46:21 -05:00
static int amdgpu_pp_sw_init ( void * handle )
{
int ret = 0 ;
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
if ( adev - > powerplay . ip_funcs - > sw_init )
ret = adev - > powerplay . ip_funcs - > sw_init (
adev - > powerplay . pp_handle ) ;
# ifdef CONFIG_DRM_AMD_POWERPLAY
2015-11-10 18:31:08 -05:00
if ( adev - > pp_enabled ) {
2015-12-02 17:46:21 -05:00
adev - > pm . dpm_enabled = true ;
amdgpu_pm_sysfs_init ( adev ) ;
}
# endif
return ret ;
}
static int amdgpu_pp_sw_fini ( void * handle )
{
int ret = 0 ;
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
if ( adev - > powerplay . ip_funcs - > sw_fini )
ret = adev - > powerplay . ip_funcs - > sw_fini (
adev - > powerplay . pp_handle ) ;
if ( ret )
return ret ;
# ifdef CONFIG_DRM_AMD_POWERPLAY
2015-11-10 18:31:08 -05:00
if ( adev - > pp_enabled ) {
2015-12-02 17:46:21 -05:00
amdgpu_pm_sysfs_fini ( adev ) ;
amd_powerplay_fini ( adev - > powerplay . pp_handle ) ;
}
# endif
return ret ;
}
static int amdgpu_pp_hw_init ( void * handle )
{
int ret = 0 ;
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
2015-11-10 18:31:08 -05:00
if ( adev - > pp_enabled & & adev - > firmware . smu_load )
2015-12-02 17:46:21 -05:00
amdgpu_ucode_init_bo ( adev ) ;
if ( adev - > powerplay . ip_funcs - > hw_init )
ret = adev - > powerplay . ip_funcs - > hw_init (
adev - > powerplay . pp_handle ) ;
return ret ;
}
static int amdgpu_pp_hw_fini ( void * handle )
{
int ret = 0 ;
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
if ( adev - > powerplay . ip_funcs - > hw_fini )
ret = adev - > powerplay . ip_funcs - > hw_fini (
adev - > powerplay . pp_handle ) ;
2015-11-10 18:31:08 -05:00
if ( adev - > pp_enabled & & adev - > firmware . smu_load )
2015-12-02 17:46:21 -05:00
amdgpu_ucode_fini_bo ( adev ) ;
return ret ;
}
static int amdgpu_pp_suspend ( void * handle )
{
int ret = 0 ;
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
if ( adev - > powerplay . ip_funcs - > suspend )
ret = adev - > powerplay . ip_funcs - > suspend (
adev - > powerplay . pp_handle ) ;
return ret ;
}
static int amdgpu_pp_resume ( void * handle )
{
int ret = 0 ;
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
if ( adev - > powerplay . ip_funcs - > resume )
ret = adev - > powerplay . ip_funcs - > resume (
adev - > powerplay . pp_handle ) ;
return ret ;
}
static int amdgpu_pp_set_clockgating_state ( void * handle ,
enum amd_clockgating_state state )
{
int ret = 0 ;
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
if ( adev - > powerplay . ip_funcs - > set_clockgating_state )
ret = adev - > powerplay . ip_funcs - > set_clockgating_state (
adev - > powerplay . pp_handle , state ) ;
return ret ;
}
static int amdgpu_pp_set_powergating_state ( void * handle ,
enum amd_powergating_state state )
{
int ret = 0 ;
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
if ( adev - > powerplay . ip_funcs - > set_powergating_state )
ret = adev - > powerplay . ip_funcs - > set_powergating_state (
adev - > powerplay . pp_handle , state ) ;
return ret ;
}
static bool amdgpu_pp_is_idle ( void * handle )
{
bool ret = true ;
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
if ( adev - > powerplay . ip_funcs - > is_idle )
ret = adev - > powerplay . ip_funcs - > is_idle (
adev - > powerplay . pp_handle ) ;
return ret ;
}
static int amdgpu_pp_wait_for_idle ( void * handle )
{
int ret = 0 ;
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
if ( adev - > powerplay . ip_funcs - > wait_for_idle )
ret = adev - > powerplay . ip_funcs - > wait_for_idle (
adev - > powerplay . pp_handle ) ;
return ret ;
}
static int amdgpu_pp_soft_reset ( void * handle )
{
int ret = 0 ;
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
if ( adev - > powerplay . ip_funcs - > soft_reset )
ret = adev - > powerplay . ip_funcs - > soft_reset (
adev - > powerplay . pp_handle ) ;
return ret ;
}
static void amdgpu_pp_print_status ( void * handle )
{
struct amdgpu_device * adev = ( struct amdgpu_device * ) handle ;
if ( adev - > powerplay . ip_funcs - > print_status )
adev - > powerplay . ip_funcs - > print_status (
adev - > powerplay . pp_handle ) ;
}
const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
. early_init = amdgpu_pp_early_init ,
2015-12-07 16:42:35 +08:00
. late_init = amdgpu_pp_late_init ,
2015-12-02 17:46:21 -05:00
. sw_init = amdgpu_pp_sw_init ,
. sw_fini = amdgpu_pp_sw_fini ,
. hw_init = amdgpu_pp_hw_init ,
. hw_fini = amdgpu_pp_hw_fini ,
. suspend = amdgpu_pp_suspend ,
. resume = amdgpu_pp_resume ,
. is_idle = amdgpu_pp_is_idle ,
. wait_for_idle = amdgpu_pp_wait_for_idle ,
. soft_reset = amdgpu_pp_soft_reset ,
. print_status = amdgpu_pp_print_status ,
. set_clockgating_state = amdgpu_pp_set_clockgating_state ,
. set_powergating_state = amdgpu_pp_set_powergating_state ,
} ;