2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-22 12:14:01 +08:00

Merge branch 'drm-next-3.11' of git://people.freedesktop.org/~agd5f/linux into drm-next

This is the pull request for radeon for 3.11.  Highlights include:

- Support for CIK (Sea Islands) asics: 3D, compute, UVD
- DPM (Dynamic Power Management) support for 6xx-SI
- ASPM support for 6xx-SI
- Assorted bug fixes

* 'drm-next-3.11' of git://people.freedesktop.org/~agd5f/linux: (168 commits)
  drm/radeon/SI: fix TDP adjustment in set_power_state
  drm/radeon/NI: fix TDP adjustment in set_power_state
  drm/radeon: fix endian issues in atombios dpm code
  drm/radeon/dpm: fix UVD clock setting on SI
  drm/radeon/dpm: fix UVD clock setting on cayman
  drm/radeon/dpm: add support for setting UVD clock on rv6xx
  drm/radeon/dpm: add support for setting UVD clock on rs780
  drm/radeon: fix typo in ni_print_power_state
  drm/radeon: fix typo in cik_select_se_sh()
  drm/radeon/si: fix typo in function name
  drm/radeon/dpm: fix typo in setting uvd clock
  drm/radeon/dpm: add dpm_set_power_state failure output (si)
  add dpm_set_power_state failure output (7xx-ni)
  drm/radeon/dpm: add dpm_set_power_state failure output (7xx-ni)
  drm/radeon/dpm: add dpm_enable failure output (si)
  drm/radeon/dpm: add dpm_enable failure output (7xx-ni)
  drm/radeon/kms: add dpm support for SI (v7)
  drm/radeon: switch SI to use radeon_ucode.h
  drm/radeon: add SI to r600_is_internal_thermal_sensor()
  drm/radeon/dpm/rs780: properly catch errors in dpm setup
  ...
This commit is contained in:
Dave Airlie 2013-06-28 10:53:23 +10:00
commit 5b0207bb59
88 changed files with 53013 additions and 614 deletions

View File

@ -76,7 +76,10 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \
evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \
atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
si_blit_shaders.o radeon_prime.o radeon_uvd.o
si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o \
r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
trinity_smc.o ni_dpm.o si_smc.o si_dpm.o
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o

View File

@ -69,6 +69,8 @@
#define ENCODER_OBJECT_ID_ALMOND 0x22
#define ENCODER_OBJECT_ID_TRAVIS 0x23
#define ENCODER_OBJECT_ID_NUTMEG 0x22
#define ENCODER_OBJECT_ID_HDMI_ANX9805 0x26
/* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */
#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 0x13
#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 0x14
@ -86,6 +88,8 @@
#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 0x20
#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 0x21
#define ENCODER_OBJECT_ID_INTERNAL_VCE 0x24
#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 0x25
#define ENCODER_OBJECT_ID_INTERNAL_AMCLK 0x27
#define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO 0xFF
@ -364,6 +368,14 @@
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_UNIPHY3_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_UNIPHY3_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 << OBJECT_ID_SHIFT)
#define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT)
@ -392,6 +404,10 @@
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_VCE << OBJECT_ID_SHIFT)
#define ENCODER_HDMI_ANX9805_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_HDMI_ANX9805 << OBJECT_ID_SHIFT)
/****************************************************/
/* Connector Object ID definition - Shared with BIOS */
/****************************************************/
@ -461,6 +477,14 @@
GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID5 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID6 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
@ -473,6 +497,10 @@
GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
#define CONNECTOR_VGA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
@ -541,6 +569,18 @@
GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
#define CONNECTOR_HDMI_TYPE_A_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
#define CONNECTOR_HDMI_TYPE_A_ENUM_ID5 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
#define CONNECTOR_HDMI_TYPE_A_ENUM_ID6 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT)

View File

@ -74,6 +74,8 @@
#define ATOM_PPLL2 1
#define ATOM_DCPLL 2
#define ATOM_PPLL0 2
#define ATOM_PPLL3 3
#define ATOM_EXT_PLL1 8
#define ATOM_EXT_PLL2 9
#define ATOM_EXT_CLOCK 10
@ -259,7 +261,7 @@ typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{
USHORT AdjustDisplayPll; //Atomic Table, used by various SW componentes.
USHORT AdjustMemoryController; //Atomic Table, indirectly used by various SW components,called from SetMemoryClock
USHORT EnableASIC_StaticPwrMgt; //Atomic Table, only used by Bios
USHORT ASIC_StaticPwrMgtStatusChange; //Obsolete , only used by Bios
USHORT SetUniphyInstance; //Atomic Table, only used by Bios
USHORT DAC_LoadDetection; //Atomic Table, directly used by various SW components,latest version 1.2
USHORT LVTMAEncoderControl; //Atomic Table,directly used by various SW components,latest version 1.3
USHORT HW_Misc_Operation; //Atomic Table, directly used by various SW components,latest version 1.1
@ -271,7 +273,7 @@ typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{
USHORT TVEncoderControl; //Function Table,directly used by various SW components,latest version 1.1
USHORT PatchMCSetting; //only used by BIOS
USHORT MC_SEQ_Control; //only used by BIOS
USHORT TV1OutputControl; //Atomic Table, Obsolete from Ry6xx, use DAC2 Output instead
USHORT Gfx_Harvesting; //Atomic Table, Obsolete from Ry6xx, Now only used by BIOS for GFX harvesting
USHORT EnableScaler; //Atomic Table, used only by Bios
USHORT BlankCRTC; //Atomic Table, directly used by various SW components,latest version 1.1
USHORT EnableCRTC; //Atomic Table, directly used by various SW components,latest version 1.1
@ -328,7 +330,7 @@ typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{
#define UNIPHYTransmitterControl DIG1TransmitterControl
#define LVTMATransmitterControl DIG2TransmitterControl
#define SetCRTC_DPM_State GetConditionalGoldenSetting
#define SetUniphyInstance ASIC_StaticPwrMgtStatusChange
#define ASIC_StaticPwrMgtStatusChange SetUniphyInstance
#define HPDInterruptService ReadHWAssistedI2CStatus
#define EnableVGA_Access GetSCLKOverMCLKRatio
#define EnableYUV GetDispObjectInfo
@ -338,7 +340,7 @@ typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{
#define TMDSAEncoderControl PatchMCSetting
#define LVDSEncoderControl MC_SEQ_Control
#define LCD1OutputControl HW_Misc_Operation
#define TV1OutputControl Gfx_Harvesting
typedef struct _ATOM_MASTER_COMMAND_TABLE
{
@ -478,11 +480,11 @@ typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3
typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4
{
#if ATOM_BIG_ENDIAN
ULONG ucPostDiv; //return parameter: post divider which is used to program to register directly
ULONG ucPostDiv:8; //return parameter: post divider which is used to program to register directly
ULONG ulClock:24; //Input= target clock, output = actual clock
#else
ULONG ulClock:24; //Input= target clock, output = actual clock
ULONG ucPostDiv; //return parameter: post divider which is used to program to register directly
ULONG ucPostDiv:8; //return parameter: post divider which is used to program to register directly
#endif
}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4;
@ -504,6 +506,32 @@ typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5
UCHAR ucReserved;
}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5;
typedef struct _COMPUTE_GPU_CLOCK_INPUT_PARAMETERS_V1_6
{
ATOM_COMPUTE_CLOCK_FREQ ulClock; //Input Parameter
ULONG ulReserved[2];
}COMPUTE_GPU_CLOCK_INPUT_PARAMETERS_V1_6;
//ATOM_COMPUTE_CLOCK_FREQ.ulComputeClockFlag
#define COMPUTE_GPUCLK_INPUT_FLAG_CLK_TYPE_MASK 0x0f
#define COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK 0x00
#define COMPUTE_GPUCLK_INPUT_FLAG_SCLK 0x01
typedef struct _COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6
{
COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 ulClock; //Output Parameter: ucPostDiv=DFS divider
ATOM_S_MPLL_FB_DIVIDER ulFbDiv; //Output Parameter: PLL FB divider
UCHAR ucPllRefDiv; //Output Parameter: PLL ref divider
UCHAR ucPllPostDiv; //Output Parameter: PLL post divider
UCHAR ucPllCntlFlag; //Output Flags: control flag
UCHAR ucReserved;
}COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6;
//ucPllCntlFlag
#define SPLL_CNTL_FLAG_VCO_MODE_MASK 0x03
// ucInputFlag
#define ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN 1 // 1-StrobeMode, 0-PerformanceMode
@ -1686,6 +1714,7 @@ typedef struct _PIXEL_CLOCK_PARAMETERS_V6
#define PIXEL_CLOCK_V6_MISC_HDMI_30BPP 0x08
#define PIXEL_CLOCK_V6_MISC_HDMI_48BPP 0x0c
#define PIXEL_CLOCK_V6_MISC_REF_DIV_SRC 0x10
#define PIXEL_CLOCK_V6_MISC_GEN_DPREFCLK 0x40
typedef struct _GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V2
{
@ -2102,6 +2131,17 @@ typedef struct _DVO_ENCODER_CONTROL_PARAMETERS_V3
}DVO_ENCODER_CONTROL_PARAMETERS_V3;
#define DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 DVO_ENCODER_CONTROL_PARAMETERS_V3
typedef struct _DVO_ENCODER_CONTROL_PARAMETERS_V1_4
{
USHORT usPixelClock;
UCHAR ucDVOConfig;
UCHAR ucAction; //ATOM_ENABLE/ATOM_DISABLE/ATOM_HPD_INIT
UCHAR ucBitPerColor; //please refer to definition of PANEL_xBIT_PER_COLOR
UCHAR ucReseved[3];
}DVO_ENCODER_CONTROL_PARAMETERS_V1_4;
#define DVO_ENCODER_CONTROL_PS_ALLOCATION_V1_4 DVO_ENCODER_CONTROL_PARAMETERS_V1_4
//ucTableFormatRevision=1
//ucTableContentRevision=3 structure is not changed but usMisc add bit 1 as another input for
// bit1=0: non-coherent mode
@ -2165,7 +2205,7 @@ typedef struct _DVO_ENCODER_CONTROL_PARAMETERS_V3
#define SET_ASIC_VOLTAGE_MODE_SOURCE_B 0x4
#define SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE 0x0
#define SET_ASIC_VOLTAGE_MODE_GET_GPIOVAL 0x1
#define SET_ASIC_VOLTAGE_MODE_GET_GPIOVAL 0x1
#define SET_ASIC_VOLTAGE_MODE_GET_GPIOMASK 0x2
typedef struct _SET_VOLTAGE_PARAMETERS
@ -2200,15 +2240,20 @@ typedef struct _SET_VOLTAGE_PARAMETERS_V1_3
//SET_VOLTAGE_PARAMETERS_V3.ucVoltageMode
#define ATOM_SET_VOLTAGE 0 //Set voltage Level
#define ATOM_INIT_VOLTAGE_REGULATOR 3 //Init Regulator
#define ATOM_SET_VOLTAGE_PHASE 4 //Set Vregulator Phase
#define ATOM_GET_MAX_VOLTAGE 6 //Get Max Voltage, not used in SetVoltageTable v1.3
#define ATOM_GET_VOLTAGE_LEVEL 6 //Get Voltage level from vitual voltage ID
#define ATOM_SET_VOLTAGE_PHASE 4 //Set Vregulator Phase, only for SVID/PVID regulator
#define ATOM_GET_MAX_VOLTAGE 6 //Get Max Voltage, not used from SetVoltageTable v1.3
#define ATOM_GET_VOLTAGE_LEVEL 6 //Get Voltage level from vitual voltage ID, not used for SetVoltage v1.4
#define ATOM_GET_LEAKAGE_ID 8 //Get Leakage Voltage Id ( starting from SMU7x IP ), SetVoltage v1.4
// define vitual voltage id in usVoltageLevel
#define ATOM_VIRTUAL_VOLTAGE_ID0 0xff01
#define ATOM_VIRTUAL_VOLTAGE_ID1 0xff02
#define ATOM_VIRTUAL_VOLTAGE_ID2 0xff03
#define ATOM_VIRTUAL_VOLTAGE_ID3 0xff04
#define ATOM_VIRTUAL_VOLTAGE_ID4 0xff05
#define ATOM_VIRTUAL_VOLTAGE_ID5 0xff06
#define ATOM_VIRTUAL_VOLTAGE_ID6 0xff07
#define ATOM_VIRTUAL_VOLTAGE_ID7 0xff08
typedef struct _SET_VOLTAGE_PS_ALLOCATION
{
@ -2628,7 +2673,8 @@ typedef struct _ATOM_FIRMWARE_INFO_V2_2
ULONG ulFirmwareRevision;
ULONG ulDefaultEngineClock; //In 10Khz unit
ULONG ulDefaultMemoryClock; //In 10Khz unit
ULONG ulReserved[2];
ULONG ulSPLL_OutputFreq; //In 10Khz unit
ULONG ulGPUPLL_OutputFreq; //In 10Khz unit
ULONG ulReserved1; //Was ulMaxEngineClockPLL_Output; //In 10Khz unit*
ULONG ulReserved2; //Was ulMaxMemoryClockPLL_Output; //In 10Khz unit*
ULONG ulMaxPixelClockPLL_Output; //In 10Khz unit
@ -3813,6 +3859,12 @@ typedef struct _ATOM_GPIO_PIN_ASSIGNMENT
UCHAR ucGPIO_ID;
}ATOM_GPIO_PIN_ASSIGNMENT;
//ucGPIO_ID pre-define id for multiple usage
//from SMU7.x, if ucGPIO_ID=PP_AC_DC_SWITCH_GPIO_PINID in GPIO_LUTTable, AC/DC swithing feature is enable
#define PP_AC_DC_SWITCH_GPIO_PINID 60
//from SMU7.x, if ucGPIO_ID=VDDC_REGULATOR_VRHOT_GPIO_PINID in GPIO_LUTable, VRHot feature is enable
#define VDDC_VRHOT_GPIO_PINID 61
typedef struct _ATOM_GPIO_PIN_LUT
{
ATOM_COMMON_TABLE_HEADER sHeader;
@ -4074,17 +4126,19 @@ typedef struct _EXT_DISPLAY_PATH
//usCaps
#define EXT_DISPLAY_PATH_CAPS__HBR2_DISABLE 0x01
#define EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN 0x02
typedef struct _ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO
{
ATOM_COMMON_TABLE_HEADER sHeader;
UCHAR ucGuid [NUMBER_OF_UCHAR_FOR_GUID]; // a GUID is a 16 byte long string
EXT_DISPLAY_PATH sPath[MAX_NUMBER_OF_EXT_DISPLAY_PATH]; // total of fixed 7 entries.
UCHAR ucChecksum; // a simple Checksum of the sum of whole structure equal to 0x0.
UCHAR ucChecksum; // a simple Checksum of the sum of whole structure equal to 0x0.
UCHAR uc3DStereoPinId; // use for eDP panel
UCHAR ucRemoteDisplayConfig;
UCHAR uceDPToLVDSRxId;
UCHAR Reserved[4]; // for potential expansion
UCHAR ucFixDPVoltageSwing; // usCaps[1]=1, this indicate DP_LANE_SET value
UCHAR Reserved[3]; // for potential expansion
}ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO;
//Related definitions, all records are different but they have a commond header
@ -4416,6 +4470,13 @@ typedef struct _ATOM_VOLTAGE_CONTROL
#define VOLTAGE_CONTROL_ID_CHL822x 0x08
#define VOLTAGE_CONTROL_ID_VT1586M 0x09
#define VOLTAGE_CONTROL_ID_UP1637 0x0A
#define VOLTAGE_CONTROL_ID_CHL8214 0x0B
#define VOLTAGE_CONTROL_ID_UP1801 0x0C
#define VOLTAGE_CONTROL_ID_ST6788A 0x0D
#define VOLTAGE_CONTROL_ID_CHLIR3564SVI2 0x0E
#define VOLTAGE_CONTROL_ID_AD527x 0x0F
#define VOLTAGE_CONTROL_ID_NCP81022 0x10
#define VOLTAGE_CONTROL_ID_LTC2635 0x11
typedef struct _ATOM_VOLTAGE_OBJECT
{
@ -4458,6 +4519,15 @@ typedef struct _ATOM_VOLTAGE_OBJECT_HEADER_V3{
USHORT usSize; //Size of Object
}ATOM_VOLTAGE_OBJECT_HEADER_V3;
// ATOM_VOLTAGE_OBJECT_HEADER_V3.ucVoltageMode
#define VOLTAGE_OBJ_GPIO_LUT 0 //VOLTAGE and GPIO Lookup table ->ATOM_GPIO_VOLTAGE_OBJECT_V3
#define VOLTAGE_OBJ_VR_I2C_INIT_SEQ 3 //VOLTAGE REGULATOR INIT sequece through I2C -> ATOM_I2C_VOLTAGE_OBJECT_V3
#define VOLTAGE_OBJ_PHASE_LUT 4 //Set Vregulator Phase lookup table ->ATOM_GPIO_VOLTAGE_OBJECT_V3
#define VOLTAGE_OBJ_SVID2 7 //Indicate voltage control by SVID2 ->ATOM_SVID2_VOLTAGE_OBJECT_V3
#define VOLTAGE_OBJ_PWRBOOST_LEAKAGE_LUT 0x10 //Powerboost Voltage and LeakageId lookup table->ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
#define VOLTAGE_OBJ_HIGH_STATE_LEAKAGE_LUT 0x11 //High voltage state Voltage and LeakageId lookup table->ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
#define VOLTAGE_OBJ_HIGH1_STATE_LEAKAGE_LUT 0x12 //High1 voltage state Voltage and LeakageId lookup table->ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
typedef struct _VOLTAGE_LUT_ENTRY_V2
{
ULONG ulVoltageId; // The Voltage ID which is used to program GPIO register
@ -4473,7 +4543,7 @@ typedef struct _LEAKAGE_VOLTAGE_LUT_ENTRY_V2
typedef struct _ATOM_I2C_VOLTAGE_OBJECT_V3
{
ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader;
ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; // voltage mode = VOLTAGE_OBJ_VR_I2C_INIT_SEQ
UCHAR ucVoltageRegulatorId; //Indicate Voltage Regulator Id
UCHAR ucVoltageControlI2cLine;
UCHAR ucVoltageControlAddress;
@ -4484,7 +4554,7 @@ typedef struct _ATOM_I2C_VOLTAGE_OBJECT_V3
typedef struct _ATOM_GPIO_VOLTAGE_OBJECT_V3
{
ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader;
ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; // voltage mode = VOLTAGE_OBJ_GPIO_LUT or VOLTAGE_OBJ_PHASE_LUT
UCHAR ucVoltageGpioCntlId; // default is 0 which indicate control through CG VID mode
UCHAR ucGpioEntryNum; // indiate the entry numbers of Votlage/Gpio value Look up table
UCHAR ucPhaseDelay; // phase delay in unit of micro second
@ -4495,7 +4565,7 @@ typedef struct _ATOM_GPIO_VOLTAGE_OBJECT_V3
typedef struct _ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
{
ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader;
ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; // voltage mode = 0x10/0x11/0x12
UCHAR ucLeakageCntlId; // default is 0
UCHAR ucLeakageEntryNum; // indicate the entry number of LeakageId/Voltage Lut table
UCHAR ucReserved[2];
@ -4503,10 +4573,26 @@ typedef struct _ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
LEAKAGE_VOLTAGE_LUT_ENTRY_V2 asLeakageIdLut[1];
}ATOM_LEAKAGE_VOLTAGE_OBJECT_V3;
typedef struct _ATOM_SVID2_VOLTAGE_OBJECT_V3
{
ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader; // voltage mode = VOLTAGE_OBJ_SVID2
// 14:7 – PSI0_VID
// 6 – PSI0_EN
// 5 – PSI1
// 4:2 – load line slope trim.
// 1:0 – offset trim,
USHORT usLoadLine_PSI;
// GPU GPIO pin Id to SVID2 regulator VRHot pin. possible value 0~31. 0 means GPIO0, 31 means GPIO31
UCHAR ucReserved[2];
ULONG ulReserved;
}ATOM_SVID2_VOLTAGE_OBJECT_V3;
typedef union _ATOM_VOLTAGE_OBJECT_V3{
ATOM_GPIO_VOLTAGE_OBJECT_V3 asGpioVoltageObj;
ATOM_I2C_VOLTAGE_OBJECT_V3 asI2cVoltageObj;
ATOM_LEAKAGE_VOLTAGE_OBJECT_V3 asLeakageObj;
ATOM_SVID2_VOLTAGE_OBJECT_V3 asSVID2Obj;
}ATOM_VOLTAGE_OBJECT_V3;
typedef struct _ATOM_VOLTAGE_OBJECT_INFO_V3_1
@ -4536,6 +4622,21 @@ typedef struct _ATOM_ASIC_PROFILING_INFO
ATOM_ASIC_PROFILE_VOLTAGE asVoltage;
}ATOM_ASIC_PROFILING_INFO;
typedef struct _ATOM_ASIC_PROFILING_INFO_V2_1
{
ATOM_COMMON_TABLE_HEADER asHeader;
UCHAR ucLeakageBinNum; // indicate the entry number of LeakageId/Voltage Lut table
USHORT usLeakageBinArrayOffset; // offset of USHORT Leakage Bin list array ( from lower LeakageId to higher)
UCHAR ucElbVDDC_Num;
USHORT usElbVDDC_IdArrayOffset; // offset of USHORT virtual VDDC voltage id ( 0xff01~0xff08 )
USHORT usElbVDDC_LevelArrayOffset; // offset of 2 dimension voltage level USHORT array
UCHAR ucElbVDDCI_Num;
USHORT usElbVDDCI_IdArrayOffset; // offset of USHORT virtual VDDCI voltage id ( 0xff01~0xff08 )
USHORT usElbVDDCI_LevelArrayOffset; // offset of 2 dimension voltage level USHORT array
}ATOM_ASIC_PROFILING_INFO_V2_1;
typedef struct _ATOM_POWER_SOURCE_OBJECT
{
UCHAR ucPwrSrcId; // Power source
@ -4652,6 +4753,8 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V6
#define SYS_INFO_LVDSMISC__888_BPC 0x04
#define SYS_INFO_LVDSMISC__OVERRIDE_EN 0x08
#define SYS_INFO_LVDSMISC__BLON_ACTIVE_LOW 0x10
// new since Trinity
#define SYS_INFO_LVDSMISC__TRAVIS_LVDS_VOL_OVERRIDE_EN 0x20
// not used any more
#define SYS_INFO_LVDSMISC__VSYNC_ACTIVE_LOW 0x04
@ -4752,6 +4855,29 @@ typedef struct _ATOM_FUSION_SYSTEM_INFO_V1
ATOM_INTEGRATED_SYSTEM_INFO_V6 sIntegratedSysInfo;
ULONG ulPowerplayTable[128];
}ATOM_FUSION_SYSTEM_INFO_V1;
typedef struct _ATOM_TDP_CONFIG_BITS
{
#if ATOM_BIG_ENDIAN
ULONG uReserved:2;
ULONG uTDP_Value:14; // Original TDP value in tens of milli watts
ULONG uCTDP_Value:14; // Override value in tens of milli watts
ULONG uCTDP_Enable:2; // = (uCTDP_Value > uTDP_Value? 2: (uCTDP_Value < uTDP_Value))
#else
ULONG uCTDP_Enable:2; // = (uCTDP_Value > uTDP_Value? 2: (uCTDP_Value < uTDP_Value))
ULONG uCTDP_Value:14; // Override value in tens of milli watts
ULONG uTDP_Value:14; // Original TDP value in tens of milli watts
ULONG uReserved:2;
#endif
}ATOM_TDP_CONFIG_BITS;
typedef union _ATOM_TDP_CONFIG
{
ATOM_TDP_CONFIG_BITS TDP_config;
ULONG TDP_config_all;
}ATOM_TDP_CONFIG;
/**********************************************************************************************************************
ATOM_FUSION_SYSTEM_INFO_V1 Description
sIntegratedSysInfo: refer to ATOM_INTEGRATED_SYSTEM_INFO_V6 definition.
@ -4784,7 +4910,8 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7
UCHAR ucMemoryType;
UCHAR ucUMAChannelNumber;
UCHAR strVBIOSMsg[40];
ULONG ulReserved[20];
ATOM_TDP_CONFIG asTdpConfig;
ULONG ulReserved[19];
ATOM_AVAILABLE_SCLK_LIST sAvail_SCLK[5];
ULONG ulGMCRestoreResetTime;
ULONG ulMinimumNClk;
@ -4809,7 +4936,7 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7
USHORT GnbTdpLimit;
USHORT usMaxLVDSPclkFreqInSingleLink;
UCHAR ucLvdsMisc;
UCHAR ucLVDSReserved;
UCHAR ucTravisLVDSVolAdjust;
UCHAR ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
UCHAR ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
UCHAR ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
@ -4817,7 +4944,7 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7
UCHAR ucLVDSOffToOnDelay_in4Ms;
UCHAR ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
UCHAR ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
UCHAR ucLVDSReserved1;
UCHAR ucMinAllowedBL_Level;
ULONG ulLCDBitDepthControlVal;
ULONG ulNbpStateMemclkFreq[4];
USHORT usNBP2Voltage;
@ -4846,6 +4973,7 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7
#define SYS_INFO_GPUCAPS__TMDSHDMI_COHERENT_SINGLEPLL_MODE 0x01
#define SYS_INFO_GPUCAPS__DP_SINGLEPLL_MODE 0x02
#define SYS_INFO_GPUCAPS__DISABLE_AUX_MODE_DETECT 0x08
#define SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS 0x10
/**********************************************************************************************************************
ATOM_INTEGRATED_SYSTEM_INFO_V1_7 Description
@ -4945,6 +5073,9 @@ ucLVDSMisc: [bit0] LVDS 888bit panel mode =0: LVDS 888 pan
[bit2] LVDS 888bit per color mode =0: 666 bit per color =1:888 bit per color
[bit3] LVDS parameter override enable =0: ucLvdsMisc parameter are not used =1: ucLvdsMisc parameter should be used
[bit4] Polarity of signal sent to digital BLON output pin. =0: not inverted(active high) =1: inverted ( active low )
[bit5] Travid LVDS output voltage override enable, when =1, use ucTravisLVDSVolAdjust value to overwrite Traivs register LVDS_CTRL_4
ucTravisLVDSVolAdjust When ucLVDSMisc[5]=1,it means platform SBIOS want to overwrite TravisLVDSVoltage. Then VBIOS will use ucTravisLVDSVolAdjust
value to program Travis register LVDS_CTRL_4
ucLVDSPwrOnSeqDIGONtoDE_in4Ms: LVDS power up sequence time in unit of 4ms, time delay from DIGON signal active to data enable signal active( DE ).
=0 mean use VBIOS default which is 8 ( 32ms ). The LVDS power up sequence is as following: DIGON->DE->VARY_BL->BLON.
This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable.
@ -4964,18 +5095,241 @@ ucLVDSOffToOnDelay_in4Ms: LVDS power down sequence time in unit of 4ms.
=0 means to use VBIOS default delay which is 125 ( 500ms ).
This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable.
ucLVDSPwrOnVARY_BLtoBLON_in4Ms: LVDS power up sequence time in unit of 4ms. Time delay from VARY_BL signal on to DLON signal active.
ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms:
LVDS power up sequence time in unit of 4ms. Time delay from VARY_BL signal on to DLON signal active.
=0 means to use VBIOS default delay which is 0 ( 0ms ).
This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable.
ucLVDSPwrOffBLONtoVARY_BL_in4Ms: LVDS power down sequence time in unit of 4ms. Time delay from BLON signal off to VARY_BL signal off.
ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms:
LVDS power down sequence time in unit of 4ms. Time delay from BLON signal off to VARY_BL signal off.
=0 means to use VBIOS default delay which is 0 ( 0ms ).
This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable.
ucMinAllowedBL_Level: Lowest LCD backlight PWM level. This is customer platform specific parameters. By default it is 0.
ulNbpStateMemclkFreq[4]: system memory clock frequncey in unit of 10Khz in different NB pstate.
**********************************************************************************************************************/
// this IntegrateSystemInfoTable is used for Kaveri & Kabini APU
typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8
{
ATOM_COMMON_TABLE_HEADER sHeader;
ULONG ulBootUpEngineClock;
ULONG ulDentistVCOFreq;
ULONG ulBootUpUMAClock;
ATOM_CLK_VOLT_CAPABILITY sDISPCLK_Voltage[4];
ULONG ulBootUpReqDisplayVector;
ULONG ulVBIOSMisc;
ULONG ulGPUCapInfo;
ULONG ulDISP_CLK2Freq;
USHORT usRequestedPWMFreqInHz;
UCHAR ucHtcTmpLmt;
UCHAR ucHtcHystLmt;
ULONG ulReserved2;
ULONG ulSystemConfig;
ULONG ulCPUCapInfo;
ULONG ulReserved3;
USHORT usGPUReservedSysMemSize;
USHORT usExtDispConnInfoOffset;
USHORT usPanelRefreshRateRange;
UCHAR ucMemoryType;
UCHAR ucUMAChannelNumber;
UCHAR strVBIOSMsg[40];
ATOM_TDP_CONFIG asTdpConfig;
ULONG ulReserved[19];
ATOM_AVAILABLE_SCLK_LIST sAvail_SCLK[5];
ULONG ulGMCRestoreResetTime;
ULONG ulReserved4;
ULONG ulIdleNClk;
ULONG ulDDR_DLL_PowerUpTime;
ULONG ulDDR_PLL_PowerUpTime;
USHORT usPCIEClkSSPercentage;
USHORT usPCIEClkSSType;
USHORT usLvdsSSPercentage;
USHORT usLvdsSSpreadRateIn10Hz;
USHORT usHDMISSPercentage;
USHORT usHDMISSpreadRateIn10Hz;
USHORT usDVISSPercentage;
USHORT usDVISSpreadRateIn10Hz;
ULONG ulGPUReservedSysMemBaseAddrLo;
ULONG ulGPUReservedSysMemBaseAddrHi;
ULONG ulReserved5[3];
USHORT usMaxLVDSPclkFreqInSingleLink;
UCHAR ucLvdsMisc;
UCHAR ucTravisLVDSVolAdjust;
UCHAR ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
UCHAR ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
UCHAR ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
UCHAR ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
UCHAR ucLVDSOffToOnDelay_in4Ms;
UCHAR ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
UCHAR ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
UCHAR ucMinAllowedBL_Level;
ULONG ulLCDBitDepthControlVal;
ULONG ulNbpStateMemclkFreq[4];
ULONG ulReserved6;
ULONG ulNbpStateNClkFreq[4];
USHORT usNBPStateVoltage[4];
USHORT usBootUpNBVoltage;
USHORT usReserved2;
ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO sExtDispConnInfo;
}ATOM_INTEGRATED_SYSTEM_INFO_V1_8;
/**********************************************************************************************************************
ATOM_INTEGRATED_SYSTEM_INFO_V1_8 Description
ulBootUpEngineClock: VBIOS bootup Engine clock frequency, in 10kHz unit. if it is equal 0, then VBIOS use pre-defined bootup engine clock
ulDentistVCOFreq: Dentist VCO clock in 10kHz unit.
ulBootUpUMAClock: System memory boot up clock frequency in 10Khz unit.
sDISPCLK_Voltage: Report Display clock frequency requirement on GNB voltage(up to 4 voltage levels).
ulBootUpReqDisplayVector: VBIOS boot up display IDs, following are supported devices in Trinity projects:
ATOM_DEVICE_CRT1_SUPPORT 0x0001
ATOM_DEVICE_DFP1_SUPPORT 0x0008
ATOM_DEVICE_DFP6_SUPPORT 0x0040
ATOM_DEVICE_DFP2_SUPPORT 0x0080
ATOM_DEVICE_DFP3_SUPPORT 0x0200
ATOM_DEVICE_DFP4_SUPPORT 0x0400
ATOM_DEVICE_DFP5_SUPPORT 0x0800
ATOM_DEVICE_LCD1_SUPPORT 0x0002
ulVBIOSMisc: Miscellenous flags for VBIOS requirement and interface
bit[0]=0: INT15 callback function Get LCD EDID ( ax=4e08, bl=1b ) is not supported by SBIOS.
=1: INT15 callback function Get LCD EDID ( ax=4e08, bl=1b ) is supported by SBIOS.
bit[1]=0: INT15 callback function Get boot display( ax=4e08, bl=01h) is not supported by SBIOS
=1: INT15 callback function Get boot display( ax=4e08, bl=01h) is supported by SBIOS
bit[2]=0: INT15 callback function Get panel Expansion ( ax=4e08, bl=02h) is not supported by SBIOS
=1: INT15 callback function Get panel Expansion ( ax=4e08, bl=02h) is supported by SBIOS
bit[3]=0: VBIOS fast boot is disable
=1: VBIOS fast boot is enable. ( VBIOS skip display device detection in every set mode if LCD panel is connect and LID is open)
ulGPUCapInfo: bit[0~2]= Reserved
bit[3]=0: Enable AUX HW mode detection logic
=1: Disable AUX HW mode detection logic
bit[4]=0: Disable DFS bypass feature
=1: Enable DFS bypass feature
usRequestedPWMFreqInHz: When it's set to 0x0 by SBIOS: the LCD BackLight is not controlled by GPU(SW).
Any attempt to change BL using VBIOS function or enable VariBri from PP table is not effective since ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==0;
When it's set to a non-zero frequency, the BackLight is controlled by GPU (SW) in one of two ways below:
1. SW uses the GPU BL PWM output to control the BL, in chis case, this non-zero frequency determines what freq GPU should use;
VBIOS will set up proper PWM frequency and ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1,as the result,
Changing BL using VBIOS function is functional in both driver and non-driver present environment;
and enabling VariBri under the driver environment from PP table is optional.
2. SW uses other means to control BL (like DPCD),this non-zero frequency serves as a flag only indicating
that BL control from GPU is expected.
VBIOS will NOT set up PWM frequency but make ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1
Changing BL using VBIOS function could be functional in both driver and non-driver present environment,but
it's per platform
and enabling VariBri under the driver environment from PP table is optional.
ucHtcTmpLmt: Refer to D18F3x64 bit[22:16], HtcTmpLmt. Threshold on value to enter HTC_active state.
ucHtcHystLmt: Refer to D18F3x64 bit[27:24], HtcHystLmt.
To calculate threshold off value to exit HTC_active state, which is Threshold on vlaue minus ucHtcHystLmt.
ulSystemConfig: Bit[0]=0: PCIE Power Gating Disabled
=1: PCIE Power Gating Enabled
Bit[1]=0: DDR-DLL shut-down feature disabled.
1: DDR-DLL shut-down feature enabled.
Bit[2]=0: DDR-PLL Power down feature disabled.
1: DDR-PLL Power down feature enabled.
Bit[3]=0: GNB DPM is disabled
=1: GNB DPM is enabled
ulCPUCapInfo: TBD
usExtDispConnInfoOffset: Offset to sExtDispConnInfo inside the structure
usPanelRefreshRateRange: Bit vector for LCD supported refresh rate range. If DRR is requestd by the platform, at least two bits need to be set
to indicate a range.
SUPPORTED_LCD_REFRESHRATE_30Hz 0x0004
SUPPORTED_LCD_REFRESHRATE_40Hz 0x0008
SUPPORTED_LCD_REFRESHRATE_50Hz 0x0010
SUPPORTED_LCD_REFRESHRATE_60Hz 0x0020
ucMemoryType: [3:0]=1:DDR1;=2:DDR2;=3:DDR3;=5:GDDR5; [7:4] is reserved.
ucUMAChannelNumber: System memory channel numbers.
strVBIOSMsg[40]: VBIOS boot up customized message string
sAvail_SCLK[5]: Arrays to provide availabe list of SLCK and corresponding voltage, order from low to high
ulGMCRestoreResetTime: GMC power restore and GMC reset time to calculate data reconnection latency. Unit in ns.
ulIdleNClk: NCLK speed while memory runs in self-refresh state, used to calculate self-refresh latency. Unit in 10kHz.
ulDDR_DLL_PowerUpTime: DDR PHY DLL power up time. Unit in ns.
ulDDR_PLL_PowerUpTime: DDR PHY PLL power up time. Unit in ns.
usPCIEClkSSPercentage: PCIE Clock Spread Spectrum Percentage in unit 0.01%; 100 mean 1%.
usPCIEClkSSType: PCIE Clock Spread Spectrum Type. 0 for Down spread(default); 1 for Center spread.
usLvdsSSPercentage: LVDS panel ( not include eDP ) Spread Spectrum Percentage in unit of 0.01%, =0, use VBIOS default setting.
usLvdsSSpreadRateIn10Hz: LVDS panel ( not include eDP ) Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting.
usHDMISSPercentage: HDMI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting.
usHDMISSpreadRateIn10Hz: HDMI Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting.
usDVISSPercentage: DVI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting.
usDVISSpreadRateIn10Hz: DVI Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting.
usGPUReservedSysMemSize: Reserved system memory size for ACP engine in APU GNB, units in MB. 0/2/4MB based on CMOS options, current default could be 0MB. KV only, not on KB.
ulGPUReservedSysMemBaseAddrLo: Low 32 bits base address to the reserved system memory.
ulGPUReservedSysMemBaseAddrHi: High 32 bits base address to the reserved system memory.
usMaxLVDSPclkFreqInSingleLink: Max pixel clock LVDS panel single link, if=0 means VBIOS use default threhold, right now it is 85Mhz
ucLVDSMisc: [bit0] LVDS 888bit panel mode =0: LVDS 888 panel in LDI mode, =1: LVDS 888 panel in FPDI mode
[bit1] LVDS panel lower and upper link mapping =0: lower link and upper link not swap, =1: lower link and upper link are swapped
[bit2] LVDS 888bit per color mode =0: 666 bit per color =1:888 bit per color
[bit3] LVDS parameter override enable =0: ucLvdsMisc parameter are not used =1: ucLvdsMisc parameter should be used
[bit4] Polarity of signal sent to digital BLON output pin. =0: not inverted(active high) =1: inverted ( active low )
[bit5] Travid LVDS output voltage override enable, when =1, use ucTravisLVDSVolAdjust value to overwrite Traivs register LVDS_CTRL_4
ucTravisLVDSVolAdjust When ucLVDSMisc[5]=1,it means platform SBIOS want to overwrite TravisLVDSVoltage. Then VBIOS will use ucTravisLVDSVolAdjust
value to program Travis register LVDS_CTRL_4
ucLVDSPwrOnSeqDIGONtoDE_in4Ms:
LVDS power up sequence time in unit of 4ms, time delay from DIGON signal active to data enable signal active( DE ).
=0 mean use VBIOS default which is 8 ( 32ms ). The LVDS power up sequence is as following: DIGON->DE->VARY_BL->BLON.
This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable.
ucLVDSPwrOnDEtoVARY_BL_in4Ms:
LVDS power up sequence time in unit of 4ms., time delay from DE( data enable ) active to Vary Brightness enable signal active( VARY_BL ).
=0 mean use VBIOS default which is 90 ( 360ms ). The LVDS power up sequence is as following: DIGON->DE->VARY_BL->BLON.
This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable.
ucLVDSPwrOffVARY_BLtoDE_in4Ms:
LVDS power down sequence time in unit of 4ms, time delay from data enable ( DE ) signal off to LCDVCC (DIGON) off.
=0 mean use VBIOS default delay which is 8 ( 32ms ). The LVDS power down sequence is as following: BLON->VARY_BL->DE->DIGON
This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable.
ucLVDSPwrOffDEtoDIGON_in4Ms:
LVDS power down sequence time in unit of 4ms, time delay from vary brightness enable signal( VARY_BL) off to data enable ( DE ) signal off.
=0 mean use VBIOS default which is 90 ( 360ms ). The LVDS power down sequence is as following: BLON->VARY_BL->DE->DIGON
This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable.
ucLVDSOffToOnDelay_in4Ms:
LVDS power down sequence time in unit of 4ms. Time delay from DIGON signal off to DIGON signal active.
=0 means to use VBIOS default delay which is 125 ( 500ms ).
This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable.
ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms:
LVDS power up sequence time in unit of 4ms. Time delay from VARY_BL signal on to DLON signal active.
=0 means to use VBIOS default delay which is 0 ( 0ms ).
This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable.
ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms:
LVDS power down sequence time in unit of 4ms. Time delay from BLON signal off to VARY_BL signal off.
=0 means to use VBIOS default delay which is 0 ( 0ms ).
This parameter is used by VBIOS only. VBIOS will patch LVDS_InfoTable.
ucMinAllowedBL_Level: Lowest LCD backlight PWM level. This is customer platform specific parameters. By default it is 0.
ulLCDBitDepthControlVal: GPU display control encoder bit dither control setting, used to program register mmFMT_BIT_DEPTH_CONTROL
ulNbpStateMemclkFreq[4]: system memory clock frequncey in unit of 10Khz in different NB P-State(P0, P1, P2 & P3).
ulNbpStateNClkFreq[4]: NB P-State NClk frequency in different NB P-State
usNBPStateVoltage[4]: NB P-State (P0/P1 & P2/P3) voltage; NBP3 refers to lowes voltage
usBootUpNBVoltage: NB P-State voltage during boot up before driver loaded
sExtDispConnInfo: Display connector information table provided to VBIOS
**********************************************************************************************************************/
// this Table is used for Kaveri/Kabini APU
typedef struct _ATOM_FUSION_SYSTEM_INFO_V2
{
ATOM_INTEGRATED_SYSTEM_INFO_V1_8 sIntegratedSysInfo; // refer to ATOM_INTEGRATED_SYSTEM_INFO_V1_8 definition
ULONG ulPowerplayTable[128]; // Update comments here to link new powerplay table definition structure
}ATOM_FUSION_SYSTEM_INFO_V2;
/**************************************************************************/
// This portion is only used when ext thermal chip or engine/memory clock SS chip is populated on a design
//Memory SS Info Table
@ -5026,22 +5380,24 @@ typedef struct _ATOM_ASIC_SS_ASSIGNMENT
//Define ucClockIndication, SW uses the IDs below to search if the SS is required/enabled on a clock branch/signal type.
//SS is not required or enabled if a match is not found.
#define ASIC_INTERNAL_MEMORY_SS 1
#define ASIC_INTERNAL_ENGINE_SS 2
#define ASIC_INTERNAL_UVD_SS 3
#define ASIC_INTERNAL_SS_ON_TMDS 4
#define ASIC_INTERNAL_SS_ON_HDMI 5
#define ASIC_INTERNAL_SS_ON_LVDS 6
#define ASIC_INTERNAL_SS_ON_DP 7
#define ASIC_INTERNAL_SS_ON_DCPLL 8
#define ASIC_EXTERNAL_SS_ON_DP_CLOCK 9
#define ASIC_INTERNAL_VCE_SS 10
#define ASIC_INTERNAL_MEMORY_SS 1
#define ASIC_INTERNAL_ENGINE_SS 2
#define ASIC_INTERNAL_UVD_SS 3
#define ASIC_INTERNAL_SS_ON_TMDS 4
#define ASIC_INTERNAL_SS_ON_HDMI 5
#define ASIC_INTERNAL_SS_ON_LVDS 6
#define ASIC_INTERNAL_SS_ON_DP 7
#define ASIC_INTERNAL_SS_ON_DCPLL 8
#define ASIC_EXTERNAL_SS_ON_DP_CLOCK 9
#define ASIC_INTERNAL_VCE_SS 10
#define ASIC_INTERNAL_GPUPLL_SS 11
typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V2
{
ULONG ulTargetClockRange; //For mem/engine/uvd, Clock Out frequence (VCO ), in unit of 10Khz
//For TMDS/HDMI/LVDS, it is pixel clock , for DP, it is link clock ( 27000 or 16200 )
USHORT usSpreadSpectrumPercentage; //in unit of 0.01%
USHORT usSpreadSpectrumPercentage; //in unit of 0.01% or 0.001%, decided by ucSpreadSpectrumMode bit4
USHORT usSpreadRateIn10Hz; //in unit of 10Hz, modulation freq
UCHAR ucClockIndication; //Indicate which clock source needs SS
UCHAR ucSpreadSpectrumMode; //Bit0=0 Down Spread,=1 Center Spread, bit1=0: internal SS bit1=1: external SS
@ -5079,6 +5435,11 @@ typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V3
UCHAR ucReserved[2];
}ATOM_ASIC_SS_ASSIGNMENT_V3;
//ATOM_ASIC_SS_ASSIGNMENT_V3.ucSpreadSpectrumMode
#define SS_MODE_V3_CENTRE_SPREAD_MASK 0x01
#define SS_MODE_V3_EXTERNAL_SS_MASK 0x02
#define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10
typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V3
{
ATOM_COMMON_TABLE_HEADER sHeader;
@ -5719,6 +6080,7 @@ typedef struct _INDIRECT_IO_ACCESS
#define INDIRECT_IO_PCIE 3
#define INDIRECT_IO_PCIEP 4
#define INDIRECT_IO_NBMISC 5
#define INDIRECT_IO_SMU 5
#define INDIRECT_IO_PLL_READ INDIRECT_IO_PLL | INDIRECT_READ
#define INDIRECT_IO_PLL_WRITE INDIRECT_IO_PLL | INDIRECT_WRITE
@ -5730,6 +6092,8 @@ typedef struct _INDIRECT_IO_ACCESS
#define INDIRECT_IO_PCIEP_WRITE INDIRECT_IO_PCIEP | INDIRECT_WRITE
#define INDIRECT_IO_NBMISC_READ INDIRECT_IO_NBMISC | INDIRECT_READ
#define INDIRECT_IO_NBMISC_WRITE INDIRECT_IO_NBMISC | INDIRECT_WRITE
#define INDIRECT_IO_SMU_READ INDIRECT_IO_SMU | INDIRECT_READ
#define INDIRECT_IO_SMU_WRITE INDIRECT_IO_SMU | INDIRECT_WRITE
typedef struct _ATOM_OEM_INFO
{
@ -5875,6 +6239,7 @@ typedef struct _ATOM_MC_INIT_PARAM_TABLE
#define _64Mx32 0x43
#define _128Mx8 0x51
#define _128Mx16 0x52
#define _128Mx32 0x53
#define _256Mx8 0x61
#define _256Mx16 0x62
@ -5893,6 +6258,8 @@ typedef struct _ATOM_MC_INIT_PARAM_TABLE
#define PROMOS MOSEL
#define KRETON INFINEON
#define ELIXIR NANYA
#define MEZZA ELPIDA
/////////////Support for GDDR5 MC uCode to reside in upper 64K of ROM/////////////
@ -6625,6 +6992,10 @@ typedef struct _ATOM_DISP_OUT_INFO_V3
ASIC_TRANSMITTER_INFO_V2 asTransmitterInfo[1]; // for alligment only
}ATOM_DISP_OUT_INFO_V3;
//ucDispCaps
#define DISPLAY_CAPS__DP_PCLK_FROM_PPLL 0x01
#define DISPLAY_CAPS__FORCE_DISPDEV_CONNECTED 0x02
typedef enum CORE_REF_CLK_SOURCE{
CLOCK_SRC_XTALIN=0,
CLOCK_SRC_XO_IN=1,
@ -6829,6 +7200,17 @@ typedef struct _DIG_TRANSMITTER_INFO_HEADER_V3_1{
USHORT usPhyPllSettingOffset; // offset of CLOCK_CONDITION_SETTING_ENTRY* with Phy Pll Settings
}DIG_TRANSMITTER_INFO_HEADER_V3_1;
typedef struct _DIG_TRANSMITTER_INFO_HEADER_V3_2{
ATOM_COMMON_TABLE_HEADER sHeader;
USHORT usDPVsPreEmphSettingOffset; // offset of PHY_ANALOG_SETTING_INFO * with DP Voltage Swing and Pre-Emphasis for each Link clock
USHORT usPhyAnalogRegListOffset; // offset of CLOCK_CONDITION_REGESTER_INFO* with None-DP mode Analog Setting's register Info
USHORT usPhyAnalogSettingOffset; // offset of CLOCK_CONDITION_SETTING_ENTRY* with None-DP mode Analog Setting for each link clock range
USHORT usPhyPllRegListOffset; // offset of CLOCK_CONDITION_REGESTER_INFO* with Phy Pll register Info
USHORT usPhyPllSettingOffset; // offset of CLOCK_CONDITION_SETTING_ENTRY* with Phy Pll Settings
USHORT usDPSSRegListOffset; // offset of CLOCK_CONDITION_REGESTER_INFO* with Phy SS Pll register Info
USHORT usDPSSSettingOffset; // offset of CLOCK_CONDITION_SETTING_ENTRY* with Phy SS Pll Settings
}DIG_TRANSMITTER_INFO_HEADER_V3_2;
typedef struct _CLOCK_CONDITION_REGESTER_INFO{
USHORT usRegisterIndex;
UCHAR ucStartBit;
@ -6852,12 +7234,24 @@ typedef struct _PHY_CONDITION_REG_VAL{
ULONG ulRegVal;
}PHY_CONDITION_REG_VAL;
typedef struct _PHY_CONDITION_REG_VAL_V2{
ULONG ulCondition;
UCHAR ucCondition2;
ULONG ulRegVal;
}PHY_CONDITION_REG_VAL_V2;
typedef struct _PHY_CONDITION_REG_INFO{
USHORT usRegIndex;
USHORT usSize;
PHY_CONDITION_REG_VAL asRegVal[1];
}PHY_CONDITION_REG_INFO;
typedef struct _PHY_CONDITION_REG_INFO_V2{
USHORT usRegIndex;
USHORT usSize;
PHY_CONDITION_REG_VAL_V2 asRegVal[1];
}PHY_CONDITION_REG_INFO_V2;
typedef struct _PHY_ANALOG_SETTING_INFO{
UCHAR ucEncodeMode;
UCHAR ucPhySel;
@ -6865,6 +7259,25 @@ typedef struct _PHY_ANALOG_SETTING_INFO{
PHY_CONDITION_REG_INFO asAnalogSetting[1];
}PHY_ANALOG_SETTING_INFO;
typedef struct _PHY_ANALOG_SETTING_INFO_V2{
UCHAR ucEncodeMode;
UCHAR ucPhySel;
USHORT usSize;
PHY_CONDITION_REG_INFO_V2 asAnalogSetting[1];
}PHY_ANALOG_SETTING_INFO_V2;
typedef struct _GFX_HAVESTING_PARAMETERS {
UCHAR ucGfxBlkId; //GFX blk id to be harvested, like CU, RB or PRIM
UCHAR ucReserved; //reserved
UCHAR ucActiveUnitNumPerSH; //requested active CU/RB/PRIM number per shader array
UCHAR ucMaxUnitNumPerSH; //max CU/RB/PRIM number per shader array
} GFX_HAVESTING_PARAMETERS;
//ucGfxBlkId
#define GFX_HARVESTING_CU_ID 0
#define GFX_HARVESTING_RB_ID 1
#define GFX_HARVESTING_PRIM_ID 2
/****************************************************************************/
//Portion VI: Definitinos for vbios MC scratch registers that driver used
/****************************************************************************/
@ -6875,8 +7288,17 @@ typedef struct _PHY_ANALOG_SETTING_INFO{
#define MC_MISC0__MEMORY_TYPE__GDDR3 0x30000000
#define MC_MISC0__MEMORY_TYPE__GDDR4 0x40000000
#define MC_MISC0__MEMORY_TYPE__GDDR5 0x50000000
#define MC_MISC0__MEMORY_TYPE__HBM 0x60000000
#define MC_MISC0__MEMORY_TYPE__DDR3 0xB0000000
#define ATOM_MEM_TYPE_DDR_STRING "DDR"
#define ATOM_MEM_TYPE_DDR2_STRING "DDR2"
#define ATOM_MEM_TYPE_GDDR3_STRING "GDDR3"
#define ATOM_MEM_TYPE_GDDR4_STRING "GDDR4"
#define ATOM_MEM_TYPE_GDDR5_STRING "GDDR5"
#define ATOM_MEM_TYPE_HBM_STRING "HBM"
#define ATOM_MEM_TYPE_DDR3_STRING "DDR3"
/****************************************************************************/
//Portion VI: Definitinos being oboselete
/****************************************************************************/
@ -7274,6 +7696,7 @@ typedef struct _ATOM_PPLIB_THERMALCONTROLLER
#define ATOM_PP_THERMALCONTROLLER_NISLANDS 15
#define ATOM_PP_THERMALCONTROLLER_SISLANDS 16
#define ATOM_PP_THERMALCONTROLLER_LM96163 17
#define ATOM_PP_THERMALCONTROLLER_CISLANDS 18
// Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal.
// We probably should reserve the bit 0x80 for this use.
@ -7316,6 +7739,8 @@ typedef struct _ATOM_PPLIB_EXTENDEDHEADER
// Add extra system parameters here, always adjust size to include all fields.
USHORT usVCETableOffset; //points to ATOM_PPLIB_VCE_Table
USHORT usUVDTableOffset; //points to ATOM_PPLIB_UVD_Table
USHORT usSAMUTableOffset; //points to ATOM_PPLIB_SAMU_Table
USHORT usPPMTableOffset; //points to ATOM_PPLIB_PPM_Table
} ATOM_PPLIB_EXTENDEDHEADER;
//// ATOM_PPLIB_POWERPLAYTABLE::ulPlatformCaps
@ -7337,7 +7762,10 @@ typedef struct _ATOM_PPLIB_EXTENDEDHEADER
#define ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL 0x8000 // Does the driver control VDDCI independently from VDDC.
#define ATOM_PP_PLATFORM_CAP_REGULATOR_HOT 0x00010000 // Enable the 'regulator hot' feature.
#define ATOM_PP_PLATFORM_CAP_BACO 0x00020000 // Does the driver supports BACO state.
#define ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE 0x00040000 // Does the driver supports new CAC voltage table.
#define ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY 0x00080000 // Does the driver supports revert GPIO5 polarity.
#define ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17 0x00100000 // Does the driver supports thermal2GPIO17.
#define ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE 0x00200000 // Does the driver supports VR HOT GPIO Configurable.
typedef struct _ATOM_PPLIB_POWERPLAYTABLE
{
@ -7398,7 +7826,7 @@ typedef struct _ATOM_PPLIB_POWERPLAYTABLE4
USHORT usVddcDependencyOnMCLKOffset;
USHORT usMaxClockVoltageOnDCOffset;
USHORT usVddcPhaseShedLimitsTableOffset; // Points to ATOM_PPLIB_PhaseSheddingLimits_Table
USHORT usReserved;
USHORT usMvddDependencyOnMCLKOffset;
} ATOM_PPLIB_POWERPLAYTABLE4, *LPATOM_PPLIB_POWERPLAYTABLE4;
typedef struct _ATOM_PPLIB_POWERPLAYTABLE5
@ -7563,6 +7991,17 @@ typedef struct _ATOM_PPLIB_SI_CLOCK_INFO
} ATOM_PPLIB_SI_CLOCK_INFO;
typedef struct _ATOM_PPLIB_CI_CLOCK_INFO
{
USHORT usEngineClockLow;
UCHAR ucEngineClockHigh;
USHORT usMemoryClockLow;
UCHAR ucMemoryClockHigh;
UCHAR ucPCIEGen;
USHORT usPCIELane;
} ATOM_PPLIB_CI_CLOCK_INFO;
typedef struct _ATOM_PPLIB_RS780_CLOCK_INFO
@ -7680,8 +8119,8 @@ typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Table
typedef struct _ATOM_PPLIB_CAC_Leakage_Record
{
USHORT usVddc; // We use this field for the "fake" standardized VDDC for power calculations
ULONG ulLeakageValue;
USHORT usVddc; // We use this field for the "fake" standardized VDDC for power calculations; For CI and newer, we use this as the real VDDC value.
ULONG ulLeakageValue; // For CI and newer we use this as the "fake" standar VDDC value.
}ATOM_PPLIB_CAC_Leakage_Record;
typedef struct _ATOM_PPLIB_CAC_Leakage_Table
@ -7796,6 +8235,42 @@ typedef struct _ATOM_PPLIB_UVD_Table
// ATOM_PPLIB_UVD_State_Table states;
}ATOM_PPLIB_UVD_Table;
typedef struct _ATOM_PPLIB_SAMClk_Voltage_Limit_Record
{
USHORT usVoltage;
USHORT usSAMClockLow;
UCHAR ucSAMClockHigh;
}ATOM_PPLIB_SAMClk_Voltage_Limit_Record;
typedef struct _ATOM_PPLIB_SAMClk_Voltage_Limit_Table{
UCHAR numEntries;
ATOM_PPLIB_SAMClk_Voltage_Limit_Record entries[1];
}ATOM_PPLIB_SAMClk_Voltage_Limit_Table;
typedef struct _ATOM_PPLIB_SAMU_Table
{
UCHAR revid;
ATOM_PPLIB_SAMClk_Voltage_Limit_Table limits;
}ATOM_PPLIB_SAMU_Table;
#define ATOM_PPM_A_A 1
#define ATOM_PPM_A_I 2
typedef struct _ATOM_PPLIB_PPM_Table
{
UCHAR ucRevId;
UCHAR ucPpmDesign; //A+I or A+A
USHORT usCpuCoreNumber;
ULONG ulPlatformTDP;
ULONG ulSmallACPlatformTDP;
ULONG ulPlatformTDC;
ULONG ulSmallACPlatformTDC;
ULONG ulApuTDP;
ULONG ulDGpuTDP;
ULONG ulDGpuUlvPower;
ULONG ulTjmax;
} ATOM_PPLIB_PPM_Table;
/**************************************************************************/

View File

@ -555,7 +555,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
if (rdev->family < CHIP_RV770)
radeon_crtc->pll_flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
/* use frac fb div on APUs */
if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev) || ASIC_IS_DCE8(rdev))
radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
/* use frac fb div on RS780/RS880 */
if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
@ -743,7 +743,7 @@ static void atombios_crtc_set_disp_eng_pll(struct radeon_device *rdev,
* SetPixelClock provides the dividers
*/
args.v6.ulDispEngClkFreq = cpu_to_le32(dispclk);
if (ASIC_IS_DCE61(rdev))
if (ASIC_IS_DCE61(rdev) || ASIC_IS_DCE8(rdev))
args.v6.ucPpll = ATOM_EXT_PLL1;
else if (ASIC_IS_DCE6(rdev))
args.v6.ucPpll = ATOM_PPLL0;
@ -1143,7 +1143,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
}
if (tiling_flags & RADEON_TILING_MACRO) {
if (rdev->family >= CHIP_TAHITI)
if (rdev->family >= CHIP_BONAIRE)
tmp = rdev->config.cik.tile_config;
else if (rdev->family >= CHIP_TAHITI)
tmp = rdev->config.si.tile_config;
else if (rdev->family >= CHIP_CAYMAN)
tmp = rdev->config.cayman.tile_config;
@ -1170,11 +1172,29 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw);
fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh);
fb_format |= EVERGREEN_GRPH_MACRO_TILE_ASPECT(mtaspect);
if (rdev->family >= CHIP_BONAIRE) {
/* XXX need to know more about the surface tiling mode */
fb_format |= CIK_GRPH_MICRO_TILE_MODE(CIK_DISPLAY_MICRO_TILING);
}
} else if (tiling_flags & RADEON_TILING_MICRO)
fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
if ((rdev->family == CHIP_TAHITI) ||
(rdev->family == CHIP_PITCAIRN))
if (rdev->family >= CHIP_BONAIRE) {
u32 num_pipe_configs = rdev->config.cik.max_tile_pipes;
u32 num_rb = rdev->config.cik.max_backends_per_se;
if (num_pipe_configs > 8)
num_pipe_configs = 8;
if (num_pipe_configs == 8)
fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P8_32x32_16x16);
else if (num_pipe_configs == 4) {
if (num_rb == 4)
fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_16x16);
else if (num_rb < 4)
fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_8x16);
} else if (num_pipe_configs == 2)
fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P2);
} else if ((rdev->family == CHIP_TAHITI) ||
(rdev->family == CHIP_PITCAIRN))
fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16);
else if (rdev->family == CHIP_VERDE)
fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16);
@ -1224,8 +1244,12 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
target_fb->height);
if (rdev->family >= CHIP_BONAIRE)
WREG32(CIK_LB_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
target_fb->height);
else
WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
target_fb->height);
x &= ~3;
y &= ~1;
WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,
@ -1597,6 +1621,12 @@ static int radeon_get_shared_nondp_ppll(struct drm_crtc *crtc)
*
* Asic specific PLL information
*
* DCE 8.x
* KB/KV
* - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP)
* CI
* - PPLL0, PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC
*
* DCE 6.1
* - PPLL2 is only available to UNIPHYA (both DP and non-DP)
* - PPLL0, PPLL1 are available for UNIPHYB/C/D/E/F (both DP and non-DP)
@ -1623,7 +1653,47 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
u32 pll_in_use;
int pll;
if (ASIC_IS_DCE61(rdev)) {
if (ASIC_IS_DCE8(rdev)) {
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
if (rdev->clock.dp_extclk)
/* skip PPLL programming if using ext clock */
return ATOM_PPLL_INVALID;
else {
/* use the same PPLL for all DP monitors */
pll = radeon_get_shared_dp_ppll(crtc);
if (pll != ATOM_PPLL_INVALID)
return pll;
}
} else {
/* use the same PPLL for all monitors with the same clock */
pll = radeon_get_shared_nondp_ppll(crtc);
if (pll != ATOM_PPLL_INVALID)
return pll;
}
/* otherwise, pick one of the plls */
if ((rdev->family == CHIP_KAVERI) ||
(rdev->family == CHIP_KABINI)) {
/* KB/KV has PPLL1 and PPLL2 */
pll_in_use = radeon_get_pll_use_mask(crtc);
if (!(pll_in_use & (1 << ATOM_PPLL2)))
return ATOM_PPLL2;
if (!(pll_in_use & (1 << ATOM_PPLL1)))
return ATOM_PPLL1;
DRM_ERROR("unable to allocate a PPLL\n");
return ATOM_PPLL_INVALID;
} else {
/* CI has PPLL0, PPLL1, and PPLL2 */
pll_in_use = radeon_get_pll_use_mask(crtc);
if (!(pll_in_use & (1 << ATOM_PPLL2)))
return ATOM_PPLL2;
if (!(pll_in_use & (1 << ATOM_PPLL1)))
return ATOM_PPLL1;
if (!(pll_in_use & (1 << ATOM_PPLL0)))
return ATOM_PPLL0;
DRM_ERROR("unable to allocate a PPLL\n");
return ATOM_PPLL_INVALID;
}
} else if (ASIC_IS_DCE61(rdev)) {
struct radeon_encoder_atom_dig *dig =
radeon_encoder->enc_priv;
@ -1861,7 +1931,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
break;
case ATOM_PPLL0:
/* disable the ppll */
if (ASIC_IS_DCE61(rdev))
if ((rdev->family == CHIP_ARUBA) || (rdev->family == CHIP_BONAIRE))
atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss);
break;

View File

@ -186,6 +186,13 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
u8 backlight_level;
char bl_name[16];
/* Mac laptops with multiple GPUs use the gmux driver for backlight
* so don't register a backlight device
*/
if ((rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
(rdev->pdev->device == 0x6741))
return;
if (!radeon_encoder->enc_priv)
return;
@ -296,6 +303,7 @@ static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
return true;
default:
return false;
@ -479,11 +487,11 @@ static u8 radeon_atom_get_bpc(struct drm_encoder *encoder)
}
}
union dvo_encoder_control {
ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds;
DVO_ENCODER_CONTROL_PS_ALLOCATION dvo;
DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3;
DVO_ENCODER_CONTROL_PS_ALLOCATION_V1_4 dvo_v4;
};
void
@ -533,6 +541,13 @@ atombios_dvo_setup(struct drm_encoder *encoder, int action)
args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
args.dvo_v3.ucDVOConfig = 0; /* XXX */
break;
case 4:
/* DCE8 */
args.dvo_v4.ucAction = action;
args.dvo_v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
args.dvo_v4.ucDVOConfig = 0; /* XXX */
args.dvo_v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
break;
default:
DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
break;
@ -915,10 +930,14 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo
args.v4.ucLaneNum = 4;
if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)) {
if (dp_clock == 270000)
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
else if (dp_clock == 540000)
if (dp_clock == 540000)
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ;
else if (dp_clock == 324000)
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_3_24GHZ;
else if (dp_clock == 270000)
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ;
else
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ;
}
args.v4.acConfig.ucDigSel = dig->dig_encoder;
args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
@ -1012,6 +1031,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
break;
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
@ -1271,6 +1291,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
else
args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE;
break;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYG;
break;
}
if (is_dp)
args.v5.ucLaneNum = dp_lane_count;
@ -1735,6 +1758,7 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
radeon_atom_encoder_dpms_dig(encoder, mode);
break;
@ -1872,6 +1896,7 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
dig = radeon_encoder->enc_priv;
switch (dig->dig_encoder) {
@ -1893,6 +1918,9 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
case 5:
args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
break;
case 6:
args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID;
break;
}
break;
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
@ -1955,7 +1983,13 @@ atombios_apply_encoder_quirks(struct drm_encoder *encoder,
/* set scaler clears this on some chips */
if (ASIC_IS_AVIVO(rdev) &&
(!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) {
if (ASIC_IS_DCE4(rdev)) {
if (ASIC_IS_DCE8(rdev)) {
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset,
CIK_INTERLEAVE_EN);
else
WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
} else if (ASIC_IS_DCE4(rdev)) {
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
EVERGREEN_INTERLEAVE_EN);
@ -2002,6 +2036,9 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
else
return 4;
break;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
return 6;
break;
}
} else if (ASIC_IS_DCE4(rdev)) {
/* DCE4/5 */
@ -2086,6 +2123,7 @@ radeon_atom_encoder_init(struct radeon_device *rdev)
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
break;
@ -2130,6 +2168,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
/* handled in dpms */
break;
@ -2395,6 +2434,7 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
/* handled in dpms */
break;
@ -2626,6 +2666,7 @@ radeon_add_atom_encoder(struct drm_device *dev,
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
radeon_encoder->rmx_type = RMX_FULL;
drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
/*
* Copyright 2011 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.
*
*/
#ifndef __BTC_DPM_H__
#define __BTC_DPM_H__
#define BTC_RLP_UVD_DFLT 20
#define BTC_RMP_UVD_DFLT 50
#define BTC_LHP_UVD_DFLT 50
#define BTC_LMP_UVD_DFLT 20
#define BARTS_MGCGCGTSSMCTRL_DFLT 0x81944000
#define TURKS_MGCGCGTSSMCTRL_DFLT 0x6e944000
#define CAICOS_MGCGCGTSSMCTRL_DFLT 0x46944040
#define BTC_CGULVPARAMETER_DFLT 0x00040035
#define BTC_CGULVCONTROL_DFLT 0x00001450
extern u32 btc_valid_sclk[40];
void btc_read_arb_registers(struct radeon_device *rdev);
void btc_program_mgcg_hw_sequence(struct radeon_device *rdev,
const u32 *sequence, u32 count);
void btc_skip_blacklist_clocks(struct radeon_device *rdev,
const u32 max_sclk, const u32 max_mclk,
u32 *sclk, u32 *mclk);
void btc_adjust_clock_combinations(struct radeon_device *rdev,
const struct radeon_clock_and_voltage_limits *max_limits,
struct rv7xx_pl *pl);
void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
u32 clock, u16 max_voltage, u16 *voltage);
void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
u16 max_vddc, u16 max_vddci,
u16 *vddc, u16 *vddci);
bool btc_dpm_enabled(struct radeon_device *rdev);
int btc_reset_to_default(struct radeon_device *rdev);
void btc_notify_uvd_to_smc(struct radeon_device *rdev,
struct radeon_ps *radeon_new_state);
#endif

View File

@ -0,0 +1,181 @@
/*
* Copyright 2010 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: Alex Deucher
*/
#ifndef _BTCD_H_
#define _BTCD_H_
/* pm registers */
#define GENERAL_PWRMGT 0x63c
# define GLOBAL_PWRMGT_EN (1 << 0)
# define STATIC_PM_EN (1 << 1)
# define THERMAL_PROTECTION_DIS (1 << 2)
# define THERMAL_PROTECTION_TYPE (1 << 3)
# define ENABLE_GEN2PCIE (1 << 4)
# define ENABLE_GEN2XSP (1 << 5)
# define SW_SMIO_INDEX(x) ((x) << 6)
# define SW_SMIO_INDEX_MASK (3 << 6)
# define SW_SMIO_INDEX_SHIFT 6
# define LOW_VOLT_D2_ACPI (1 << 8)
# define LOW_VOLT_D3_ACPI (1 << 9)
# define VOLT_PWRMGT_EN (1 << 10)
# define BACKBIAS_PAD_EN (1 << 18)
# define BACKBIAS_VALUE (1 << 19)
# define DYN_SPREAD_SPECTRUM_EN (1 << 23)
# define AC_DC_SW (1 << 24)
#define CG_BIF_REQ_AND_RSP 0x7f4
#define CG_CLIENT_REQ(x) ((x) << 0)
#define CG_CLIENT_REQ_MASK (0xff << 0)
#define CG_CLIENT_REQ_SHIFT 0
#define CG_CLIENT_RESP(x) ((x) << 8)
#define CG_CLIENT_RESP_MASK (0xff << 8)
#define CG_CLIENT_RESP_SHIFT 8
#define CLIENT_CG_REQ(x) ((x) << 16)
#define CLIENT_CG_REQ_MASK (0xff << 16)
#define CLIENT_CG_REQ_SHIFT 16
#define CLIENT_CG_RESP(x) ((x) << 24)
#define CLIENT_CG_RESP_MASK (0xff << 24)
#define CLIENT_CG_RESP_SHIFT 24
#define SCLK_PSKIP_CNTL 0x8c0
#define PSKIP_ON_ALLOW_STOP_HI(x) ((x) << 16)
#define PSKIP_ON_ALLOW_STOP_HI_MASK (0xff << 16)
#define PSKIP_ON_ALLOW_STOP_HI_SHIFT 16
#define CG_ULV_CONTROL 0x8c8
#define CG_ULV_PARAMETER 0x8cc
#define MC_ARB_DRAM_TIMING 0x2774
#define MC_ARB_DRAM_TIMING2 0x2778
#define MC_ARB_RFSH_RATE 0x27b0
#define POWERMODE0(x) ((x) << 0)
#define POWERMODE0_MASK (0xff << 0)
#define POWERMODE0_SHIFT 0
#define POWERMODE1(x) ((x) << 8)
#define POWERMODE1_MASK (0xff << 8)
#define POWERMODE1_SHIFT 8
#define POWERMODE2(x) ((x) << 16)
#define POWERMODE2_MASK (0xff << 16)
#define POWERMODE2_SHIFT 16
#define POWERMODE3(x) ((x) << 24)
#define POWERMODE3_MASK (0xff << 24)
#define POWERMODE3_SHIFT 24
#define MC_ARB_BURST_TIME 0x2808
#define STATE0(x) ((x) << 0)
#define STATE0_MASK (0x1f << 0)
#define STATE0_SHIFT 0
#define STATE1(x) ((x) << 5)
#define STATE1_MASK (0x1f << 5)
#define STATE1_SHIFT 5
#define STATE2(x) ((x) << 10)
#define STATE2_MASK (0x1f << 10)
#define STATE2_SHIFT 10
#define STATE3(x) ((x) << 15)
#define STATE3_MASK (0x1f << 15)
#define STATE3_SHIFT 15
#define MC_SEQ_RAS_TIMING 0x28a0
#define MC_SEQ_CAS_TIMING 0x28a4
#define MC_SEQ_MISC_TIMING 0x28a8
#define MC_SEQ_MISC_TIMING2 0x28ac
#define MC_SEQ_RD_CTL_D0 0x28b4
#define MC_SEQ_RD_CTL_D1 0x28b8
#define MC_SEQ_WR_CTL_D0 0x28bc
#define MC_SEQ_WR_CTL_D1 0x28c0
#define MC_PMG_AUTO_CFG 0x28d4
#define MC_SEQ_STATUS_M 0x29f4
# define PMG_PWRSTATE (1 << 16)
#define MC_SEQ_MISC0 0x2a00
#define MC_SEQ_MISC0_GDDR5_SHIFT 28
#define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000
#define MC_SEQ_MISC0_GDDR5_VALUE 5
#define MC_SEQ_MISC1 0x2a04
#define MC_SEQ_RESERVE_M 0x2a08
#define MC_PMG_CMD_EMRS 0x2a0c
#define MC_SEQ_MISC3 0x2a2c
#define MC_SEQ_MISC5 0x2a54
#define MC_SEQ_MISC6 0x2a58
#define MC_SEQ_MISC7 0x2a64
#define MC_SEQ_CG 0x2a68
#define CG_SEQ_REQ(x) ((x) << 0)
#define CG_SEQ_REQ_MASK (0xff << 0)
#define CG_SEQ_REQ_SHIFT 0
#define CG_SEQ_RESP(x) ((x) << 8)
#define CG_SEQ_RESP_MASK (0xff << 8)
#define CG_SEQ_RESP_SHIFT 8
#define SEQ_CG_REQ(x) ((x) << 16)
#define SEQ_CG_REQ_MASK (0xff << 16)
#define SEQ_CG_REQ_SHIFT 16
#define SEQ_CG_RESP(x) ((x) << 24)
#define SEQ_CG_RESP_MASK (0xff << 24)
#define SEQ_CG_RESP_SHIFT 24
#define MC_SEQ_RAS_TIMING_LP 0x2a6c
#define MC_SEQ_CAS_TIMING_LP 0x2a70
#define MC_SEQ_MISC_TIMING_LP 0x2a74
#define MC_SEQ_MISC_TIMING2_LP 0x2a78
#define MC_SEQ_WR_CTL_D0_LP 0x2a7c
#define MC_SEQ_WR_CTL_D1_LP 0x2a80
#define MC_SEQ_PMG_CMD_EMRS_LP 0x2a84
#define MC_SEQ_PMG_CMD_MRS_LP 0x2a88
#define MC_PMG_CMD_MRS 0x2aac
#define MC_SEQ_RD_CTL_D0_LP 0x2b1c
#define MC_SEQ_RD_CTL_D1_LP 0x2b20
#define MC_PMG_CMD_MRS1 0x2b44
#define MC_SEQ_PMG_CMD_MRS1_LP 0x2b48
#define LB_SYNC_RESET_SEL 0x6b28
#define LB_SYNC_RESET_SEL_MASK (3 << 0)
#define LB_SYNC_RESET_SEL_SHIFT 0
/* PCIE link stuff */
#define PCIE_LC_SPEED_CNTL 0xa4 /* PCIE_P */
# define LC_GEN2_EN_STRAP (1 << 0)
# define LC_TARGET_LINK_SPEED_OVERRIDE_EN (1 << 1)
# define LC_FORCE_EN_HW_SPEED_CHANGE (1 << 5)
# define LC_FORCE_DIS_HW_SPEED_CHANGE (1 << 6)
# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK (0x3 << 8)
# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT 3
# define LC_CURRENT_DATA_RATE (1 << 11)
# define LC_HW_VOLTAGE_IF_CONTROL(x) ((x) << 12)
# define LC_HW_VOLTAGE_IF_CONTROL_MASK (3 << 12)
# define LC_HW_VOLTAGE_IF_CONTROL_SHIFT 12
# define LC_VOLTAGE_TIMER_SEL_MASK (0xf << 14)
# define LC_CLR_FAILED_SPD_CHANGE_CNT (1 << 21)
# define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 23)
# define LC_OTHER_SIDE_SUPPORTS_GEN2 (1 << 24)
#endif

6987
drivers/gpu/drm/radeon/cik.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,246 @@
/*
* Copyright 2012 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 (including the next
* paragraph) 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) AND/OR ITS SUPPLIERS 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:
* Alex Deucher <alexander.deucher@amd.com>
*/
#include <linux/types.h>
#include <linux/bug.h>
#include <linux/kernel.h>
const u32 cik_default_state[] =
{
0xc0066900,
0x00000000,
0x00000060, /* DB_RENDER_CONTROL */
0x00000000, /* DB_COUNT_CONTROL */
0x00000000, /* DB_DEPTH_VIEW */
0x0000002a, /* DB_RENDER_OVERRIDE */
0x00000000, /* DB_RENDER_OVERRIDE2 */
0x00000000, /* DB_HTILE_DATA_BASE */
0xc0046900,
0x00000008,
0x00000000, /* DB_DEPTH_BOUNDS_MIN */
0x00000000, /* DB_DEPTH_BOUNDS_MAX */
0x00000000, /* DB_STENCIL_CLEAR */
0x00000000, /* DB_DEPTH_CLEAR */
0xc0036900,
0x0000000f,
0x00000000, /* DB_DEPTH_INFO */
0x00000000, /* DB_Z_INFO */
0x00000000, /* DB_STENCIL_INFO */
0xc0016900,
0x00000080,
0x00000000, /* PA_SC_WINDOW_OFFSET */
0xc00d6900,
0x00000083,
0x0000ffff, /* PA_SC_CLIPRECT_RULE */
0x00000000, /* PA_SC_CLIPRECT_0_TL */
0x20002000, /* PA_SC_CLIPRECT_0_BR */
0x00000000,
0x20002000,
0x00000000,
0x20002000,
0x00000000,
0x20002000,
0xaaaaaaaa, /* PA_SC_EDGERULE */
0x00000000, /* PA_SU_HARDWARE_SCREEN_OFFSET */
0x0000000f, /* CB_TARGET_MASK */
0x0000000f, /* CB_SHADER_MASK */
0xc0226900,
0x00000094,
0x80000000, /* PA_SC_VPORT_SCISSOR_0_TL */
0x20002000, /* PA_SC_VPORT_SCISSOR_0_BR */
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x80000000,
0x20002000,
0x00000000, /* PA_SC_VPORT_ZMIN_0 */
0x3f800000, /* PA_SC_VPORT_ZMAX_0 */
0xc0046900,
0x00000100,
0xffffffff, /* VGT_MAX_VTX_INDX */
0x00000000, /* VGT_MIN_VTX_INDX */
0x00000000, /* VGT_INDX_OFFSET */
0x00000000, /* VGT_MULTI_PRIM_IB_RESET_INDX */
0xc0046900,
0x00000105,
0x00000000, /* CB_BLEND_RED */
0x00000000, /* CB_BLEND_GREEN */
0x00000000, /* CB_BLEND_BLUE */
0x00000000, /* CB_BLEND_ALPHA */
0xc0016900,
0x000001e0,
0x00000000, /* CB_BLEND0_CONTROL */
0xc00c6900,
0x00000200,
0x00000000, /* DB_DEPTH_CONTROL */
0x00000000, /* DB_EQAA */
0x00cc0010, /* CB_COLOR_CONTROL */
0x00000210, /* DB_SHADER_CONTROL */
0x00010000, /* PA_CL_CLIP_CNTL */
0x00000004, /* PA_SU_SC_MODE_CNTL */
0x00000100, /* PA_CL_VTE_CNTL */
0x00000000, /* PA_CL_VS_OUT_CNTL */
0x00000000, /* PA_CL_NANINF_CNTL */
0x00000000, /* PA_SU_LINE_STIPPLE_CNTL */
0x00000000, /* PA_SU_LINE_STIPPLE_SCALE */
0x00000000, /* PA_SU_PRIM_FILTER_CNTL */
0xc0116900,
0x00000280,
0x00000000, /* PA_SU_POINT_SIZE */
0x00000000, /* PA_SU_POINT_MINMAX */
0x00000008, /* PA_SU_LINE_CNTL */
0x00000000, /* PA_SC_LINE_STIPPLE */
0x00000000, /* VGT_OUTPUT_PATH_CNTL */
0x00000000, /* VGT_HOS_CNTL */
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000, /* VGT_GS_MODE */
0xc0026900,
0x00000292,
0x00000000, /* PA_SC_MODE_CNTL_0 */
0x00000000, /* PA_SC_MODE_CNTL_1 */
0xc0016900,
0x000002a1,
0x00000000, /* VGT_PRIMITIVEID_EN */
0xc0016900,
0x000002a5,
0x00000000, /* VGT_MULTI_PRIM_IB_RESET_EN */
0xc0026900,
0x000002a8,
0x00000000, /* VGT_INSTANCE_STEP_RATE_0 */
0x00000000,
0xc0026900,
0x000002ad,
0x00000000, /* VGT_REUSE_OFF */
0x00000000,
0xc0016900,
0x000002d5,
0x00000000, /* VGT_SHADER_STAGES_EN */
0xc0016900,
0x000002dc,
0x0000aa00, /* DB_ALPHA_TO_MASK */
0xc0066900,
0x000002de,
0x00000000, /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0xc0026900,
0x000002e5,
0x00000000, /* VGT_STRMOUT_CONFIG */
0x00000000,
0xc01b6900,
0x000002f5,
0x76543210, /* PA_SC_CENTROID_PRIORITY_0 */
0xfedcba98, /* PA_SC_CENTROID_PRIORITY_1 */
0x00000000, /* PA_SC_LINE_CNTL */
0x00000000, /* PA_SC_AA_CONFIG */
0x00000005, /* PA_SU_VTX_CNTL */
0x3f800000, /* PA_CL_GB_VERT_CLIP_ADJ */
0x3f800000, /* PA_CL_GB_VERT_DISC_ADJ */
0x3f800000, /* PA_CL_GB_HORZ_CLIP_ADJ */
0x3f800000, /* PA_CL_GB_HORZ_DISC_ADJ */
0x00000000, /* PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0xffffffff, /* PA_SC_AA_MASK_X0Y0_X1Y0 */
0xffffffff,
0xc0026900,
0x00000316,
0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */
0x00000010, /* */
};
const u32 cik_default_size = ARRAY_SIZE(cik_default_state);

View File

@ -0,0 +1,32 @@
/*
* Copyright 2012 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 (including the next
* paragraph) 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) AND/OR ITS SUPPLIERS 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.
*
*/
#ifndef CIK_BLIT_SHADERS_H
#define CIK_BLIT_SHADERS_H
extern const u32 cik_default_state[];
extern const u32 cik_default_size;
#endif

View File

@ -0,0 +1,147 @@
/*
* Copyright 2012 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: Alex Deucher
*/
#ifndef __CIK_REG_H__
#define __CIK_REG_H__
#define CIK_DC_GPIO_HPD_MASK 0x65b0
#define CIK_DC_GPIO_HPD_A 0x65b4
#define CIK_DC_GPIO_HPD_EN 0x65b8
#define CIK_DC_GPIO_HPD_Y 0x65bc
#define CIK_GRPH_CONTROL 0x6804
# define CIK_GRPH_DEPTH(x) (((x) & 0x3) << 0)
# define CIK_GRPH_DEPTH_8BPP 0
# define CIK_GRPH_DEPTH_16BPP 1
# define CIK_GRPH_DEPTH_32BPP 2
# define CIK_GRPH_NUM_BANKS(x) (((x) & 0x3) << 2)
# define CIK_ADDR_SURF_2_BANK 0
# define CIK_ADDR_SURF_4_BANK 1
# define CIK_ADDR_SURF_8_BANK 2
# define CIK_ADDR_SURF_16_BANK 3
# define CIK_GRPH_Z(x) (((x) & 0x3) << 4)
# define CIK_GRPH_BANK_WIDTH(x) (((x) & 0x3) << 6)
# define CIK_ADDR_SURF_BANK_WIDTH_1 0
# define CIK_ADDR_SURF_BANK_WIDTH_2 1
# define CIK_ADDR_SURF_BANK_WIDTH_4 2
# define CIK_ADDR_SURF_BANK_WIDTH_8 3
# define CIK_GRPH_FORMAT(x) (((x) & 0x7) << 8)
/* 8 BPP */
# define CIK_GRPH_FORMAT_INDEXED 0
/* 16 BPP */
# define CIK_GRPH_FORMAT_ARGB1555 0
# define CIK_GRPH_FORMAT_ARGB565 1
# define CIK_GRPH_FORMAT_ARGB4444 2
# define CIK_GRPH_FORMAT_AI88 3
# define CIK_GRPH_FORMAT_MONO16 4
# define CIK_GRPH_FORMAT_BGRA5551 5
/* 32 BPP */
# define CIK_GRPH_FORMAT_ARGB8888 0
# define CIK_GRPH_FORMAT_ARGB2101010 1
# define CIK_GRPH_FORMAT_32BPP_DIG 2
# define CIK_GRPH_FORMAT_8B_ARGB2101010 3
# define CIK_GRPH_FORMAT_BGRA1010102 4
# define CIK_GRPH_FORMAT_8B_BGRA1010102 5
# define CIK_GRPH_FORMAT_RGB111110 6
# define CIK_GRPH_FORMAT_BGR101111 7
# define CIK_GRPH_BANK_HEIGHT(x) (((x) & 0x3) << 11)
# define CIK_ADDR_SURF_BANK_HEIGHT_1 0
# define CIK_ADDR_SURF_BANK_HEIGHT_2 1
# define CIK_ADDR_SURF_BANK_HEIGHT_4 2
# define CIK_ADDR_SURF_BANK_HEIGHT_8 3
# define CIK_GRPH_TILE_SPLIT(x) (((x) & 0x7) << 13)
# define CIK_ADDR_SURF_TILE_SPLIT_64B 0
# define CIK_ADDR_SURF_TILE_SPLIT_128B 1
# define CIK_ADDR_SURF_TILE_SPLIT_256B 2
# define CIK_ADDR_SURF_TILE_SPLIT_512B 3
# define CIK_ADDR_SURF_TILE_SPLIT_1KB 4
# define CIK_ADDR_SURF_TILE_SPLIT_2KB 5
# define CIK_ADDR_SURF_TILE_SPLIT_4KB 6
# define CIK_GRPH_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 18)
# define CIK_ADDR_SURF_MACRO_TILE_ASPECT_1 0
# define CIK_ADDR_SURF_MACRO_TILE_ASPECT_2 1
# define CIK_ADDR_SURF_MACRO_TILE_ASPECT_4 2
# define CIK_ADDR_SURF_MACRO_TILE_ASPECT_8 3
# define CIK_GRPH_ARRAY_MODE(x) (((x) & 0x7) << 20)
# define CIK_GRPH_ARRAY_LINEAR_GENERAL 0
# define CIK_GRPH_ARRAY_LINEAR_ALIGNED 1
# define CIK_GRPH_ARRAY_1D_TILED_THIN1 2
# define CIK_GRPH_ARRAY_2D_TILED_THIN1 4
# define CIK_GRPH_PIPE_CONFIG(x) (((x) & 0x1f) << 24)
# define CIK_ADDR_SURF_P2 0
# define CIK_ADDR_SURF_P4_8x16 4
# define CIK_ADDR_SURF_P4_16x16 5
# define CIK_ADDR_SURF_P4_16x32 6
# define CIK_ADDR_SURF_P4_32x32 7
# define CIK_ADDR_SURF_P8_16x16_8x16 8
# define CIK_ADDR_SURF_P8_16x32_8x16 9
# define CIK_ADDR_SURF_P8_32x32_8x16 10
# define CIK_ADDR_SURF_P8_16x32_16x16 11
# define CIK_ADDR_SURF_P8_32x32_16x16 12
# define CIK_ADDR_SURF_P8_32x32_16x32 13
# define CIK_ADDR_SURF_P8_32x64_32x32 14
# define CIK_GRPH_MICRO_TILE_MODE(x) (((x) & 0x7) << 29)
# define CIK_DISPLAY_MICRO_TILING 0
# define CIK_THIN_MICRO_TILING 1
# define CIK_DEPTH_MICRO_TILING 2
# define CIK_ROTATED_MICRO_TILING 4
/* CUR blocks at 0x6998, 0x7598, 0x10198, 0x10d98, 0x11998, 0x12598 */
#define CIK_CUR_CONTROL 0x6998
# define CIK_CURSOR_EN (1 << 0)
# define CIK_CURSOR_MODE(x) (((x) & 0x3) << 8)
# define CIK_CURSOR_MONO 0
# define CIK_CURSOR_24_1 1
# define CIK_CURSOR_24_8_PRE_MULT 2
# define CIK_CURSOR_24_8_UNPRE_MULT 3
# define CIK_CURSOR_2X_MAGNIFY (1 << 16)
# define CIK_CURSOR_FORCE_MC_ON (1 << 20)
# define CIK_CURSOR_URGENT_CONTROL(x) (((x) & 0x7) << 24)
# define CIK_CURSOR_URGENT_ALWAYS 0
# define CIK_CURSOR_URGENT_1_8 1
# define CIK_CURSOR_URGENT_1_4 2
# define CIK_CURSOR_URGENT_3_8 3
# define CIK_CURSOR_URGENT_1_2 4
#define CIK_CUR_SURFACE_ADDRESS 0x699c
# define CIK_CUR_SURFACE_ADDRESS_MASK 0xfffff000
#define CIK_CUR_SIZE 0x69a0
#define CIK_CUR_SURFACE_ADDRESS_HIGH 0x69a4
#define CIK_CUR_POSITION 0x69a8
#define CIK_CUR_HOT_SPOT 0x69ac
#define CIK_CUR_COLOR1 0x69b0
#define CIK_CUR_COLOR2 0x69b4
#define CIK_CUR_UPDATE 0x69b8
# define CIK_CURSOR_UPDATE_PENDING (1 << 0)
# define CIK_CURSOR_UPDATE_TAKEN (1 << 1)
# define CIK_CURSOR_UPDATE_LOCK (1 << 16)
# define CIK_CURSOR_DISABLE_MULTIPLE_UPDATE (1 << 24)
#define CIK_ALPHA_CONTROL 0x6af0
# define CIK_CURSOR_ALPHA_BLND_ENA (1 << 1)
#define CIK_LB_DATA_FORMAT 0x6b00
# define CIK_INTERLEAVE_EN (1 << 3)
#define CIK_LB_DESKTOP_HEIGHT 0x6b0c
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
/*
* Copyright 2012 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.
*
*/
#ifndef CLEARSTATE_DEFS_H
#define CLEARSTATE_DEFS_H
enum section_id {
SECT_NONE,
SECT_CONTEXT,
SECT_CLEAR,
SECT_CTRLCONST
};
struct cs_extent_def {
const unsigned int *extent;
const unsigned int reg_index;
const unsigned int reg_count;
};
struct cs_section_def {
const struct cs_extent_def *section;
const enum section_id id;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,941 @@
/*
* Copyright 2013 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.
*
*/
static const u32 si_SECT_CONTEXT_def_1[] =
{
0x00000000, // DB_RENDER_CONTROL
0x00000000, // DB_COUNT_CONTROL
0x00000000, // DB_DEPTH_VIEW
0x00000000, // DB_RENDER_OVERRIDE
0x00000000, // DB_RENDER_OVERRIDE2
0x00000000, // DB_HTILE_DATA_BASE
0, // HOLE
0, // HOLE
0x00000000, // DB_DEPTH_BOUNDS_MIN
0x00000000, // DB_DEPTH_BOUNDS_MAX
0x00000000, // DB_STENCIL_CLEAR
0x00000000, // DB_DEPTH_CLEAR
0x00000000, // PA_SC_SCREEN_SCISSOR_TL
0x40004000, // PA_SC_SCREEN_SCISSOR_BR
0, // HOLE
0x00000000, // DB_DEPTH_INFO
0x00000000, // DB_Z_INFO
0x00000000, // DB_STENCIL_INFO
0x00000000, // DB_Z_READ_BASE
0x00000000, // DB_STENCIL_READ_BASE
0x00000000, // DB_Z_WRITE_BASE
0x00000000, // DB_STENCIL_WRITE_BASE
0x00000000, // DB_DEPTH_SIZE
0x00000000, // DB_DEPTH_SLICE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0x00000000, // TA_BC_BASE_ADDR
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0x00000000, // COHER_DEST_BASE_2
0x00000000, // COHER_DEST_BASE_3
0x00000000, // PA_SC_WINDOW_OFFSET
0x80000000, // PA_SC_WINDOW_SCISSOR_TL
0x40004000, // PA_SC_WINDOW_SCISSOR_BR
0x0000ffff, // PA_SC_CLIPRECT_RULE
0x00000000, // PA_SC_CLIPRECT_0_TL
0x40004000, // PA_SC_CLIPRECT_0_BR
0x00000000, // PA_SC_CLIPRECT_1_TL
0x40004000, // PA_SC_CLIPRECT_1_BR
0x00000000, // PA_SC_CLIPRECT_2_TL
0x40004000, // PA_SC_CLIPRECT_2_BR
0x00000000, // PA_SC_CLIPRECT_3_TL
0x40004000, // PA_SC_CLIPRECT_3_BR
0xaa99aaaa, // PA_SC_EDGERULE
0x00000000, // PA_SU_HARDWARE_SCREEN_OFFSET
0xffffffff, // CB_TARGET_MASK
0xffffffff, // CB_SHADER_MASK
0x80000000, // PA_SC_GENERIC_SCISSOR_TL
0x40004000, // PA_SC_GENERIC_SCISSOR_BR
0x00000000, // COHER_DEST_BASE_0
0x00000000, // COHER_DEST_BASE_1
0x80000000, // PA_SC_VPORT_SCISSOR_0_TL
0x40004000, // PA_SC_VPORT_SCISSOR_0_BR
0x80000000, // PA_SC_VPORT_SCISSOR_1_TL
0x40004000, // PA_SC_VPORT_SCISSOR_1_BR
0x80000000, // PA_SC_VPORT_SCISSOR_2_TL
0x40004000, // PA_SC_VPORT_SCISSOR_2_BR
0x80000000, // PA_SC_VPORT_SCISSOR_3_TL
0x40004000, // PA_SC_VPORT_SCISSOR_3_BR
0x80000000, // PA_SC_VPORT_SCISSOR_4_TL
0x40004000, // PA_SC_VPORT_SCISSOR_4_BR
0x80000000, // PA_SC_VPORT_SCISSOR_5_TL
0x40004000, // PA_SC_VPORT_SCISSOR_5_BR
0x80000000, // PA_SC_VPORT_SCISSOR_6_TL
0x40004000, // PA_SC_VPORT_SCISSOR_6_BR
0x80000000, // PA_SC_VPORT_SCISSOR_7_TL
0x40004000, // PA_SC_VPORT_SCISSOR_7_BR
0x80000000, // PA_SC_VPORT_SCISSOR_8_TL
0x40004000, // PA_SC_VPORT_SCISSOR_8_BR
0x80000000, // PA_SC_VPORT_SCISSOR_9_TL
0x40004000, // PA_SC_VPORT_SCISSOR_9_BR
0x80000000, // PA_SC_VPORT_SCISSOR_10_TL
0x40004000, // PA_SC_VPORT_SCISSOR_10_BR
0x80000000, // PA_SC_VPORT_SCISSOR_11_TL
0x40004000, // PA_SC_VPORT_SCISSOR_11_BR
0x80000000, // PA_SC_VPORT_SCISSOR_12_TL
0x40004000, // PA_SC_VPORT_SCISSOR_12_BR
0x80000000, // PA_SC_VPORT_SCISSOR_13_TL
0x40004000, // PA_SC_VPORT_SCISSOR_13_BR
0x80000000, // PA_SC_VPORT_SCISSOR_14_TL
0x40004000, // PA_SC_VPORT_SCISSOR_14_BR
0x80000000, // PA_SC_VPORT_SCISSOR_15_TL
0x40004000, // PA_SC_VPORT_SCISSOR_15_BR
0x00000000, // PA_SC_VPORT_ZMIN_0
0x3f800000, // PA_SC_VPORT_ZMAX_0
0x00000000, // PA_SC_VPORT_ZMIN_1
0x3f800000, // PA_SC_VPORT_ZMAX_1
0x00000000, // PA_SC_VPORT_ZMIN_2
0x3f800000, // PA_SC_VPORT_ZMAX_2
0x00000000, // PA_SC_VPORT_ZMIN_3
0x3f800000, // PA_SC_VPORT_ZMAX_3
0x00000000, // PA_SC_VPORT_ZMIN_4
0x3f800000, // PA_SC_VPORT_ZMAX_4
0x00000000, // PA_SC_VPORT_ZMIN_5
0x3f800000, // PA_SC_VPORT_ZMAX_5
0x00000000, // PA_SC_VPORT_ZMIN_6
0x3f800000, // PA_SC_VPORT_ZMAX_6
0x00000000, // PA_SC_VPORT_ZMIN_7
0x3f800000, // PA_SC_VPORT_ZMAX_7
0x00000000, // PA_SC_VPORT_ZMIN_8
0x3f800000, // PA_SC_VPORT_ZMAX_8
0x00000000, // PA_SC_VPORT_ZMIN_9
0x3f800000, // PA_SC_VPORT_ZMAX_9
0x00000000, // PA_SC_VPORT_ZMIN_10
0x3f800000, // PA_SC_VPORT_ZMAX_10
0x00000000, // PA_SC_VPORT_ZMIN_11
0x3f800000, // PA_SC_VPORT_ZMAX_11
0x00000000, // PA_SC_VPORT_ZMIN_12
0x3f800000, // PA_SC_VPORT_ZMAX_12
0x00000000, // PA_SC_VPORT_ZMIN_13
0x3f800000, // PA_SC_VPORT_ZMAX_13
0x00000000, // PA_SC_VPORT_ZMIN_14
0x3f800000, // PA_SC_VPORT_ZMAX_14
0x00000000, // PA_SC_VPORT_ZMIN_15
0x3f800000, // PA_SC_VPORT_ZMAX_15
};
static const u32 si_SECT_CONTEXT_def_2[] =
{
0x00000000, // CP_PERFMON_CNTX_CNTL
0x00000000, // CP_RINGID
0x00000000, // CP_VMID
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0xffffffff, // VGT_MAX_VTX_INDX
0x00000000, // VGT_MIN_VTX_INDX
0x00000000, // VGT_INDX_OFFSET
0x00000000, // VGT_MULTI_PRIM_IB_RESET_INDX
0, // HOLE
0x00000000, // CB_BLEND_RED
0x00000000, // CB_BLEND_GREEN
0x00000000, // CB_BLEND_BLUE
0x00000000, // CB_BLEND_ALPHA
0, // HOLE
0, // HOLE
0x00000000, // DB_STENCIL_CONTROL
0x00000000, // DB_STENCILREFMASK
0x00000000, // DB_STENCILREFMASK_BF
0, // HOLE
0x00000000, // PA_CL_VPORT_XSCALE
0x00000000, // PA_CL_VPORT_XOFFSET
0x00000000, // PA_CL_VPORT_YSCALE
0x00000000, // PA_CL_VPORT_YOFFSET
0x00000000, // PA_CL_VPORT_ZSCALE
0x00000000, // PA_CL_VPORT_ZOFFSET
0x00000000, // PA_CL_VPORT_XSCALE_1
0x00000000, // PA_CL_VPORT_XOFFSET_1
0x00000000, // PA_CL_VPORT_YSCALE_1
0x00000000, // PA_CL_VPORT_YOFFSET_1
0x00000000, // PA_CL_VPORT_ZSCALE_1
0x00000000, // PA_CL_VPORT_ZOFFSET_1
0x00000000, // PA_CL_VPORT_XSCALE_2
0x00000000, // PA_CL_VPORT_XOFFSET_2
0x00000000, // PA_CL_VPORT_YSCALE_2
0x00000000, // PA_CL_VPORT_YOFFSET_2
0x00000000, // PA_CL_VPORT_ZSCALE_2
0x00000000, // PA_CL_VPORT_ZOFFSET_2
0x00000000, // PA_CL_VPORT_XSCALE_3
0x00000000, // PA_CL_VPORT_XOFFSET_3
0x00000000, // PA_CL_VPORT_YSCALE_3
0x00000000, // PA_CL_VPORT_YOFFSET_3
0x00000000, // PA_CL_VPORT_ZSCALE_3
0x00000000, // PA_CL_VPORT_ZOFFSET_3
0x00000000, // PA_CL_VPORT_XSCALE_4
0x00000000, // PA_CL_VPORT_XOFFSET_4
0x00000000, // PA_CL_VPORT_YSCALE_4
0x00000000, // PA_CL_VPORT_YOFFSET_4
0x00000000, // PA_CL_VPORT_ZSCALE_4
0x00000000, // PA_CL_VPORT_ZOFFSET_4
0x00000000, // PA_CL_VPORT_XSCALE_5
0x00000000, // PA_CL_VPORT_XOFFSET_5
0x00000000, // PA_CL_VPORT_YSCALE_5
0x00000000, // PA_CL_VPORT_YOFFSET_5
0x00000000, // PA_CL_VPORT_ZSCALE_5
0x00000000, // PA_CL_VPORT_ZOFFSET_5
0x00000000, // PA_CL_VPORT_XSCALE_6
0x00000000, // PA_CL_VPORT_XOFFSET_6
0x00000000, // PA_CL_VPORT_YSCALE_6
0x00000000, // PA_CL_VPORT_YOFFSET_6
0x00000000, // PA_CL_VPORT_ZSCALE_6
0x00000000, // PA_CL_VPORT_ZOFFSET_6
0x00000000, // PA_CL_VPORT_XSCALE_7
0x00000000, // PA_CL_VPORT_XOFFSET_7
0x00000000, // PA_CL_VPORT_YSCALE_7
0x00000000, // PA_CL_VPORT_YOFFSET_7
0x00000000, // PA_CL_VPORT_ZSCALE_7
0x00000000, // PA_CL_VPORT_ZOFFSET_7
0x00000000, // PA_CL_VPORT_XSCALE_8
0x00000000, // PA_CL_VPORT_XOFFSET_8
0x00000000, // PA_CL_VPORT_YSCALE_8
0x00000000, // PA_CL_VPORT_YOFFSET_8
0x00000000, // PA_CL_VPORT_ZSCALE_8
0x00000000, // PA_CL_VPORT_ZOFFSET_8
0x00000000, // PA_CL_VPORT_XSCALE_9
0x00000000, // PA_CL_VPORT_XOFFSET_9
0x00000000, // PA_CL_VPORT_YSCALE_9
0x00000000, // PA_CL_VPORT_YOFFSET_9
0x00000000, // PA_CL_VPORT_ZSCALE_9
0x00000000, // PA_CL_VPORT_ZOFFSET_9
0x00000000, // PA_CL_VPORT_XSCALE_10
0x00000000, // PA_CL_VPORT_XOFFSET_10
0x00000000, // PA_CL_VPORT_YSCALE_10
0x00000000, // PA_CL_VPORT_YOFFSET_10
0x00000000, // PA_CL_VPORT_ZSCALE_10
0x00000000, // PA_CL_VPORT_ZOFFSET_10
0x00000000, // PA_CL_VPORT_XSCALE_11
0x00000000, // PA_CL_VPORT_XOFFSET_11
0x00000000, // PA_CL_VPORT_YSCALE_11
0x00000000, // PA_CL_VPORT_YOFFSET_11
0x00000000, // PA_CL_VPORT_ZSCALE_11
0x00000000, // PA_CL_VPORT_ZOFFSET_11
0x00000000, // PA_CL_VPORT_XSCALE_12
0x00000000, // PA_CL_VPORT_XOFFSET_12
0x00000000, // PA_CL_VPORT_YSCALE_12
0x00000000, // PA_CL_VPORT_YOFFSET_12
0x00000000, // PA_CL_VPORT_ZSCALE_12
0x00000000, // PA_CL_VPORT_ZOFFSET_12
0x00000000, // PA_CL_VPORT_XSCALE_13
0x00000000, // PA_CL_VPORT_XOFFSET_13
0x00000000, // PA_CL_VPORT_YSCALE_13
0x00000000, // PA_CL_VPORT_YOFFSET_13
0x00000000, // PA_CL_VPORT_ZSCALE_13
0x00000000, // PA_CL_VPORT_ZOFFSET_13
0x00000000, // PA_CL_VPORT_XSCALE_14
0x00000000, // PA_CL_VPORT_XOFFSET_14
0x00000000, // PA_CL_VPORT_YSCALE_14
0x00000000, // PA_CL_VPORT_YOFFSET_14
0x00000000, // PA_CL_VPORT_ZSCALE_14
0x00000000, // PA_CL_VPORT_ZOFFSET_14
0x00000000, // PA_CL_VPORT_XSCALE_15
0x00000000, // PA_CL_VPORT_XOFFSET_15
0x00000000, // PA_CL_VPORT_YSCALE_15
0x00000000, // PA_CL_VPORT_YOFFSET_15
0x00000000, // PA_CL_VPORT_ZSCALE_15
0x00000000, // PA_CL_VPORT_ZOFFSET_15
0x00000000, // PA_CL_UCP_0_X
0x00000000, // PA_CL_UCP_0_Y
0x00000000, // PA_CL_UCP_0_Z
0x00000000, // PA_CL_UCP_0_W
0x00000000, // PA_CL_UCP_1_X
0x00000000, // PA_CL_UCP_1_Y
0x00000000, // PA_CL_UCP_1_Z
0x00000000, // PA_CL_UCP_1_W
0x00000000, // PA_CL_UCP_2_X
0x00000000, // PA_CL_UCP_2_Y
0x00000000, // PA_CL_UCP_2_Z
0x00000000, // PA_CL_UCP_2_W
0x00000000, // PA_CL_UCP_3_X
0x00000000, // PA_CL_UCP_3_Y
0x00000000, // PA_CL_UCP_3_Z
0x00000000, // PA_CL_UCP_3_W
0x00000000, // PA_CL_UCP_4_X
0x00000000, // PA_CL_UCP_4_Y
0x00000000, // PA_CL_UCP_4_Z
0x00000000, // PA_CL_UCP_4_W
0x00000000, // PA_CL_UCP_5_X
0x00000000, // PA_CL_UCP_5_Y
0x00000000, // PA_CL_UCP_5_Z
0x00000000, // PA_CL_UCP_5_W
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0x00000000, // SPI_PS_INPUT_CNTL_0
0x00000000, // SPI_PS_INPUT_CNTL_1
0x00000000, // SPI_PS_INPUT_CNTL_2
0x00000000, // SPI_PS_INPUT_CNTL_3
0x00000000, // SPI_PS_INPUT_CNTL_4
0x00000000, // SPI_PS_INPUT_CNTL_5
0x00000000, // SPI_PS_INPUT_CNTL_6
0x00000000, // SPI_PS_INPUT_CNTL_7
0x00000000, // SPI_PS_INPUT_CNTL_8
0x00000000, // SPI_PS_INPUT_CNTL_9
0x00000000, // SPI_PS_INPUT_CNTL_10
0x00000000, // SPI_PS_INPUT_CNTL_11
0x00000000, // SPI_PS_INPUT_CNTL_12
0x00000000, // SPI_PS_INPUT_CNTL_13
0x00000000, // SPI_PS_INPUT_CNTL_14
0x00000000, // SPI_PS_INPUT_CNTL_15
0x00000000, // SPI_PS_INPUT_CNTL_16
0x00000000, // SPI_PS_INPUT_CNTL_17
0x00000000, // SPI_PS_INPUT_CNTL_18
0x00000000, // SPI_PS_INPUT_CNTL_19
0x00000000, // SPI_PS_INPUT_CNTL_20
0x00000000, // SPI_PS_INPUT_CNTL_21
0x00000000, // SPI_PS_INPUT_CNTL_22
0x00000000, // SPI_PS_INPUT_CNTL_23
0x00000000, // SPI_PS_INPUT_CNTL_24
0x00000000, // SPI_PS_INPUT_CNTL_25
0x00000000, // SPI_PS_INPUT_CNTL_26
0x00000000, // SPI_PS_INPUT_CNTL_27
0x00000000, // SPI_PS_INPUT_CNTL_28
0x00000000, // SPI_PS_INPUT_CNTL_29
0x00000000, // SPI_PS_INPUT_CNTL_30
0x00000000, // SPI_PS_INPUT_CNTL_31
0x00000000, // SPI_VS_OUT_CONFIG
0, // HOLE
0x00000000, // SPI_PS_INPUT_ENA
0x00000000, // SPI_PS_INPUT_ADDR
0x00000000, // SPI_INTERP_CONTROL_0
0x00000002, // SPI_PS_IN_CONTROL
0, // HOLE
0x00000000, // SPI_BARYC_CNTL
0, // HOLE
0x00000000, // SPI_TMPRING_SIZE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0x00000000, // SPI_WAVE_MGMT_1
0x00000000, // SPI_WAVE_MGMT_2
0x00000000, // SPI_SHADER_POS_FORMAT
0x00000000, // SPI_SHADER_Z_FORMAT
0x00000000, // SPI_SHADER_COL_FORMAT
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0x00000000, // CB_BLEND0_CONTROL
0x00000000, // CB_BLEND1_CONTROL
0x00000000, // CB_BLEND2_CONTROL
0x00000000, // CB_BLEND3_CONTROL
0x00000000, // CB_BLEND4_CONTROL
0x00000000, // CB_BLEND5_CONTROL
0x00000000, // CB_BLEND6_CONTROL
0x00000000, // CB_BLEND7_CONTROL
};
static const u32 si_SECT_CONTEXT_def_3[] =
{
0x00000000, // PA_CL_POINT_X_RAD
0x00000000, // PA_CL_POINT_Y_RAD
0x00000000, // PA_CL_POINT_SIZE
0x00000000, // PA_CL_POINT_CULL_RAD
0x00000000, // VGT_DMA_BASE_HI
0x00000000, // VGT_DMA_BASE
};
static const u32 si_SECT_CONTEXT_def_4[] =
{
0x00000000, // DB_DEPTH_CONTROL
0x00000000, // DB_EQAA
0x00000000, // CB_COLOR_CONTROL
0x00000000, // DB_SHADER_CONTROL
0x00090000, // PA_CL_CLIP_CNTL
0x00000004, // PA_SU_SC_MODE_CNTL
0x00000000, // PA_CL_VTE_CNTL
0x00000000, // PA_CL_VS_OUT_CNTL
0x00000000, // PA_CL_NANINF_CNTL
0x00000000, // PA_SU_LINE_STIPPLE_CNTL
0x00000000, // PA_SU_LINE_STIPPLE_SCALE
0x00000000, // PA_SU_PRIM_FILTER_CNTL
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0x00000000, // PA_SU_POINT_SIZE
0x00000000, // PA_SU_POINT_MINMAX
0x00000000, // PA_SU_LINE_CNTL
0x00000000, // PA_SC_LINE_STIPPLE
0x00000000, // VGT_OUTPUT_PATH_CNTL
0x00000000, // VGT_HOS_CNTL
0x00000000, // VGT_HOS_MAX_TESS_LEVEL
0x00000000, // VGT_HOS_MIN_TESS_LEVEL
0x00000000, // VGT_HOS_REUSE_DEPTH
0x00000000, // VGT_GROUP_PRIM_TYPE
0x00000000, // VGT_GROUP_FIRST_DECR
0x00000000, // VGT_GROUP_DECR
0x00000000, // VGT_GROUP_VECT_0_CNTL
0x00000000, // VGT_GROUP_VECT_1_CNTL
0x00000000, // VGT_GROUP_VECT_0_FMT_CNTL
0x00000000, // VGT_GROUP_VECT_1_FMT_CNTL
0x00000000, // VGT_GS_MODE
0, // HOLE
0x00000000, // PA_SC_MODE_CNTL_0
0x00000000, // PA_SC_MODE_CNTL_1
0x00000000, // VGT_ENHANCE
0x00000100, // VGT_GS_PER_ES
0x00000080, // VGT_ES_PER_GS
0x00000002, // VGT_GS_PER_VS
0x00000000, // VGT_GSVS_RING_OFFSET_1
0x00000000, // VGT_GSVS_RING_OFFSET_2
0x00000000, // VGT_GSVS_RING_OFFSET_3
0x00000000, // VGT_GS_OUT_PRIM_TYPE
0x00000000, // IA_ENHANCE
};
static const u32 si_SECT_CONTEXT_def_5[] =
{
0x00000000, // VGT_PRIMITIVEID_EN
};
static const u32 si_SECT_CONTEXT_def_6[] =
{
0x00000000, // VGT_PRIMITIVEID_RESET
};
static const u32 si_SECT_CONTEXT_def_7[] =
{
0x00000000, // VGT_MULTI_PRIM_IB_RESET_EN
0, // HOLE
0, // HOLE
0x00000000, // VGT_INSTANCE_STEP_RATE_0
0x00000000, // VGT_INSTANCE_STEP_RATE_1
0x000000ff, // IA_MULTI_VGT_PARAM
0x00000000, // VGT_ESGS_RING_ITEMSIZE
0x00000000, // VGT_GSVS_RING_ITEMSIZE
0x00000000, // VGT_REUSE_OFF
0x00000000, // VGT_VTX_CNT_EN
0x00000000, // DB_HTILE_SURFACE
0x00000000, // DB_SRESULTS_COMPARE_STATE0
0x00000000, // DB_SRESULTS_COMPARE_STATE1
0x00000000, // DB_PRELOAD_CONTROL
0, // HOLE
0x00000000, // VGT_STRMOUT_BUFFER_SIZE_0
0x00000000, // VGT_STRMOUT_VTX_STRIDE_0
0, // HOLE
0x00000000, // VGT_STRMOUT_BUFFER_OFFSET_0
0x00000000, // VGT_STRMOUT_BUFFER_SIZE_1
0x00000000, // VGT_STRMOUT_VTX_STRIDE_1
0, // HOLE
0x00000000, // VGT_STRMOUT_BUFFER_OFFSET_1
0x00000000, // VGT_STRMOUT_BUFFER_SIZE_2
0x00000000, // VGT_STRMOUT_VTX_STRIDE_2
0, // HOLE
0x00000000, // VGT_STRMOUT_BUFFER_OFFSET_2
0x00000000, // VGT_STRMOUT_BUFFER_SIZE_3
0x00000000, // VGT_STRMOUT_VTX_STRIDE_3
0, // HOLE
0x00000000, // VGT_STRMOUT_BUFFER_OFFSET_3
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0x00000000, // VGT_STRMOUT_DRAW_OPAQUE_OFFSET
0x00000000, // VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE
0x00000000, // VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE
0, // HOLE
0x00000000, // VGT_GS_MAX_VERT_OUT
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0x00000000, // VGT_SHADER_STAGES_EN
0x00000000, // VGT_LS_HS_CONFIG
0x00000000, // VGT_GS_VERT_ITEMSIZE
0x00000000, // VGT_GS_VERT_ITEMSIZE_1
0x00000000, // VGT_GS_VERT_ITEMSIZE_2
0x00000000, // VGT_GS_VERT_ITEMSIZE_3
0x00000000, // VGT_TF_PARAM
0x00000000, // DB_ALPHA_TO_MASK
0, // HOLE
0x00000000, // PA_SU_POLY_OFFSET_DB_FMT_CNTL
0x00000000, // PA_SU_POLY_OFFSET_CLAMP
0x00000000, // PA_SU_POLY_OFFSET_FRONT_SCALE
0x00000000, // PA_SU_POLY_OFFSET_FRONT_OFFSET
0x00000000, // PA_SU_POLY_OFFSET_BACK_SCALE
0x00000000, // PA_SU_POLY_OFFSET_BACK_OFFSET
0x00000000, // VGT_GS_INSTANCE_CNT
0x00000000, // VGT_STRMOUT_CONFIG
0x00000000, // VGT_STRMOUT_BUFFER_CONFIG
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0x00000000, // PA_SC_CENTROID_PRIORITY_0
0x00000000, // PA_SC_CENTROID_PRIORITY_1
0x00001000, // PA_SC_LINE_CNTL
0x00000000, // PA_SC_AA_CONFIG
0x00000005, // PA_SU_VTX_CNTL
0x3f800000, // PA_CL_GB_VERT_CLIP_ADJ
0x3f800000, // PA_CL_GB_VERT_DISC_ADJ
0x3f800000, // PA_CL_GB_HORZ_CLIP_ADJ
0x3f800000, // PA_CL_GB_HORZ_DISC_ADJ
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2
0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3
0xffffffff, // PA_SC_AA_MASK_X0Y0_X1Y0
0xffffffff, // PA_SC_AA_MASK_X0Y1_X1Y1
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0, // HOLE
0x0000000e, // VGT_VERTEX_REUSE_BLOCK_CNTL
0x00000010, // VGT_OUT_DEALLOC_CNTL
0x00000000, // CB_COLOR0_BASE
0x00000000, // CB_COLOR0_PITCH
0x00000000, // CB_COLOR0_SLICE
0x00000000, // CB_COLOR0_VIEW
0x00000000, // CB_COLOR0_INFO
0x00000000, // CB_COLOR0_ATTRIB
0, // HOLE
0x00000000, // CB_COLOR0_CMASK
0x00000000, // CB_COLOR0_CMASK_SLICE
0x00000000, // CB_COLOR0_FMASK
0x00000000, // CB_COLOR0_FMASK_SLICE
0x00000000, // CB_COLOR0_CLEAR_WORD0
0x00000000, // CB_COLOR0_CLEAR_WORD1
0, // HOLE
0, // HOLE
0x00000000, // CB_COLOR1_BASE
0x00000000, // CB_COLOR1_PITCH
0x00000000, // CB_COLOR1_SLICE
0x00000000, // CB_COLOR1_VIEW
0x00000000, // CB_COLOR1_INFO
0x00000000, // CB_COLOR1_ATTRIB
0, // HOLE
0x00000000, // CB_COLOR1_CMASK
0x00000000, // CB_COLOR1_CMASK_SLICE
0x00000000, // CB_COLOR1_FMASK
0x00000000, // CB_COLOR1_FMASK_SLICE
0x00000000, // CB_COLOR1_CLEAR_WORD0
0x00000000, // CB_COLOR1_CLEAR_WORD1
0, // HOLE
0, // HOLE
0x00000000, // CB_COLOR2_BASE
0x00000000, // CB_COLOR2_PITCH
0x00000000, // CB_COLOR2_SLICE
0x00000000, // CB_COLOR2_VIEW
0x00000000, // CB_COLOR2_INFO
0x00000000, // CB_COLOR2_ATTRIB
0, // HOLE
0x00000000, // CB_COLOR2_CMASK
0x00000000, // CB_COLOR2_CMASK_SLICE
0x00000000, // CB_COLOR2_FMASK
0x00000000, // CB_COLOR2_FMASK_SLICE
0x00000000, // CB_COLOR2_CLEAR_WORD0
0x00000000, // CB_COLOR2_CLEAR_WORD1
0, // HOLE
0, // HOLE
0x00000000, // CB_COLOR3_BASE
0x00000000, // CB_COLOR3_PITCH
0x00000000, // CB_COLOR3_SLICE
0x00000000, // CB_COLOR3_VIEW
0x00000000, // CB_COLOR3_INFO
0x00000000, // CB_COLOR3_ATTRIB
0, // HOLE
0x00000000, // CB_COLOR3_CMASK
0x00000000, // CB_COLOR3_CMASK_SLICE
0x00000000, // CB_COLOR3_FMASK
0x00000000, // CB_COLOR3_FMASK_SLICE
0x00000000, // CB_COLOR3_CLEAR_WORD0
0x00000000, // CB_COLOR3_CLEAR_WORD1
0, // HOLE
0, // HOLE
0x00000000, // CB_COLOR4_BASE
0x00000000, // CB_COLOR4_PITCH
0x00000000, // CB_COLOR4_SLICE
0x00000000, // CB_COLOR4_VIEW
0x00000000, // CB_COLOR4_INFO
0x00000000, // CB_COLOR4_ATTRIB
0, // HOLE
0x00000000, // CB_COLOR4_CMASK
0x00000000, // CB_COLOR4_CMASK_SLICE
0x00000000, // CB_COLOR4_FMASK
0x00000000, // CB_COLOR4_FMASK_SLICE
0x00000000, // CB_COLOR4_CLEAR_WORD0
0x00000000, // CB_COLOR4_CLEAR_WORD1
0, // HOLE
0, // HOLE
0x00000000, // CB_COLOR5_BASE
0x00000000, // CB_COLOR5_PITCH
0x00000000, // CB_COLOR5_SLICE
0x00000000, // CB_COLOR5_VIEW
0x00000000, // CB_COLOR5_INFO
0x00000000, // CB_COLOR5_ATTRIB
0, // HOLE
0x00000000, // CB_COLOR5_CMASK
0x00000000, // CB_COLOR5_CMASK_SLICE
0x00000000, // CB_COLOR5_FMASK
0x00000000, // CB_COLOR5_FMASK_SLICE
0x00000000, // CB_COLOR5_CLEAR_WORD0
0x00000000, // CB_COLOR5_CLEAR_WORD1
0, // HOLE
0, // HOLE
0x00000000, // CB_COLOR6_BASE
0x00000000, // CB_COLOR6_PITCH
0x00000000, // CB_COLOR6_SLICE
0x00000000, // CB_COLOR6_VIEW
0x00000000, // CB_COLOR6_INFO
0x00000000, // CB_COLOR6_ATTRIB
0, // HOLE
0x00000000, // CB_COLOR6_CMASK
0x00000000, // CB_COLOR6_CMASK_SLICE
0x00000000, // CB_COLOR6_FMASK
0x00000000, // CB_COLOR6_FMASK_SLICE
0x00000000, // CB_COLOR6_CLEAR_WORD0
0x00000000, // CB_COLOR6_CLEAR_WORD1
0, // HOLE
0, // HOLE
0x00000000, // CB_COLOR7_BASE
0x00000000, // CB_COLOR7_PITCH
0x00000000, // CB_COLOR7_SLICE
0x00000000, // CB_COLOR7_VIEW
0x00000000, // CB_COLOR7_INFO
0x00000000, // CB_COLOR7_ATTRIB
0, // HOLE
0x00000000, // CB_COLOR7_CMASK
0x00000000, // CB_COLOR7_CMASK_SLICE
0x00000000, // CB_COLOR7_FMASK
0x00000000, // CB_COLOR7_FMASK_SLICE
0x00000000, // CB_COLOR7_CLEAR_WORD0
0x00000000, // CB_COLOR7_CLEAR_WORD1
};
static const struct cs_extent_def si_SECT_CONTEXT_defs[] =
{
{si_SECT_CONTEXT_def_1, 0x0000a000, 212 },
{si_SECT_CONTEXT_def_2, 0x0000a0d8, 272 },
{si_SECT_CONTEXT_def_3, 0x0000a1f5, 6 },
{si_SECT_CONTEXT_def_4, 0x0000a200, 157 },
{si_SECT_CONTEXT_def_5, 0x0000a2a1, 1 },
{si_SECT_CONTEXT_def_6, 0x0000a2a3, 1 },
{si_SECT_CONTEXT_def_7, 0x0000a2a5, 233 },
{ 0, 0, 0 }
};
static const struct cs_section_def si_cs_data[] = {
{ si_SECT_CONTEXT_defs, SECT_CONTEXT },
{ 0, SECT_NONE }
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,160 @@
/*
* Copyright 2011 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.
*
*/
#ifndef __CYPRESS_DPM_H__
#define __CYPRESS_DPM_H__
#include "rv770_dpm.h"
#include "evergreen_smc.h"
struct evergreen_mc_reg_entry {
u32 mclk_max;
u32 mc_data[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE];
};
struct evergreen_mc_reg_table {
u8 last;
u8 num_entries;
u16 valid_flag;
struct evergreen_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES];
SMC_Evergreen_MCRegisterAddress mc_reg_address[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE];
};
struct evergreen_ulv_param {
bool supported;
struct rv7xx_pl *pl;
};
struct evergreen_arb_registers {
u32 mc_arb_dram_timing;
u32 mc_arb_dram_timing2;
u32 mc_arb_rfsh_rate;
u32 mc_arb_burst_time;
};
struct at {
u32 rlp;
u32 rmp;
u32 lhp;
u32 lmp;
};
struct evergreen_power_info {
/* must be first! */
struct rv7xx_power_info rv7xx;
/* flags */
bool vddci_control;
bool dynamic_ac_timing;
bool abm;
bool mcls;
bool light_sleep;
bool memory_transition;
bool pcie_performance_request;
bool pcie_performance_request_registered;
bool sclk_deep_sleep;
bool dll_default_on;
bool ls_clock_gating;
bool smu_uvd_hs;
bool uvd_enabled;
/* stored values */
u16 acpi_vddci;
u8 mvdd_high_index;
u8 mvdd_low_index;
u32 mclk_edc_wr_enable_threshold;
struct evergreen_mc_reg_table mc_reg_table;
struct atom_voltage_table vddc_voltage_table;
struct atom_voltage_table vddci_voltage_table;
struct evergreen_arb_registers bootup_arb_registers;
struct evergreen_ulv_param ulv;
struct at ats[2];
/* smc offsets */
u16 mc_reg_table_start;
struct radeon_ps current_rps;
struct rv7xx_ps current_ps;
struct radeon_ps requested_rps;
struct rv7xx_ps requested_ps;
};
#define CYPRESS_HASI_DFLT 400000
#define CYPRESS_MGCGTTLOCAL0_DFLT 0x00000000
#define CYPRESS_MGCGTTLOCAL1_DFLT 0x00000000
#define CYPRESS_MGCGTTLOCAL2_DFLT 0x00000000
#define CYPRESS_MGCGTTLOCAL3_DFLT 0x00000000
#define CYPRESS_MGCGCGTSSMCTRL_DFLT 0x81944bc0
#define REDWOOD_MGCGCGTSSMCTRL_DFLT 0x6e944040
#define CEDAR_MGCGCGTSSMCTRL_DFLT 0x46944040
#define CYPRESS_VRC_DFLT 0xC00033
#define PCIE_PERF_REQ_REMOVE_REGISTRY 0
#define PCIE_PERF_REQ_FORCE_LOWPOWER 1
#define PCIE_PERF_REQ_PECI_GEN1 2
#define PCIE_PERF_REQ_PECI_GEN2 3
#define PCIE_PERF_REQ_PECI_GEN3 4
int cypress_convert_power_level_to_smc(struct radeon_device *rdev,
struct rv7xx_pl *pl,
RV770_SMC_HW_PERFORMANCE_LEVEL *level,
u8 watermark_level);
int cypress_populate_smc_acpi_state(struct radeon_device *rdev,
RV770_SMC_STATETABLE *table);
int cypress_populate_smc_voltage_tables(struct radeon_device *rdev,
RV770_SMC_STATETABLE *table);
int cypress_populate_smc_initial_state(struct radeon_device *rdev,
struct radeon_ps *radeon_initial_state,
RV770_SMC_STATETABLE *table);
u32 cypress_calculate_burst_time(struct radeon_device *rdev,
u32 engine_clock, u32 memory_clock);
void cypress_notify_link_speed_change_before_state_change(struct radeon_device *rdev,
struct radeon_ps *radeon_new_state,
struct radeon_ps *radeon_current_state);
int cypress_upload_sw_state(struct radeon_device *rdev,
struct radeon_ps *radeon_new_state);
int cypress_upload_mc_reg_table(struct radeon_device *rdev,
struct radeon_ps *radeon_new_state);
void cypress_program_memory_timing_parameters(struct radeon_device *rdev,
struct radeon_ps *radeon_new_state);
void cypress_notify_link_speed_change_after_state_change(struct radeon_device *rdev,
struct radeon_ps *radeon_new_state,
struct radeon_ps *radeon_current_state);
int cypress_construct_voltage_tables(struct radeon_device *rdev);
int cypress_get_mvdd_configuration(struct radeon_device *rdev);
void cypress_enable_spread_spectrum(struct radeon_device *rdev,
bool enable);
void cypress_enable_display_gap(struct radeon_device *rdev);
int cypress_get_table_locations(struct radeon_device *rdev);
int cypress_populate_mc_reg_table(struct radeon_device *rdev,
struct radeon_ps *radeon_boot_state);
void cypress_program_response_times(struct radeon_device *rdev);
int cypress_notify_smc_display_change(struct radeon_device *rdev,
bool has_display);
void cypress_enable_sclk_control(struct radeon_device *rdev,
bool enable);
void cypress_enable_mclk_control(struct radeon_device *rdev,
bool enable);
void cypress_start_dpm(struct radeon_device *rdev);
void cypress_advertise_gen2_capability(struct radeon_device *rdev);
u32 cypress_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf);
u8 cypress_get_mclk_frequency_ratio(struct radeon_device *rdev,
u32 memory_clock, bool strobe_mode);
u8 cypress_get_strobe_mode_settings(struct radeon_device *rdev, u32 mclk);
#endif

View File

@ -33,9 +33,7 @@
#include "avivod.h"
#include "evergreen_reg.h"
#include "evergreen_blit_shaders.h"
#define EVERGREEN_PFP_UCODE_SIZE 1120
#define EVERGREEN_PM4_UCODE_SIZE 1376
#include "radeon_ucode.h"
static const u32 crtc_offsets[6] =
{
@ -47,9 +45,98 @@ static const u32 crtc_offsets[6] =
EVERGREEN_CRTC5_REGISTER_OFFSET
};
#include "clearstate_evergreen.h"
static u32 sumo_rlc_save_restore_register_list[] =
{
0x98fc,
0x9830,
0x9834,
0x9838,
0x9870,
0x9874,
0x8a14,
0x8b24,
0x8bcc,
0x8b10,
0x8d00,
0x8d04,
0x8c00,
0x8c04,
0x8c08,
0x8c0c,
0x8d8c,
0x8c20,
0x8c24,
0x8c28,
0x8c18,
0x8c1c,
0x8cf0,
0x8e2c,
0x8e38,
0x8c30,
0x9508,
0x9688,
0x9608,
0x960c,
0x9610,
0x9614,
0x88c4,
0x88d4,
0xa008,
0x900c,
0x9100,
0x913c,
0x98f8,
0x98f4,
0x9b7c,
0x3f8c,
0x8950,
0x8954,
0x8a18,
0x8b28,
0x9144,
0x9148,
0x914c,
0x3f90,
0x3f94,
0x915c,
0x9160,
0x9178,
0x917c,
0x9180,
0x918c,
0x9190,
0x9194,
0x9198,
0x919c,
0x91a8,
0x91ac,
0x91b0,
0x91b4,
0x91b8,
0x91c4,
0x91c8,
0x91cc,
0x91d0,
0x91d4,
0x91e0,
0x91e4,
0x91ec,
0x91f0,
0x91f4,
0x9200,
0x9204,
0x929c,
0x9150,
0x802c,
};
static u32 sumo_rlc_save_restore_register_list_size = ARRAY_SIZE(sumo_rlc_save_restore_register_list);
static void evergreen_gpu_init(struct radeon_device *rdev);
void evergreen_fini(struct radeon_device *rdev);
void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
void evergreen_program_aspm(struct radeon_device *rdev);
extern void cayman_cp_int_cntl_setup(struct radeon_device *rdev,
int ring, u32 cp_int_cntl);
@ -2036,7 +2123,8 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
u32 lb_size, u32 num_heads)
{
struct drm_display_mode *mode = &radeon_crtc->base.mode;
struct evergreen_wm_params wm;
struct evergreen_wm_params wm_low, wm_high;
u32 dram_channels;
u32 pixel_period;
u32 line_time = 0;
u32 latency_watermark_a = 0, latency_watermark_b = 0;
@ -2052,39 +2140,81 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535);
priority_a_cnt = 0;
priority_b_cnt = 0;
dram_channels = evergreen_get_number_of_dram_channels(rdev);
wm.yclk = rdev->pm.current_mclk * 10;
wm.sclk = rdev->pm.current_sclk * 10;
wm.disp_clk = mode->clock;
wm.src_width = mode->crtc_hdisplay;
wm.active_time = mode->crtc_hdisplay * pixel_period;
wm.blank_time = line_time - wm.active_time;
wm.interlaced = false;
/* watermark for high clocks */
if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
wm_high.yclk =
radeon_dpm_get_mclk(rdev, false) * 10;
wm_high.sclk =
radeon_dpm_get_sclk(rdev, false) * 10;
} else {
wm_high.yclk = rdev->pm.current_mclk * 10;
wm_high.sclk = rdev->pm.current_sclk * 10;
}
wm_high.disp_clk = mode->clock;
wm_high.src_width = mode->crtc_hdisplay;
wm_high.active_time = mode->crtc_hdisplay * pixel_period;
wm_high.blank_time = line_time - wm_high.active_time;
wm_high.interlaced = false;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
wm.interlaced = true;
wm.vsc = radeon_crtc->vsc;
wm.vtaps = 1;
wm_high.interlaced = true;
wm_high.vsc = radeon_crtc->vsc;
wm_high.vtaps = 1;
if (radeon_crtc->rmx_type != RMX_OFF)
wm.vtaps = 2;
wm.bytes_per_pixel = 4; /* XXX: get this from fb config */
wm.lb_size = lb_size;
wm.dram_channels = evergreen_get_number_of_dram_channels(rdev);
wm.num_heads = num_heads;
wm_high.vtaps = 2;
wm_high.bytes_per_pixel = 4; /* XXX: get this from fb config */
wm_high.lb_size = lb_size;
wm_high.dram_channels = dram_channels;
wm_high.num_heads = num_heads;
/* watermark for low clocks */
if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
wm_low.yclk =
radeon_dpm_get_mclk(rdev, true) * 10;
wm_low.sclk =
radeon_dpm_get_sclk(rdev, true) * 10;
} else {
wm_low.yclk = rdev->pm.current_mclk * 10;
wm_low.sclk = rdev->pm.current_sclk * 10;
}
wm_low.disp_clk = mode->clock;
wm_low.src_width = mode->crtc_hdisplay;
wm_low.active_time = mode->crtc_hdisplay * pixel_period;
wm_low.blank_time = line_time - wm_low.active_time;
wm_low.interlaced = false;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
wm_low.interlaced = true;
wm_low.vsc = radeon_crtc->vsc;
wm_low.vtaps = 1;
if (radeon_crtc->rmx_type != RMX_OFF)
wm_low.vtaps = 2;
wm_low.bytes_per_pixel = 4; /* XXX: get this from fb config */
wm_low.lb_size = lb_size;
wm_low.dram_channels = dram_channels;
wm_low.num_heads = num_heads;
/* set for high clocks */
latency_watermark_a = min(evergreen_latency_watermark(&wm), (u32)65535);
latency_watermark_a = min(evergreen_latency_watermark(&wm_high), (u32)65535);
/* set for low clocks */
/* wm.yclk = low clk; wm.sclk = low clk */
latency_watermark_b = min(evergreen_latency_watermark(&wm), (u32)65535);
latency_watermark_b = min(evergreen_latency_watermark(&wm_low), (u32)65535);
/* possibly force display priority to high */
/* should really do this at mode validation time... */
if (!evergreen_average_bandwidth_vs_dram_bandwidth_for_display(&wm) ||
!evergreen_average_bandwidth_vs_available_bandwidth(&wm) ||
!evergreen_check_latency_hiding(&wm) ||
if (!evergreen_average_bandwidth_vs_dram_bandwidth_for_display(&wm_high) ||
!evergreen_average_bandwidth_vs_available_bandwidth(&wm_high) ||
!evergreen_check_latency_hiding(&wm_high) ||
(rdev->disp_priority == 2)) {
DRM_DEBUG_KMS("force priority to high\n");
DRM_DEBUG_KMS("force priority a to high\n");
priority_a_cnt |= PRIORITY_ALWAYS_ON;
}
if (!evergreen_average_bandwidth_vs_dram_bandwidth_for_display(&wm_low) ||
!evergreen_average_bandwidth_vs_available_bandwidth(&wm_low) ||
!evergreen_check_latency_hiding(&wm_low) ||
(rdev->disp_priority == 2)) {
DRM_DEBUG_KMS("force priority b to high\n");
priority_b_cnt |= PRIORITY_ALWAYS_ON;
}
@ -2137,6 +2267,10 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
WREG32(PRIORITY_A_CNT + radeon_crtc->crtc_offset, priority_a_cnt);
WREG32(PRIORITY_B_CNT + radeon_crtc->crtc_offset, priority_b_cnt);
/* save values for DPM */
radeon_crtc->line_time = line_time;
radeon_crtc->wm_high = latency_watermark_a;
radeon_crtc->wm_low = latency_watermark_b;
}
/**
@ -3120,10 +3254,8 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
u32 efuse_straps_4;
u32 efuse_straps_3;
WREG32(RCU_IND_INDEX, 0x204);
efuse_straps_4 = RREG32(RCU_IND_DATA);
WREG32(RCU_IND_INDEX, 0x203);
efuse_straps_3 = RREG32(RCU_IND_DATA);
efuse_straps_4 = RREG32_RCU(0x204);
efuse_straps_3 = RREG32_RCU(0x203);
tmp = (((efuse_straps_4 & 0xf) << 4) |
((efuse_straps_3 & 0xf0000000) >> 28));
} else {
@ -3727,6 +3859,264 @@ bool evergreen_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *rin
return radeon_ring_test_lockup(rdev, ring);
}
/*
* RLC
*/
#define RLC_SAVE_RESTORE_LIST_END_MARKER 0x00000000
#define RLC_CLEAR_STATE_END_MARKER 0x00000001
void sumo_rlc_fini(struct radeon_device *rdev)
{
int r;
/* save restore block */
if (rdev->rlc.save_restore_obj) {
r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false);
if (unlikely(r != 0))
dev_warn(rdev->dev, "(%d) reserve RLC sr bo failed\n", r);
radeon_bo_unpin(rdev->rlc.save_restore_obj);
radeon_bo_unreserve(rdev->rlc.save_restore_obj);
radeon_bo_unref(&rdev->rlc.save_restore_obj);
rdev->rlc.save_restore_obj = NULL;
}
/* clear state block */
if (rdev->rlc.clear_state_obj) {
r = radeon_bo_reserve(rdev->rlc.clear_state_obj, false);
if (unlikely(r != 0))
dev_warn(rdev->dev, "(%d) reserve RLC c bo failed\n", r);
radeon_bo_unpin(rdev->rlc.clear_state_obj);
radeon_bo_unreserve(rdev->rlc.clear_state_obj);
radeon_bo_unref(&rdev->rlc.clear_state_obj);
rdev->rlc.clear_state_obj = NULL;
}
}
int sumo_rlc_init(struct radeon_device *rdev)
{
u32 *src_ptr;
volatile u32 *dst_ptr;
u32 dws, data, i, j, k, reg_num;
u32 reg_list_num, reg_list_hdr_blk_index, reg_list_blk_index;
u64 reg_list_mc_addr;
struct cs_section_def *cs_data;
int r;
src_ptr = rdev->rlc.reg_list;
dws = rdev->rlc.reg_list_size;
cs_data = rdev->rlc.cs_data;
/* save restore block */
if (rdev->rlc.save_restore_obj == NULL) {
r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true,
RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.save_restore_obj);
if (r) {
dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r);
return r;
}
}
r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false);
if (unlikely(r != 0)) {
sumo_rlc_fini(rdev);
return r;
}
r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM,
&rdev->rlc.save_restore_gpu_addr);
if (r) {
radeon_bo_unreserve(rdev->rlc.save_restore_obj);
dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r);
sumo_rlc_fini(rdev);
return r;
}
r = radeon_bo_kmap(rdev->rlc.save_restore_obj, (void **)&rdev->rlc.sr_ptr);
if (r) {
dev_warn(rdev->dev, "(%d) map RLC sr bo failed\n", r);
sumo_rlc_fini(rdev);
return r;
}
/* write the sr buffer */
dst_ptr = rdev->rlc.sr_ptr;
/* format:
* dw0: (reg2 << 16) | reg1
* dw1: reg1 save space
* dw2: reg2 save space
*/
for (i = 0; i < dws; i++) {
data = src_ptr[i] >> 2;
i++;
if (i < dws)
data |= (src_ptr[i] >> 2) << 16;
j = (((i - 1) * 3) / 2);
dst_ptr[j] = data;
}
j = ((i * 3) / 2);
dst_ptr[j] = RLC_SAVE_RESTORE_LIST_END_MARKER;
radeon_bo_kunmap(rdev->rlc.save_restore_obj);
radeon_bo_unreserve(rdev->rlc.save_restore_obj);
/* clear state block */
reg_list_num = 0;
dws = 0;
for (i = 0; cs_data[i].section != NULL; i++) {
for (j = 0; cs_data[i].section[j].extent != NULL; j++) {
reg_list_num++;
dws += cs_data[i].section[j].reg_count;
}
}
reg_list_blk_index = (3 * reg_list_num + 2);
dws += reg_list_blk_index;
if (rdev->rlc.clear_state_obj == NULL) {
r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true,
RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.clear_state_obj);
if (r) {
dev_warn(rdev->dev, "(%d) create RLC c bo failed\n", r);
sumo_rlc_fini(rdev);
return r;
}
}
r = radeon_bo_reserve(rdev->rlc.clear_state_obj, false);
if (unlikely(r != 0)) {
sumo_rlc_fini(rdev);
return r;
}
r = radeon_bo_pin(rdev->rlc.clear_state_obj, RADEON_GEM_DOMAIN_VRAM,
&rdev->rlc.clear_state_gpu_addr);
if (r) {
radeon_bo_unreserve(rdev->rlc.clear_state_obj);
dev_warn(rdev->dev, "(%d) pin RLC c bo failed\n", r);
sumo_rlc_fini(rdev);
return r;
}
r = radeon_bo_kmap(rdev->rlc.clear_state_obj, (void **)&rdev->rlc.cs_ptr);
if (r) {
dev_warn(rdev->dev, "(%d) map RLC c bo failed\n", r);
sumo_rlc_fini(rdev);
return r;
}
/* set up the cs buffer */
dst_ptr = rdev->rlc.cs_ptr;
reg_list_hdr_blk_index = 0;
reg_list_mc_addr = rdev->rlc.clear_state_gpu_addr + (reg_list_blk_index * 4);
data = upper_32_bits(reg_list_mc_addr);
dst_ptr[reg_list_hdr_blk_index] = data;
reg_list_hdr_blk_index++;
for (i = 0; cs_data[i].section != NULL; i++) {
for (j = 0; cs_data[i].section[j].extent != NULL; j++) {
reg_num = cs_data[i].section[j].reg_count;
data = reg_list_mc_addr & 0xffffffff;
dst_ptr[reg_list_hdr_blk_index] = data;
reg_list_hdr_blk_index++;
data = (cs_data[i].section[j].reg_index * 4) & 0xffffffff;
dst_ptr[reg_list_hdr_blk_index] = data;
reg_list_hdr_blk_index++;
data = 0x08000000 | (reg_num * 4);
dst_ptr[reg_list_hdr_blk_index] = data;
reg_list_hdr_blk_index++;
for (k = 0; k < reg_num; k++) {
data = cs_data[i].section[j].extent[k];
dst_ptr[reg_list_blk_index + k] = data;
}
reg_list_mc_addr += reg_num * 4;
reg_list_blk_index += reg_num;
}
}
dst_ptr[reg_list_hdr_blk_index] = RLC_CLEAR_STATE_END_MARKER;
radeon_bo_kunmap(rdev->rlc.clear_state_obj);
radeon_bo_unreserve(rdev->rlc.clear_state_obj);
return 0;
}
static void evergreen_rlc_start(struct radeon_device *rdev)
{
u32 mask = RLC_ENABLE;
if (rdev->flags & RADEON_IS_IGP) {
mask |= GFX_POWER_GATING_ENABLE | GFX_POWER_GATING_SRC;
if (rdev->family == CHIP_ARUBA)
mask |= DYN_PER_SIMD_PG_ENABLE | LB_CNT_SPIM_ACTIVE | LOAD_BALANCE_ENABLE;
}
WREG32(RLC_CNTL, mask);
}
int evergreen_rlc_resume(struct radeon_device *rdev)
{
u32 i;
const __be32 *fw_data;
if (!rdev->rlc_fw)
return -EINVAL;
r600_rlc_stop(rdev);
WREG32(RLC_HB_CNTL, 0);
if (rdev->flags & RADEON_IS_IGP) {
if (rdev->family == CHIP_ARUBA) {
u32 always_on_bitmap =
3 | (3 << (16 * rdev->config.cayman.max_shader_engines));
/* find out the number of active simds */
u32 tmp = (RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffff0000) >> 16;
tmp |= 0xffffffff << rdev->config.cayman.max_simds_per_se;
tmp = hweight32(~tmp);
if (tmp == rdev->config.cayman.max_simds_per_se) {
WREG32(TN_RLC_LB_ALWAYS_ACTIVE_SIMD_MASK, always_on_bitmap);
WREG32(TN_RLC_LB_PARAMS, 0x00601004);
WREG32(TN_RLC_LB_INIT_SIMD_MASK, 0xffffffff);
WREG32(TN_RLC_LB_CNTR_INIT, 0x00000000);
WREG32(TN_RLC_LB_CNTR_MAX, 0x00002000);
}
} else {
WREG32(RLC_HB_WPTR_LSB_ADDR, 0);
WREG32(RLC_HB_WPTR_MSB_ADDR, 0);
}
WREG32(TN_RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8);
WREG32(TN_RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8);
} else {
WREG32(RLC_HB_BASE, 0);
WREG32(RLC_HB_RPTR, 0);
WREG32(RLC_HB_WPTR, 0);
WREG32(RLC_HB_WPTR_LSB_ADDR, 0);
WREG32(RLC_HB_WPTR_MSB_ADDR, 0);
}
WREG32(RLC_MC_CNTL, 0);
WREG32(RLC_UCODE_CNTL, 0);
fw_data = (const __be32 *)rdev->rlc_fw->data;
if (rdev->family >= CHIP_ARUBA) {
for (i = 0; i < ARUBA_RLC_UCODE_SIZE; i++) {
WREG32(RLC_UCODE_ADDR, i);
WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
}
} else if (rdev->family >= CHIP_CAYMAN) {
for (i = 0; i < CAYMAN_RLC_UCODE_SIZE; i++) {
WREG32(RLC_UCODE_ADDR, i);
WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
}
} else {
for (i = 0; i < EVERGREEN_RLC_UCODE_SIZE; i++) {
WREG32(RLC_UCODE_ADDR, i);
WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
}
}
WREG32(RLC_UCODE_ADDR, 0);
evergreen_rlc_start(rdev);
return 0;
}
/* Interrupts */
u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc)
@ -3805,6 +4195,7 @@ int evergreen_irq_set(struct radeon_device *rdev)
u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0;
u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0;
u32 dma_cntl, dma_cntl1 = 0;
u32 thermal_int = 0;
if (!rdev->irq.installed) {
WARN(1, "Can't enable IRQ/MSI because no handler is installed\n");
@ -3824,6 +4215,12 @@ int evergreen_irq_set(struct radeon_device *rdev)
hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
if (rdev->family == CHIP_ARUBA)
thermal_int = RREG32(TN_CG_THERMAL_INT_CTRL) &
~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
else
thermal_int = RREG32(CG_THERMAL_INT) &
~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
afmt1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
afmt2 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
@ -3869,6 +4266,11 @@ int evergreen_irq_set(struct radeon_device *rdev)
}
}
if (rdev->irq.dpm_thermal) {
DRM_DEBUG("dpm thermal\n");
thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
}
if (rdev->irq.crtc_vblank_int[0] ||
atomic_read(&rdev->irq.pflip[0])) {
DRM_DEBUG("evergreen_irq_set: vblank 0\n");
@ -3990,6 +4392,10 @@ int evergreen_irq_set(struct radeon_device *rdev)
WREG32(DC_HPD4_INT_CONTROL, hpd4);
WREG32(DC_HPD5_INT_CONTROL, hpd5);
WREG32(DC_HPD6_INT_CONTROL, hpd6);
if (rdev->family == CHIP_ARUBA)
WREG32(TN_CG_THERMAL_INT_CTRL, thermal_int);
else
WREG32(CG_THERMAL_INT, thermal_int);
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, afmt1);
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, afmt2);
@ -4181,6 +4587,7 @@ int evergreen_irq_process(struct radeon_device *rdev)
u32 ring_index;
bool queue_hotplug = false;
bool queue_hdmi = false;
bool queue_thermal = false;
if (!rdev->ih.enabled || rdev->shutdown)
return IRQ_NONE;
@ -4502,6 +4909,16 @@ restart_ih:
DRM_DEBUG("IH: DMA trap\n");
radeon_fence_process(rdev, R600_RING_TYPE_DMA_INDEX);
break;
case 230: /* thermal low to high */
DRM_DEBUG("IH: thermal low to high\n");
rdev->pm.dpm.thermal.high_to_low = false;
queue_thermal = true;
break;
case 231: /* thermal high to low */
DRM_DEBUG("IH: thermal high to low\n");
rdev->pm.dpm.thermal.high_to_low = true;
queue_thermal = true;
break;
case 233: /* GUI IDLE */
DRM_DEBUG("IH: GUI idle\n");
break;
@ -4524,6 +4941,8 @@ restart_ih:
schedule_work(&rdev->hotplug_work);
if (queue_hdmi)
schedule_work(&rdev->audio_work);
if (queue_thermal && rdev->pm.dpm_enabled)
schedule_work(&rdev->pm.dpm.thermal.work);
rdev->ih.rptr = rptr;
WREG32(IH_RB_RPTR, rdev->ih.rptr);
atomic_set(&rdev->ih.lock, 0);
@ -4680,6 +5099,8 @@ static int evergreen_startup(struct radeon_device *rdev)
/* enable pcie gen2 link */
evergreen_pcie_gen2_enable(rdev);
/* enable aspm */
evergreen_program_aspm(rdev);
if (ASIC_IS_DCE5(rdev)) {
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
@ -4725,6 +5146,18 @@ static int evergreen_startup(struct radeon_device *rdev)
dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
}
/* allocate rlc buffers */
if (rdev->flags & RADEON_IS_IGP) {
rdev->rlc.reg_list = sumo_rlc_save_restore_register_list;
rdev->rlc.reg_list_size = sumo_rlc_save_restore_register_list_size;
rdev->rlc.cs_data = evergreen_cs_data;
r = sumo_rlc_init(rdev);
if (r) {
DRM_ERROR("Failed to init rlc BOs!\n");
return r;
}
}
/* allocate wb buffer */
r = radeon_wb_init(rdev);
if (r)
@ -4956,6 +5389,8 @@ int evergreen_init(struct radeon_device *rdev)
r700_cp_fini(rdev);
r600_dma_fini(rdev);
r600_irq_fini(rdev);
if (rdev->flags & RADEON_IS_IGP)
sumo_rlc_fini(rdev);
radeon_wb_fini(rdev);
radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev);
@ -4984,6 +5419,8 @@ void evergreen_fini(struct radeon_device *rdev)
r700_cp_fini(rdev);
r600_dma_fini(rdev);
r600_irq_fini(rdev);
if (rdev->flags & RADEON_IS_IGP)
sumo_rlc_fini(rdev);
radeon_wb_fini(rdev);
radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev);
@ -5061,3 +5498,150 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
}
}
void evergreen_program_aspm(struct radeon_device *rdev)
{
u32 data, orig;
u32 pcie_lc_cntl, pcie_lc_cntl_old;
bool disable_l0s, disable_l1 = false, disable_plloff_in_l1 = false;
/* fusion_platform = true
* if the system is a fusion system
* (APU or DGPU in a fusion system).
* todo: check if the system is a fusion platform.
*/
bool fusion_platform = false;
if (!(rdev->flags & RADEON_IS_PCIE))
return;
switch (rdev->family) {
case CHIP_CYPRESS:
case CHIP_HEMLOCK:
case CHIP_JUNIPER:
case CHIP_REDWOOD:
case CHIP_CEDAR:
case CHIP_SUMO:
case CHIP_SUMO2:
case CHIP_PALM:
case CHIP_ARUBA:
disable_l0s = true;
break;
default:
disable_l0s = false;
break;
}
if (rdev->flags & RADEON_IS_IGP)
fusion_platform = true; /* XXX also dGPUs in a fusion system */
data = orig = RREG32_PIF_PHY0(PB0_PIF_PAIRING);
if (fusion_platform)
data &= ~MULTI_PIF;
else
data |= MULTI_PIF;
if (data != orig)
WREG32_PIF_PHY0(PB0_PIF_PAIRING, data);
data = orig = RREG32_PIF_PHY1(PB1_PIF_PAIRING);
if (fusion_platform)
data &= ~MULTI_PIF;
else
data |= MULTI_PIF;
if (data != orig)
WREG32_PIF_PHY1(PB1_PIF_PAIRING, data);
pcie_lc_cntl = pcie_lc_cntl_old = RREG32_PCIE_PORT(PCIE_LC_CNTL);
pcie_lc_cntl &= ~(LC_L0S_INACTIVITY_MASK | LC_L1_INACTIVITY_MASK);
if (!disable_l0s) {
if (rdev->family >= CHIP_BARTS)
pcie_lc_cntl |= LC_L0S_INACTIVITY(7);
else
pcie_lc_cntl |= LC_L0S_INACTIVITY(3);
}
if (!disable_l1) {
if (rdev->family >= CHIP_BARTS)
pcie_lc_cntl |= LC_L1_INACTIVITY(7);
else
pcie_lc_cntl |= LC_L1_INACTIVITY(8);
if (!disable_plloff_in_l1) {
data = orig = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_0);
data &= ~(PLL_POWER_STATE_IN_OFF_0_MASK | PLL_POWER_STATE_IN_TXS2_0_MASK);
data |= PLL_POWER_STATE_IN_OFF_0(7) | PLL_POWER_STATE_IN_TXS2_0(7);
if (data != orig)
WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_0, data);
data = orig = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_1);
data &= ~(PLL_POWER_STATE_IN_OFF_1_MASK | PLL_POWER_STATE_IN_TXS2_1_MASK);
data |= PLL_POWER_STATE_IN_OFF_1(7) | PLL_POWER_STATE_IN_TXS2_1(7);
if (data != orig)
WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_1, data);
data = orig = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_0);
data &= ~(PLL_POWER_STATE_IN_OFF_0_MASK | PLL_POWER_STATE_IN_TXS2_0_MASK);
data |= PLL_POWER_STATE_IN_OFF_0(7) | PLL_POWER_STATE_IN_TXS2_0(7);
if (data != orig)
WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_0, data);
data = orig = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_1);
data &= ~(PLL_POWER_STATE_IN_OFF_1_MASK | PLL_POWER_STATE_IN_TXS2_1_MASK);
data |= PLL_POWER_STATE_IN_OFF_1(7) | PLL_POWER_STATE_IN_TXS2_1(7);
if (data != orig)
WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_1, data);
if (rdev->family >= CHIP_BARTS) {
data = orig = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_0);
data &= ~PLL_RAMP_UP_TIME_0_MASK;
data |= PLL_RAMP_UP_TIME_0(4);
if (data != orig)
WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_0, data);
data = orig = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_1);
data &= ~PLL_RAMP_UP_TIME_1_MASK;
data |= PLL_RAMP_UP_TIME_1(4);
if (data != orig)
WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_1, data);
data = orig = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_0);
data &= ~PLL_RAMP_UP_TIME_0_MASK;
data |= PLL_RAMP_UP_TIME_0(4);
if (data != orig)
WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_0, data);
data = orig = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_1);
data &= ~PLL_RAMP_UP_TIME_1_MASK;
data |= PLL_RAMP_UP_TIME_1(4);
if (data != orig)
WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_1, data);
}
data = orig = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL);
data &= ~LC_DYN_LANES_PWR_STATE_MASK;
data |= LC_DYN_LANES_PWR_STATE(3);
if (data != orig)
WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, data);
if (rdev->family >= CHIP_BARTS) {
data = orig = RREG32_PIF_PHY0(PB0_PIF_CNTL);
data &= ~LS2_EXIT_TIME_MASK;
data |= LS2_EXIT_TIME(1);
if (data != orig)
WREG32_PIF_PHY0(PB0_PIF_CNTL, data);
data = orig = RREG32_PIF_PHY1(PB1_PIF_CNTL);
data &= ~LS2_EXIT_TIME_MASK;
data |= LS2_EXIT_TIME(1);
if (data != orig)
WREG32_PIF_PHY1(PB1_PIF_CNTL, data);
}
}
}
/* evergreen parts only */
if (rdev->family < CHIP_BARTS)
pcie_lc_cntl |= LC_PMI_TO_L1_DIS;
if (pcie_lc_cntl != pcie_lc_cntl_old)
WREG32_PCIE_PORT(PCIE_LC_CNTL, pcie_lc_cntl);
}

View File

@ -128,14 +128,7 @@ static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
uint32_t offset = dig->afmt->offset;
uint8_t *frame = buffer + 3;
/* Our header values (type, version, length) should be alright, Intel
* is using the same. Checksum function also seems to be OK, it works
* fine for audio infoframe. However calculated value is always lower
* by 2 in comparison to fglrx. It breaks displaying anything in case
* of TVs that strictly check the checksum. Hack it manually here to
* workaround this issue. */
frame[0x0] += 2;
uint8_t *header = buffer;
WREG32(AFMT_AVI_INFO0 + offset,
frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
@ -144,7 +137,7 @@ static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
WREG32(AFMT_AVI_INFO2 + offset,
frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
WREG32(AFMT_AVI_INFO3 + offset,
frame[0xC] | (frame[0xD] << 8));
frame[0xC] | (frame[0xD] << 8) | (header[1] << 24));
}
static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock)

View File

@ -24,7 +24,16 @@
#ifndef __EVERGREEN_REG_H__
#define __EVERGREEN_REG_H__
/* trinity */
#define TN_SMC_IND_INDEX_0 0x200
#define TN_SMC_IND_DATA_0 0x204
/* evergreen */
#define EVERGREEN_PIF_PHY0_INDEX 0x8
#define EVERGREEN_PIF_PHY0_DATA 0xc
#define EVERGREEN_PIF_PHY1_INDEX 0x10
#define EVERGREEN_PIF_PHY1_DATA 0x14
#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS 0x310
#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH 0x324
#define EVERGREEN_D3VGA_CONTROL 0x3e0
@ -40,6 +49,9 @@
#define EVERGREEN_AUDIO_PLL1_DIV 0x5b4
#define EVERGREEN_AUDIO_PLL1_UNK 0x5bc
#define EVERGREEN_CG_IND_ADDR 0x8f8
#define EVERGREEN_CG_IND_DATA 0x8fc
#define EVERGREEN_AUDIO_ENABLE 0x5e78
#define EVERGREEN_AUDIO_VENDOR_ID 0x5ec0

View File

@ -0,0 +1,67 @@
/*
* Copyright 2011 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.
*
*/
#ifndef __EVERGREEN_SMC_H__
#define __EVERGREEN_SMC_H__
#include "rv770_smc.h"
#pragma pack(push, 1)
#define SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE 16
struct SMC_Evergreen_MCRegisterAddress
{
uint16_t s0;
uint16_t s1;
};
typedef struct SMC_Evergreen_MCRegisterAddress SMC_Evergreen_MCRegisterAddress;
struct SMC_Evergreen_MCRegisterSet
{
uint32_t value[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE];
};
typedef struct SMC_Evergreen_MCRegisterSet SMC_Evergreen_MCRegisterSet;
struct SMC_Evergreen_MCRegisters
{
uint8_t last;
uint8_t reserved[3];
SMC_Evergreen_MCRegisterAddress address[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE];
SMC_Evergreen_MCRegisterSet data[5];
};
typedef struct SMC_Evergreen_MCRegisters SMC_Evergreen_MCRegisters;
#define EVERGREEN_SMC_FIRMWARE_HEADER_LOCATION 0x100
#define EVERGREEN_SMC_FIRMWARE_HEADER_softRegisters 0x0
#define EVERGREEN_SMC_FIRMWARE_HEADER_stateTable 0xC
#define EVERGREEN_SMC_FIRMWARE_HEADER_mcRegisterTable 0x20
#pragma pack(pop)
#endif

View File

@ -48,6 +48,293 @@
#define SUMO_GB_ADDR_CONFIG_GOLDEN 0x02010002
#define SUMO2_GB_ADDR_CONFIG_GOLDEN 0x02010002
/* pm registers */
#define SMC_MSG 0x20c
#define HOST_SMC_MSG(x) ((x) << 0)
#define HOST_SMC_MSG_MASK (0xff << 0)
#define HOST_SMC_MSG_SHIFT 0
#define HOST_SMC_RESP(x) ((x) << 8)
#define HOST_SMC_RESP_MASK (0xff << 8)
#define HOST_SMC_RESP_SHIFT 8
#define SMC_HOST_MSG(x) ((x) << 16)
#define SMC_HOST_MSG_MASK (0xff << 16)
#define SMC_HOST_MSG_SHIFT 16
#define SMC_HOST_RESP(x) ((x) << 24)
#define SMC_HOST_RESP_MASK (0xff << 24)
#define SMC_HOST_RESP_SHIFT 24
#define DCCG_DISP_SLOW_SELECT_REG 0x4fc
#define DCCG_DISP1_SLOW_SELECT(x) ((x) << 0)
#define DCCG_DISP1_SLOW_SELECT_MASK (7 << 0)
#define DCCG_DISP1_SLOW_SELECT_SHIFT 0
#define DCCG_DISP2_SLOW_SELECT(x) ((x) << 4)
#define DCCG_DISP2_SLOW_SELECT_MASK (7 << 4)
#define DCCG_DISP2_SLOW_SELECT_SHIFT 4
#define CG_SPLL_FUNC_CNTL 0x600
#define SPLL_RESET (1 << 0)
#define SPLL_SLEEP (1 << 1)
#define SPLL_BYPASS_EN (1 << 3)
#define SPLL_REF_DIV(x) ((x) << 4)
#define SPLL_REF_DIV_MASK (0x3f << 4)
#define SPLL_PDIV_A(x) ((x) << 20)
#define SPLL_PDIV_A_MASK (0x7f << 20)
#define CG_SPLL_FUNC_CNTL_2 0x604
#define SCLK_MUX_SEL(x) ((x) << 0)
#define SCLK_MUX_SEL_MASK (0x1ff << 0)
#define CG_SPLL_FUNC_CNTL_3 0x608
#define SPLL_FB_DIV(x) ((x) << 0)
#define SPLL_FB_DIV_MASK (0x3ffffff << 0)
#define SPLL_DITHEN (1 << 28)
#define MPLL_CNTL_MODE 0x61c
# define SS_SSEN (1 << 24)
# define SS_DSMODE_EN (1 << 25)
#define MPLL_AD_FUNC_CNTL 0x624
#define CLKF(x) ((x) << 0)
#define CLKF_MASK (0x7f << 0)
#define CLKR(x) ((x) << 7)
#define CLKR_MASK (0x1f << 7)
#define CLKFRAC(x) ((x) << 12)
#define CLKFRAC_MASK (0x1f << 12)
#define YCLK_POST_DIV(x) ((x) << 17)
#define YCLK_POST_DIV_MASK (3 << 17)
#define IBIAS(x) ((x) << 20)
#define IBIAS_MASK (0x3ff << 20)
#define RESET (1 << 30)
#define PDNB (1 << 31)
#define MPLL_AD_FUNC_CNTL_2 0x628
#define BYPASS (1 << 19)
#define BIAS_GEN_PDNB (1 << 24)
#define RESET_EN (1 << 25)
#define VCO_MODE (1 << 29)
#define MPLL_DQ_FUNC_CNTL 0x62c
#define MPLL_DQ_FUNC_CNTL_2 0x630
#define GENERAL_PWRMGT 0x63c
# define GLOBAL_PWRMGT_EN (1 << 0)
# define STATIC_PM_EN (1 << 1)
# define THERMAL_PROTECTION_DIS (1 << 2)
# define THERMAL_PROTECTION_TYPE (1 << 3)
# define ENABLE_GEN2PCIE (1 << 4)
# define ENABLE_GEN2XSP (1 << 5)
# define SW_SMIO_INDEX(x) ((x) << 6)
# define SW_SMIO_INDEX_MASK (3 << 6)
# define SW_SMIO_INDEX_SHIFT 6
# define LOW_VOLT_D2_ACPI (1 << 8)
# define LOW_VOLT_D3_ACPI (1 << 9)
# define VOLT_PWRMGT_EN (1 << 10)
# define BACKBIAS_PAD_EN (1 << 18)
# define BACKBIAS_VALUE (1 << 19)
# define DYN_SPREAD_SPECTRUM_EN (1 << 23)
# define AC_DC_SW (1 << 24)
#define SCLK_PWRMGT_CNTL 0x644
# define SCLK_PWRMGT_OFF (1 << 0)
# define SCLK_LOW_D1 (1 << 1)
# define FIR_RESET (1 << 4)
# define FIR_FORCE_TREND_SEL (1 << 5)
# define FIR_TREND_MODE (1 << 6)
# define DYN_GFX_CLK_OFF_EN (1 << 7)
# define GFX_CLK_FORCE_ON (1 << 8)
# define GFX_CLK_REQUEST_OFF (1 << 9)
# define GFX_CLK_FORCE_OFF (1 << 10)
# define GFX_CLK_OFF_ACPI_D1 (1 << 11)
# define GFX_CLK_OFF_ACPI_D2 (1 << 12)
# define GFX_CLK_OFF_ACPI_D3 (1 << 13)
# define DYN_LIGHT_SLEEP_EN (1 << 14)
#define MCLK_PWRMGT_CNTL 0x648
# define DLL_SPEED(x) ((x) << 0)
# define DLL_SPEED_MASK (0x1f << 0)
# define MPLL_PWRMGT_OFF (1 << 5)
# define DLL_READY (1 << 6)
# define MC_INT_CNTL (1 << 7)
# define MRDCKA0_PDNB (1 << 8)
# define MRDCKA1_PDNB (1 << 9)
# define MRDCKB0_PDNB (1 << 10)
# define MRDCKB1_PDNB (1 << 11)
# define MRDCKC0_PDNB (1 << 12)
# define MRDCKC1_PDNB (1 << 13)
# define MRDCKD0_PDNB (1 << 14)
# define MRDCKD1_PDNB (1 << 15)
# define MRDCKA0_RESET (1 << 16)
# define MRDCKA1_RESET (1 << 17)
# define MRDCKB0_RESET (1 << 18)
# define MRDCKB1_RESET (1 << 19)
# define MRDCKC0_RESET (1 << 20)
# define MRDCKC1_RESET (1 << 21)
# define MRDCKD0_RESET (1 << 22)
# define MRDCKD1_RESET (1 << 23)
# define DLL_READY_READ (1 << 24)
# define USE_DISPLAY_GAP (1 << 25)
# define USE_DISPLAY_URGENT_NORMAL (1 << 26)
# define MPLL_TURNOFF_D2 (1 << 28)
#define DLL_CNTL 0x64c
# define MRDCKA0_BYPASS (1 << 24)
# define MRDCKA1_BYPASS (1 << 25)
# define MRDCKB0_BYPASS (1 << 26)
# define MRDCKB1_BYPASS (1 << 27)
# define MRDCKC0_BYPASS (1 << 28)
# define MRDCKC1_BYPASS (1 << 29)
# define MRDCKD0_BYPASS (1 << 30)
# define MRDCKD1_BYPASS (1 << 31)
#define CG_AT 0x6d4
# define CG_R(x) ((x) << 0)
# define CG_R_MASK (0xffff << 0)
# define CG_L(x) ((x) << 16)
# define CG_L_MASK (0xffff << 16)
#define CG_DISPLAY_GAP_CNTL 0x714
# define DISP1_GAP(x) ((x) << 0)
# define DISP1_GAP_MASK (3 << 0)
# define DISP2_GAP(x) ((x) << 2)
# define DISP2_GAP_MASK (3 << 2)
# define VBI_TIMER_COUNT(x) ((x) << 4)
# define VBI_TIMER_COUNT_MASK (0x3fff << 4)
# define VBI_TIMER_UNIT(x) ((x) << 20)
# define VBI_TIMER_UNIT_MASK (7 << 20)
# define DISP1_GAP_MCHG(x) ((x) << 24)
# define DISP1_GAP_MCHG_MASK (3 << 24)
# define DISP2_GAP_MCHG(x) ((x) << 26)
# define DISP2_GAP_MCHG_MASK (3 << 26)
#define CG_BIF_REQ_AND_RSP 0x7f4
#define CG_CLIENT_REQ(x) ((x) << 0)
#define CG_CLIENT_REQ_MASK (0xff << 0)
#define CG_CLIENT_REQ_SHIFT 0
#define CG_CLIENT_RESP(x) ((x) << 8)
#define CG_CLIENT_RESP_MASK (0xff << 8)
#define CG_CLIENT_RESP_SHIFT 8
#define CLIENT_CG_REQ(x) ((x) << 16)
#define CLIENT_CG_REQ_MASK (0xff << 16)
#define CLIENT_CG_REQ_SHIFT 16
#define CLIENT_CG_RESP(x) ((x) << 24)
#define CLIENT_CG_RESP_MASK (0xff << 24)
#define CLIENT_CG_RESP_SHIFT 24
#define CG_SPLL_SPREAD_SPECTRUM 0x790
#define SSEN (1 << 0)
#define CG_SPLL_SPREAD_SPECTRUM_2 0x794
#define MPLL_SS1 0x85c
#define CLKV(x) ((x) << 0)
#define CLKV_MASK (0x3ffffff << 0)
#define MPLL_SS2 0x860
#define CLKS(x) ((x) << 0)
#define CLKS_MASK (0xfff << 0)
#define CG_IND_ADDR 0x8f8
#define CG_IND_DATA 0x8fc
/* CGIND regs */
#define CG_CGTT_LOCAL_0 0x00
#define CG_CGTT_LOCAL_1 0x01
#define CG_CGTT_LOCAL_2 0x02
#define CG_CGTT_LOCAL_3 0x03
#define CG_CGLS_TILE_0 0x20
#define CG_CGLS_TILE_1 0x21
#define CG_CGLS_TILE_2 0x22
#define CG_CGLS_TILE_3 0x23
#define CG_CGLS_TILE_4 0x24
#define CG_CGLS_TILE_5 0x25
#define CG_CGLS_TILE_6 0x26
#define CG_CGLS_TILE_7 0x27
#define CG_CGLS_TILE_8 0x28
#define CG_CGLS_TILE_9 0x29
#define CG_CGLS_TILE_10 0x2a
#define CG_CGLS_TILE_11 0x2b
#define VM_L2_CG 0x15c0
#define MC_CONFIG 0x2000
#define MC_CONFIG_MCD 0x20a0
#define MC_CG_CONFIG_MCD 0x20a4
#define MC_RD_ENABLE_MCD(x) ((x) << 8)
#define MC_RD_ENABLE_MCD_MASK (7 << 8)
#define MC_HUB_MISC_HUB_CG 0x20b8
#define MC_HUB_MISC_VM_CG 0x20bc
#define MC_HUB_MISC_SIP_CG 0x20c0
#define MC_XPB_CLK_GAT 0x2478
#define MC_CG_CONFIG 0x25bc
#define MC_RD_ENABLE(x) ((x) << 4)
#define MC_RD_ENABLE_MASK (3 << 4)
#define MC_CITF_MISC_RD_CG 0x2648
#define MC_CITF_MISC_WR_CG 0x264c
#define MC_CITF_MISC_VM_CG 0x2650
# define MEM_LS_ENABLE (1 << 19)
#define MC_ARB_BURST_TIME 0x2808
#define STATE0(x) ((x) << 0)
#define STATE0_MASK (0x1f << 0)
#define STATE1(x) ((x) << 5)
#define STATE1_MASK (0x1f << 5)
#define STATE2(x) ((x) << 10)
#define STATE2_MASK (0x1f << 10)
#define STATE3(x) ((x) << 15)
#define STATE3_MASK (0x1f << 15)
#define MC_SEQ_RAS_TIMING 0x28a0
#define MC_SEQ_CAS_TIMING 0x28a4
#define MC_SEQ_MISC_TIMING 0x28a8
#define MC_SEQ_MISC_TIMING2 0x28ac
#define MC_SEQ_RD_CTL_D0 0x28b4
#define MC_SEQ_RD_CTL_D1 0x28b8
#define MC_SEQ_WR_CTL_D0 0x28bc
#define MC_SEQ_WR_CTL_D1 0x28c0
#define MC_SEQ_STATUS_M 0x29f4
# define PMG_PWRSTATE (1 << 16)
#define MC_SEQ_MISC1 0x2a04
#define MC_SEQ_RESERVE_M 0x2a08
#define MC_PMG_CMD_EMRS 0x2a0c
#define MC_SEQ_MISC3 0x2a2c
#define MC_SEQ_MISC5 0x2a54
#define MC_SEQ_MISC6 0x2a58
#define MC_SEQ_MISC7 0x2a64
#define MC_SEQ_CG 0x2a68
#define CG_SEQ_REQ(x) ((x) << 0)
#define CG_SEQ_REQ_MASK (0xff << 0)
#define CG_SEQ_REQ_SHIFT 0
#define CG_SEQ_RESP(x) ((x) << 8)
#define CG_SEQ_RESP_MASK (0xff << 8)
#define CG_SEQ_RESP_SHIFT 8
#define SEQ_CG_REQ(x) ((x) << 16)
#define SEQ_CG_REQ_MASK (0xff << 16)
#define SEQ_CG_REQ_SHIFT 16
#define SEQ_CG_RESP(x) ((x) << 24)
#define SEQ_CG_RESP_MASK (0xff << 24)
#define SEQ_CG_RESP_SHIFT 24
#define MC_SEQ_RAS_TIMING_LP 0x2a6c
#define MC_SEQ_CAS_TIMING_LP 0x2a70
#define MC_SEQ_MISC_TIMING_LP 0x2a74
#define MC_SEQ_MISC_TIMING2_LP 0x2a78
#define MC_SEQ_WR_CTL_D0_LP 0x2a7c
#define MC_SEQ_WR_CTL_D1_LP 0x2a80
#define MC_SEQ_PMG_CMD_EMRS_LP 0x2a84
#define MC_SEQ_PMG_CMD_MRS_LP 0x2a88
#define MC_PMG_CMD_MRS 0x2aac
#define MC_SEQ_RD_CTL_D0_LP 0x2b1c
#define MC_SEQ_RD_CTL_D1_LP 0x2b20
#define MC_PMG_CMD_MRS1 0x2b44
#define MC_SEQ_PMG_CMD_MRS1_LP 0x2b48
#define CGTS_SM_CTRL_REG 0x9150
/* Registers */
#define RCU_IND_INDEX 0x100
@ -90,6 +377,34 @@
#define CG_VCLK_STATUS 0x61c
#define CG_SCRATCH1 0x820
#define RLC_CNTL 0x3f00
# define RLC_ENABLE (1 << 0)
# define GFX_POWER_GATING_ENABLE (1 << 7)
# define GFX_POWER_GATING_SRC (1 << 8)
# define DYN_PER_SIMD_PG_ENABLE (1 << 27)
# define LB_CNT_SPIM_ACTIVE (1 << 30)
# define LOAD_BALANCE_ENABLE (1 << 31)
#define RLC_HB_BASE 0x3f10
#define RLC_HB_CNTL 0x3f0c
#define RLC_HB_RPTR 0x3f20
#define RLC_HB_WPTR 0x3f1c
#define RLC_HB_WPTR_LSB_ADDR 0x3f14
#define RLC_HB_WPTR_MSB_ADDR 0x3f18
#define RLC_MC_CNTL 0x3f44
#define RLC_UCODE_CNTL 0x3f48
#define RLC_UCODE_ADDR 0x3f2c
#define RLC_UCODE_DATA 0x3f30
/* new for TN */
#define TN_RLC_SAVE_AND_RESTORE_BASE 0x3f10
#define TN_RLC_LB_CNTR_MAX 0x3f14
#define TN_RLC_LB_CNTR_INIT 0x3f18
#define TN_RLC_CLEAR_STATE_RESTORE_BASE 0x3f20
#define TN_RLC_LB_INIT_SIMD_MASK 0x3fe4
#define TN_RLC_LB_ALWAYS_ACTIVE_SIMD_MASK 0x3fe8
#define TN_RLC_LB_PARAMS 0x3fec
#define GRBM_GFX_INDEX 0x802C
#define INSTANCE_INDEX(x) ((x) << 0)
#define SE_INDEX(x) ((x) << 16)
@ -503,6 +818,30 @@
#define CG_THERMAL_CTRL 0x72c
#define TOFFSET_MASK 0x00003FE0
#define TOFFSET_SHIFT 5
#define DIG_THERM_DPM(x) ((x) << 14)
#define DIG_THERM_DPM_MASK 0x003FC000
#define DIG_THERM_DPM_SHIFT 14
#define CG_THERMAL_INT 0x734
#define DIG_THERM_INTH(x) ((x) << 8)
#define DIG_THERM_INTH_MASK 0x0000FF00
#define DIG_THERM_INTH_SHIFT 8
#define DIG_THERM_INTL(x) ((x) << 16)
#define DIG_THERM_INTL_MASK 0x00FF0000
#define DIG_THERM_INTL_SHIFT 16
#define THERM_INT_MASK_HIGH (1 << 24)
#define THERM_INT_MASK_LOW (1 << 25)
#define TN_CG_THERMAL_INT_CTRL 0x738
#define TN_DIG_THERM_INTH(x) ((x) << 0)
#define TN_DIG_THERM_INTH_MASK 0x000000FF
#define TN_DIG_THERM_INTH_SHIFT 0
#define TN_DIG_THERM_INTL(x) ((x) << 8)
#define TN_DIG_THERM_INTL_MASK 0x0000FF00
#define TN_DIG_THERM_INTL_SHIFT 8
#define TN_THERM_INT_MASK_HIGH (1 << 24)
#define TN_THERM_INT_MASK_LOW (1 << 25)
#define CG_MULT_THERMAL_STATUS 0x740
#define ASIC_T(x) ((x) << 16)
#define ASIC_T_MASK 0x07FF0000
@ -510,6 +849,7 @@
#define CG_TS0_STATUS 0x760
#define TS0_ADC_DOUT_MASK 0x000003FF
#define TS0_ADC_DOUT_SHIFT 0
/* APU */
#define CG_THERMAL_STATUS 0x678
@ -992,7 +1332,48 @@
#define DMA_PACKET_CONSTANT_FILL 0xd
#define DMA_PACKET_NOP 0xf
/* PCIE link stuff */
/* PIF PHY0 indirect regs */
#define PB0_PIF_CNTL 0x10
# define LS2_EXIT_TIME(x) ((x) << 17)
# define LS2_EXIT_TIME_MASK (0x7 << 17)
# define LS2_EXIT_TIME_SHIFT 17
#define PB0_PIF_PAIRING 0x11
# define MULTI_PIF (1 << 25)
#define PB0_PIF_PWRDOWN_0 0x12
# define PLL_POWER_STATE_IN_TXS2_0(x) ((x) << 7)
# define PLL_POWER_STATE_IN_TXS2_0_MASK (0x7 << 7)
# define PLL_POWER_STATE_IN_TXS2_0_SHIFT 7
# define PLL_POWER_STATE_IN_OFF_0(x) ((x) << 10)
# define PLL_POWER_STATE_IN_OFF_0_MASK (0x7 << 10)
# define PLL_POWER_STATE_IN_OFF_0_SHIFT 10
# define PLL_RAMP_UP_TIME_0(x) ((x) << 24)
# define PLL_RAMP_UP_TIME_0_MASK (0x7 << 24)
# define PLL_RAMP_UP_TIME_0_SHIFT 24
#define PB0_PIF_PWRDOWN_1 0x13
# define PLL_POWER_STATE_IN_TXS2_1(x) ((x) << 7)
# define PLL_POWER_STATE_IN_TXS2_1_MASK (0x7 << 7)
# define PLL_POWER_STATE_IN_TXS2_1_SHIFT 7
# define PLL_POWER_STATE_IN_OFF_1(x) ((x) << 10)
# define PLL_POWER_STATE_IN_OFF_1_MASK (0x7 << 10)
# define PLL_POWER_STATE_IN_OFF_1_SHIFT 10
# define PLL_RAMP_UP_TIME_1(x) ((x) << 24)
# define PLL_RAMP_UP_TIME_1_MASK (0x7 << 24)
# define PLL_RAMP_UP_TIME_1_SHIFT 24
/* PIF PHY1 indirect regs */
#define PB1_PIF_CNTL 0x10
#define PB1_PIF_PAIRING 0x11
#define PB1_PIF_PWRDOWN_0 0x12
#define PB1_PIF_PWRDOWN_1 0x13
/* PCIE PORT indirect regs */
#define PCIE_LC_CNTL 0xa0
# define LC_L0S_INACTIVITY(x) ((x) << 8)
# define LC_L0S_INACTIVITY_MASK (0xf << 8)
# define LC_L0S_INACTIVITY_SHIFT 8
# define LC_L1_INACTIVITY(x) ((x) << 12)
# define LC_L1_INACTIVITY_MASK (0xf << 12)
# define LC_L1_INACTIVITY_SHIFT 12
# define LC_PMI_TO_L1_DIS (1 << 16)
# define LC_ASPM_TO_L1_DIS (1 << 24)
#define PCIE_LC_TRAINING_CNTL 0xa1 /* PCIE_P */
#define PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE_P */
# define LC_LINK_WIDTH_SHIFT 0
@ -1012,6 +1393,9 @@
# define LC_SHORT_RECONFIG_EN (1 << 11)
# define LC_UPCONFIGURE_SUPPORT (1 << 12)
# define LC_UPCONFIGURE_DIS (1 << 13)
# define LC_DYN_LANES_PWR_STATE(x) ((x) << 21)
# define LC_DYN_LANES_PWR_STATE_MASK (0x3 << 21)
# define LC_DYN_LANES_PWR_STATE_SHIFT 21
#define PCIE_LC_SPEED_CNTL 0xa4 /* PCIE_P */
# define LC_GEN2_EN_STRAP (1 << 0)
# define LC_TARGET_LINK_SPEED_OVERRIDE_EN (1 << 1)
@ -1020,6 +1404,9 @@
# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK (0x3 << 8)
# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT 3
# define LC_CURRENT_DATA_RATE (1 << 11)
# define LC_HW_VOLTAGE_IF_CONTROL(x) ((x) << 12)
# define LC_HW_VOLTAGE_IF_CONTROL_MASK (3 << 12)
# define LC_HW_VOLTAGE_IF_CONTROL_SHIFT 12
# define LC_VOLTAGE_TIMER_SEL_MASK (0xf << 14)
# define LC_CLR_FAILED_SPD_CHANGE_CNT (1 << 21)
# define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 23)

View File

@ -33,6 +33,135 @@
#include "atom.h"
#include "ni_reg.h"
#include "cayman_blit_shaders.h"
#include "radeon_ucode.h"
#include "clearstate_cayman.h"
static u32 tn_rlc_save_restore_register_list[] =
{
0x98fc,
0x98f0,
0x9834,
0x9838,
0x9870,
0x9874,
0x8a14,
0x8b24,
0x8bcc,
0x8b10,
0x8c30,
0x8d00,
0x8d04,
0x8c00,
0x8c04,
0x8c10,
0x8c14,
0x8d8c,
0x8cf0,
0x8e38,
0x9508,
0x9688,
0x9608,
0x960c,
0x9610,
0x9614,
0x88c4,
0x8978,
0x88d4,
0x900c,
0x9100,
0x913c,
0x90e8,
0x9354,
0xa008,
0x98f8,
0x9148,
0x914c,
0x3f94,
0x98f4,
0x9b7c,
0x3f8c,
0x8950,
0x8954,
0x8a18,
0x8b28,
0x9144,
0x3f90,
0x915c,
0x9160,
0x9178,
0x917c,
0x9180,
0x918c,
0x9190,
0x9194,
0x9198,
0x919c,
0x91a8,
0x91ac,
0x91b0,
0x91b4,
0x91b8,
0x91c4,
0x91c8,
0x91cc,
0x91d0,
0x91d4,
0x91e0,
0x91e4,
0x91ec,
0x91f0,
0x91f4,
0x9200,
0x9204,
0x929c,
0x8030,
0x9150,
0x9a60,
0x920c,
0x9210,
0x9228,
0x922c,
0x9244,
0x9248,
0x91e8,
0x9294,
0x9208,
0x9224,
0x9240,
0x9220,
0x923c,
0x9258,
0x9744,
0xa200,
0xa204,
0xa208,
0xa20c,
0x8d58,
0x9030,
0x9034,
0x9038,
0x903c,
0x9040,
0x9654,
0x897c,
0xa210,
0xa214,
0x9868,
0xa02c,
0x9664,
0x9698,
0x949c,
0x8e10,
0x8e18,
0x8c50,
0x8c58,
0x8c60,
0x8c68,
0x89b4,
0x9830,
0x802c,
};
static u32 tn_rlc_save_restore_register_list_size = ARRAY_SIZE(tn_rlc_save_restore_register_list);
extern bool evergreen_is_display_hung(struct radeon_device *rdev);
extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev);
@ -44,36 +173,29 @@ extern void evergreen_irq_suspend(struct radeon_device *rdev);
extern int evergreen_mc_init(struct radeon_device *rdev);
extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev);
extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
extern void si_rlc_fini(struct radeon_device *rdev);
extern int si_rlc_init(struct radeon_device *rdev);
#define EVERGREEN_PFP_UCODE_SIZE 1120
#define EVERGREEN_PM4_UCODE_SIZE 1376
#define EVERGREEN_RLC_UCODE_SIZE 768
#define BTC_MC_UCODE_SIZE 6024
#define CAYMAN_PFP_UCODE_SIZE 2176
#define CAYMAN_PM4_UCODE_SIZE 2176
#define CAYMAN_RLC_UCODE_SIZE 1024
#define CAYMAN_MC_UCODE_SIZE 6037
#define ARUBA_RLC_UCODE_SIZE 1536
extern void evergreen_program_aspm(struct radeon_device *rdev);
extern void sumo_rlc_fini(struct radeon_device *rdev);
extern int sumo_rlc_init(struct radeon_device *rdev);
/* Firmware Names */
MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
MODULE_FIRMWARE("radeon/BARTS_me.bin");
MODULE_FIRMWARE("radeon/BARTS_mc.bin");
MODULE_FIRMWARE("radeon/BARTS_smc.bin");
MODULE_FIRMWARE("radeon/BTC_rlc.bin");
MODULE_FIRMWARE("radeon/TURKS_pfp.bin");
MODULE_FIRMWARE("radeon/TURKS_me.bin");
MODULE_FIRMWARE("radeon/TURKS_mc.bin");
MODULE_FIRMWARE("radeon/TURKS_smc.bin");
MODULE_FIRMWARE("radeon/CAICOS_pfp.bin");
MODULE_FIRMWARE("radeon/CAICOS_me.bin");
MODULE_FIRMWARE("radeon/CAICOS_mc.bin");
MODULE_FIRMWARE("radeon/CAICOS_smc.bin");
MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin");
MODULE_FIRMWARE("radeon/CAYMAN_me.bin");
MODULE_FIRMWARE("radeon/CAYMAN_mc.bin");
MODULE_FIRMWARE("radeon/CAYMAN_rlc.bin");
MODULE_FIRMWARE("radeon/CAYMAN_smc.bin");
MODULE_FIRMWARE("radeon/ARUBA_pfp.bin");
MODULE_FIRMWARE("radeon/ARUBA_me.bin");
MODULE_FIRMWARE("radeon/ARUBA_rlc.bin");
@ -566,6 +688,7 @@ int ni_init_microcode(struct radeon_device *rdev)
const char *chip_name;
const char *rlc_chip_name;
size_t pfp_req_size, me_req_size, rlc_req_size, mc_req_size;
size_t smc_req_size = 0;
char fw_name[30];
int err;
@ -586,6 +709,7 @@ int ni_init_microcode(struct radeon_device *rdev)
me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
mc_req_size = BTC_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(BARTS_SMC_UCODE_SIZE, 4);
break;
case CHIP_TURKS:
chip_name = "TURKS";
@ -594,6 +718,7 @@ int ni_init_microcode(struct radeon_device *rdev)
me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
mc_req_size = BTC_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(TURKS_SMC_UCODE_SIZE, 4);
break;
case CHIP_CAICOS:
chip_name = "CAICOS";
@ -602,6 +727,7 @@ int ni_init_microcode(struct radeon_device *rdev)
me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
mc_req_size = BTC_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(CAICOS_SMC_UCODE_SIZE, 4);
break;
case CHIP_CAYMAN:
chip_name = "CAYMAN";
@ -610,6 +736,7 @@ int ni_init_microcode(struct radeon_device *rdev)
me_req_size = CAYMAN_PM4_UCODE_SIZE * 4;
rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4;
mc_req_size = CAYMAN_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(CAYMAN_SMC_UCODE_SIZE, 4);
break;
case CHIP_ARUBA:
chip_name = "ARUBA";
@ -672,6 +799,20 @@ int ni_init_microcode(struct radeon_device *rdev)
err = -EINVAL;
}
}
if ((rdev->family >= CHIP_BARTS) && (rdev->family <= CHIP_CAYMAN)) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
err = request_firmware(&rdev->smc_fw, fw_name, &pdev->dev);
if (err)
goto out;
if (rdev->smc_fw->size != smc_req_size) {
printk(KERN_ERR
"ni_mc: Bogus length %zu in firmware \"%s\"\n",
rdev->mc_fw->size, fw_name);
err = -EINVAL;
}
}
out:
platform_device_unregister(pdev);
@ -692,6 +833,14 @@ out:
return err;
}
int tn_get_temp(struct radeon_device *rdev)
{
u32 temp = RREG32_SMC(TN_CURRENT_GNB_TEMP) & 0x7ff;
int actual_temp = (temp / 8) - 49;
return actual_temp * 1000;
}
/*
* Core functions
*/
@ -1027,6 +1176,16 @@ static void cayman_gpu_init(struct radeon_device *rdev)
WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3));
udelay(50);
/* set clockgating golden values on TN */
if (rdev->family == CHIP_ARUBA) {
tmp = RREG32_CG(CG_CGTT_LOCAL_0);
tmp &= ~0x00380000;
WREG32_CG(CG_CGTT_LOCAL_0, tmp);
tmp = RREG32_CG(CG_CGTT_LOCAL_1);
tmp &= ~0x0e000000;
WREG32_CG(CG_CGTT_LOCAL_1, tmp);
}
}
/*
@ -1928,6 +2087,8 @@ static int cayman_startup(struct radeon_device *rdev)
/* enable pcie gen2 link */
evergreen_pcie_gen2_enable(rdev);
/* enable aspm */
evergreen_program_aspm(rdev);
if (rdev->flags & RADEON_IS_IGP) {
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
@ -1972,7 +2133,10 @@ static int cayman_startup(struct radeon_device *rdev)
/* allocate rlc buffers */
if (rdev->flags & RADEON_IS_IGP) {
r = si_rlc_init(rdev);
rdev->rlc.reg_list = tn_rlc_save_restore_register_list;
rdev->rlc.reg_list_size = tn_rlc_save_restore_register_list_size;
rdev->rlc.cs_data = cayman_cs_data;
r = sumo_rlc_init(rdev);
if (r) {
DRM_ERROR("Failed to init rlc BOs!\n");
return r;
@ -2229,7 +2393,7 @@ int cayman_init(struct radeon_device *rdev)
cayman_dma_fini(rdev);
r600_irq_fini(rdev);
if (rdev->flags & RADEON_IS_IGP)
si_rlc_fini(rdev);
sumo_rlc_fini(rdev);
radeon_wb_fini(rdev);
radeon_ib_pool_fini(rdev);
radeon_vm_manager_fini(rdev);
@ -2260,7 +2424,7 @@ void cayman_fini(struct radeon_device *rdev)
cayman_dma_fini(rdev);
r600_irq_fini(rdev);
if (rdev->flags & RADEON_IS_IGP)
si_rlc_fini(rdev);
sumo_rlc_fini(rdev);
radeon_wb_fini(rdev);
radeon_vm_manager_fini(rdev);
radeon_ib_pool_fini(rdev);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,248 @@
/*
* Copyright 2012 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.
*
*/
#ifndef __NI_DPM_H__
#define __NI_DPM_H__
#include "cypress_dpm.h"
#include "btc_dpm.h"
#include "nislands_smc.h"
struct ni_clock_registers {
u32 cg_spll_func_cntl;
u32 cg_spll_func_cntl_2;
u32 cg_spll_func_cntl_3;
u32 cg_spll_func_cntl_4;
u32 cg_spll_spread_spectrum;
u32 cg_spll_spread_spectrum_2;
u32 mclk_pwrmgt_cntl;
u32 dll_cntl;
u32 mpll_ad_func_cntl;
u32 mpll_ad_func_cntl_2;
u32 mpll_dq_func_cntl;
u32 mpll_dq_func_cntl_2;
u32 mpll_ss1;
u32 mpll_ss2;
};
struct ni_mc_reg_entry {
u32 mclk_max;
u32 mc_data[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE];
};
struct ni_mc_reg_table {
u8 last;
u8 num_entries;
u16 valid_flag;
struct ni_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES];
SMC_NIslands_MCRegisterAddress mc_reg_address[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE];
};
#define NISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT 2
enum ni_dc_cac_level
{
NISLANDS_DCCAC_LEVEL_0 = 0,
NISLANDS_DCCAC_LEVEL_1,
NISLANDS_DCCAC_LEVEL_2,
NISLANDS_DCCAC_LEVEL_3,
NISLANDS_DCCAC_LEVEL_4,
NISLANDS_DCCAC_LEVEL_5,
NISLANDS_DCCAC_LEVEL_6,
NISLANDS_DCCAC_LEVEL_7,
NISLANDS_DCCAC_MAX_LEVELS
};
struct ni_leakage_coeffients
{
u32 at;
u32 bt;
u32 av;
u32 bv;
s32 t_slope;
s32 t_intercept;
u32 t_ref;
};
struct ni_cac_data
{
struct ni_leakage_coeffients leakage_coefficients;
u32 i_leakage;
s32 leakage_minimum_temperature;
u32 pwr_const;
u32 dc_cac_value;
u32 bif_cac_value;
u32 lkge_pwr;
u8 mc_wr_weight;
u8 mc_rd_weight;
u8 allow_ovrflw;
u8 num_win_tdp;
u8 l2num_win_tdp;
u8 lts_truncate_n;
};
struct ni_cac_weights
{
u32 weight_tcp_sig0;
u32 weight_tcp_sig1;
u32 weight_ta_sig;
u32 weight_tcc_en0;
u32 weight_tcc_en1;
u32 weight_tcc_en2;
u32 weight_cb_en0;
u32 weight_cb_en1;
u32 weight_cb_en2;
u32 weight_cb_en3;
u32 weight_db_sig0;
u32 weight_db_sig1;
u32 weight_db_sig2;
u32 weight_db_sig3;
u32 weight_sxm_sig0;
u32 weight_sxm_sig1;
u32 weight_sxm_sig2;
u32 weight_sxs_sig0;
u32 weight_sxs_sig1;
u32 weight_xbr_0;
u32 weight_xbr_1;
u32 weight_xbr_2;
u32 weight_spi_sig0;
u32 weight_spi_sig1;
u32 weight_spi_sig2;
u32 weight_spi_sig3;
u32 weight_spi_sig4;
u32 weight_spi_sig5;
u32 weight_lds_sig0;
u32 weight_lds_sig1;
u32 weight_sc;
u32 weight_bif;
u32 weight_cp;
u32 weight_pa_sig0;
u32 weight_pa_sig1;
u32 weight_vgt_sig0;
u32 weight_vgt_sig1;
u32 weight_vgt_sig2;
u32 weight_dc_sig0;
u32 weight_dc_sig1;
u32 weight_dc_sig2;
u32 weight_dc_sig3;
u32 weight_uvd_sig0;
u32 weight_uvd_sig1;
u32 weight_spare0;
u32 weight_spare1;
u32 weight_sq_vsp;
u32 weight_sq_vsp0;
u32 weight_sq_gpr;
u32 ovr_mode_spare_0;
u32 ovr_val_spare_0;
u32 ovr_mode_spare_1;
u32 ovr_val_spare_1;
u32 vsp;
u32 vsp0;
u32 gpr;
u8 mc_read_weight;
u8 mc_write_weight;
u32 tid_cnt;
u32 tid_unit;
u32 l2_lta_window_size;
u32 lts_truncate;
u32 dc_cac[NISLANDS_DCCAC_MAX_LEVELS];
u32 pcie_cac[SMC_NISLANDS_BIF_LUT_NUM_OF_ENTRIES];
bool enable_power_containment_by_default;
};
struct ni_ps {
u16 performance_level_count;
bool dc_compatible;
struct rv7xx_pl performance_levels[NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE];
};
struct ni_power_info {
/* must be first! */
struct evergreen_power_info eg;
struct ni_clock_registers clock_registers;
struct ni_mc_reg_table mc_reg_table;
u32 mclk_rtt_mode_threshold;
/* flags */
bool use_power_boost_limit;
bool support_cac_long_term_average;
bool cac_enabled;
bool cac_configuration_required;
bool driver_calculate_cac_leakage;
bool pc_enabled;
bool enable_power_containment;
bool enable_cac;
bool enable_sq_ramping;
/* smc offsets */
u16 arb_table_start;
u16 fan_table_start;
u16 cac_table_start;
u16 spll_table_start;
/* CAC stuff */
struct ni_cac_data cac_data;
u32 dc_cac_table[NISLANDS_DCCAC_MAX_LEVELS];
const struct ni_cac_weights *cac_weights;
u8 lta_window_size;
u8 lts_truncate;
struct ni_ps current_ps;
struct ni_ps requested_ps;
/* scratch structs */
SMC_NIslands_MCRegisters smc_mc_reg_table;
NISLANDS_SMC_STATETABLE smc_statetable;
};
#define NISLANDS_INITIAL_STATE_ARB_INDEX 0
#define NISLANDS_ACPI_STATE_ARB_INDEX 1
#define NISLANDS_ULV_STATE_ARB_INDEX 2
#define NISLANDS_DRIVER_STATE_ARB_INDEX 3
#define NISLANDS_DPM2_MAX_PULSE_SKIP 256
#define NISLANDS_DPM2_NEAR_TDP_DEC 10
#define NISLANDS_DPM2_ABOVE_SAFE_INC 5
#define NISLANDS_DPM2_BELOW_SAFE_INC 20
#define NISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT 80
#define NISLANDS_DPM2_MAXPS_PERCENT_H 90
#define NISLANDS_DPM2_MAXPS_PERCENT_M 0
#define NISLANDS_DPM2_SQ_RAMP_MAX_POWER 0x3FFF
#define NISLANDS_DPM2_SQ_RAMP_MIN_POWER 0x12
#define NISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15
#define NISLANDS_DPM2_SQ_RAMP_STI_SIZE 0x1E
#define NISLANDS_DPM2_SQ_RAMP_LTI_RATIO 0xF
int ni_copy_and_switch_arb_sets(struct radeon_device *rdev,
u32 arb_freq_src, u32 arb_freq_dest);
void ni_update_current_ps(struct radeon_device *rdev,
struct radeon_ps *rps);
void ni_update_requested_ps(struct radeon_device *rdev,
struct radeon_ps *rps);
void ni_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
struct radeon_ps *new_ps,
struct radeon_ps *old_ps);
void ni_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
struct radeon_ps *new_ps,
struct radeon_ps *old_ps);
#endif

View File

@ -489,6 +489,567 @@
# define CACHE_FLUSH_AND_INV_EVENT_TS (0x14 << 0)
# define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0)
/* TN SMU registers */
#define TN_CURRENT_GNB_TEMP 0x1F390
/* pm registers */
#define SMC_MSG 0x20c
#define HOST_SMC_MSG(x) ((x) << 0)
#define HOST_SMC_MSG_MASK (0xff << 0)
#define HOST_SMC_MSG_SHIFT 0
#define HOST_SMC_RESP(x) ((x) << 8)
#define HOST_SMC_RESP_MASK (0xff << 8)
#define HOST_SMC_RESP_SHIFT 8
#define SMC_HOST_MSG(x) ((x) << 16)
#define SMC_HOST_MSG_MASK (0xff << 16)
#define SMC_HOST_MSG_SHIFT 16
#define SMC_HOST_RESP(x) ((x) << 24)
#define SMC_HOST_RESP_MASK (0xff << 24)
#define SMC_HOST_RESP_SHIFT 24
#define CG_SPLL_FUNC_CNTL 0x600
#define SPLL_RESET (1 << 0)
#define SPLL_SLEEP (1 << 1)
#define SPLL_BYPASS_EN (1 << 3)
#define SPLL_REF_DIV(x) ((x) << 4)
#define SPLL_REF_DIV_MASK (0x3f << 4)
#define SPLL_PDIV_A(x) ((x) << 20)
#define SPLL_PDIV_A_MASK (0x7f << 20)
#define SPLL_PDIV_A_SHIFT 20
#define CG_SPLL_FUNC_CNTL_2 0x604
#define SCLK_MUX_SEL(x) ((x) << 0)
#define SCLK_MUX_SEL_MASK (0x1ff << 0)
#define CG_SPLL_FUNC_CNTL_3 0x608
#define SPLL_FB_DIV(x) ((x) << 0)
#define SPLL_FB_DIV_MASK (0x3ffffff << 0)
#define SPLL_FB_DIV_SHIFT 0
#define SPLL_DITHEN (1 << 28)
#define MPLL_CNTL_MODE 0x61c
# define SS_SSEN (1 << 24)
# define SS_DSMODE_EN (1 << 25)
#define MPLL_AD_FUNC_CNTL 0x624
#define CLKF(x) ((x) << 0)
#define CLKF_MASK (0x7f << 0)
#define CLKR(x) ((x) << 7)
#define CLKR_MASK (0x1f << 7)
#define CLKFRAC(x) ((x) << 12)
#define CLKFRAC_MASK (0x1f << 12)
#define YCLK_POST_DIV(x) ((x) << 17)
#define YCLK_POST_DIV_MASK (3 << 17)
#define IBIAS(x) ((x) << 20)
#define IBIAS_MASK (0x3ff << 20)
#define RESET (1 << 30)
#define PDNB (1 << 31)
#define MPLL_AD_FUNC_CNTL_2 0x628
#define BYPASS (1 << 19)
#define BIAS_GEN_PDNB (1 << 24)
#define RESET_EN (1 << 25)
#define VCO_MODE (1 << 29)
#define MPLL_DQ_FUNC_CNTL 0x62c
#define MPLL_DQ_FUNC_CNTL_2 0x630
#define GENERAL_PWRMGT 0x63c
# define GLOBAL_PWRMGT_EN (1 << 0)
# define STATIC_PM_EN (1 << 1)
# define THERMAL_PROTECTION_DIS (1 << 2)
# define THERMAL_PROTECTION_TYPE (1 << 3)
# define ENABLE_GEN2PCIE (1 << 4)
# define ENABLE_GEN2XSP (1 << 5)
# define SW_SMIO_INDEX(x) ((x) << 6)
# define SW_SMIO_INDEX_MASK (3 << 6)
# define SW_SMIO_INDEX_SHIFT 6
# define LOW_VOLT_D2_ACPI (1 << 8)
# define LOW_VOLT_D3_ACPI (1 << 9)
# define VOLT_PWRMGT_EN (1 << 10)
# define BACKBIAS_PAD_EN (1 << 18)
# define BACKBIAS_VALUE (1 << 19)
# define DYN_SPREAD_SPECTRUM_EN (1 << 23)
# define AC_DC_SW (1 << 24)
#define SCLK_PWRMGT_CNTL 0x644
# define SCLK_PWRMGT_OFF (1 << 0)
# define SCLK_LOW_D1 (1 << 1)
# define FIR_RESET (1 << 4)
# define FIR_FORCE_TREND_SEL (1 << 5)
# define FIR_TREND_MODE (1 << 6)
# define DYN_GFX_CLK_OFF_EN (1 << 7)
# define GFX_CLK_FORCE_ON (1 << 8)
# define GFX_CLK_REQUEST_OFF (1 << 9)
# define GFX_CLK_FORCE_OFF (1 << 10)
# define GFX_CLK_OFF_ACPI_D1 (1 << 11)
# define GFX_CLK_OFF_ACPI_D2 (1 << 12)
# define GFX_CLK_OFF_ACPI_D3 (1 << 13)
# define DYN_LIGHT_SLEEP_EN (1 << 14)
#define MCLK_PWRMGT_CNTL 0x648
# define DLL_SPEED(x) ((x) << 0)
# define DLL_SPEED_MASK (0x1f << 0)
# define MPLL_PWRMGT_OFF (1 << 5)
# define DLL_READY (1 << 6)
# define MC_INT_CNTL (1 << 7)
# define MRDCKA0_PDNB (1 << 8)
# define MRDCKA1_PDNB (1 << 9)
# define MRDCKB0_PDNB (1 << 10)
# define MRDCKB1_PDNB (1 << 11)
# define MRDCKC0_PDNB (1 << 12)
# define MRDCKC1_PDNB (1 << 13)
# define MRDCKD0_PDNB (1 << 14)
# define MRDCKD1_PDNB (1 << 15)
# define MRDCKA0_RESET (1 << 16)
# define MRDCKA1_RESET (1 << 17)
# define MRDCKB0_RESET (1 << 18)
# define MRDCKB1_RESET (1 << 19)
# define MRDCKC0_RESET (1 << 20)
# define MRDCKC1_RESET (1 << 21)
# define MRDCKD0_RESET (1 << 22)
# define MRDCKD1_RESET (1 << 23)
# define DLL_READY_READ (1 << 24)
# define USE_DISPLAY_GAP (1 << 25)
# define USE_DISPLAY_URGENT_NORMAL (1 << 26)
# define MPLL_TURNOFF_D2 (1 << 28)
#define DLL_CNTL 0x64c
# define MRDCKA0_BYPASS (1 << 24)
# define MRDCKA1_BYPASS (1 << 25)
# define MRDCKB0_BYPASS (1 << 26)
# define MRDCKB1_BYPASS (1 << 27)
# define MRDCKC0_BYPASS (1 << 28)
# define MRDCKC1_BYPASS (1 << 29)
# define MRDCKD0_BYPASS (1 << 30)
# define MRDCKD1_BYPASS (1 << 31)
#define CG_AT 0x6d4
# define CG_R(x) ((x) << 0)
# define CG_R_MASK (0xffff << 0)
# define CG_L(x) ((x) << 16)
# define CG_L_MASK (0xffff << 16)
#define CG_BIF_REQ_AND_RSP 0x7f4
#define CG_CLIENT_REQ(x) ((x) << 0)
#define CG_CLIENT_REQ_MASK (0xff << 0)
#define CG_CLIENT_REQ_SHIFT 0
#define CG_CLIENT_RESP(x) ((x) << 8)
#define CG_CLIENT_RESP_MASK (0xff << 8)
#define CG_CLIENT_RESP_SHIFT 8
#define CLIENT_CG_REQ(x) ((x) << 16)
#define CLIENT_CG_REQ_MASK (0xff << 16)
#define CLIENT_CG_REQ_SHIFT 16
#define CLIENT_CG_RESP(x) ((x) << 24)
#define CLIENT_CG_RESP_MASK (0xff << 24)
#define CLIENT_CG_RESP_SHIFT 24
#define CG_SPLL_SPREAD_SPECTRUM 0x790
#define SSEN (1 << 0)
#define CLK_S(x) ((x) << 4)
#define CLK_S_MASK (0xfff << 4)
#define CLK_S_SHIFT 4
#define CG_SPLL_SPREAD_SPECTRUM_2 0x794
#define CLK_V(x) ((x) << 0)
#define CLK_V_MASK (0x3ffffff << 0)
#define CLK_V_SHIFT 0
#define SMC_SCRATCH0 0x81c
#define CG_SPLL_FUNC_CNTL_4 0x850
#define MPLL_SS1 0x85c
#define CLKV(x) ((x) << 0)
#define CLKV_MASK (0x3ffffff << 0)
#define MPLL_SS2 0x860
#define CLKS(x) ((x) << 0)
#define CLKS_MASK (0xfff << 0)
#define CG_CAC_CTRL 0x88c
#define TID_CNT(x) ((x) << 0)
#define TID_CNT_MASK (0x3fff << 0)
#define TID_UNIT(x) ((x) << 14)
#define TID_UNIT_MASK (0xf << 14)
#define CG_IND_ADDR 0x8f8
#define CG_IND_DATA 0x8fc
/* CGIND regs */
#define CG_CGTT_LOCAL_0 0x00
#define CG_CGTT_LOCAL_1 0x01
#define MC_CG_CONFIG 0x25bc
#define MCDW_WR_ENABLE (1 << 0)
#define MCDX_WR_ENABLE (1 << 1)
#define MCDY_WR_ENABLE (1 << 2)
#define MCDZ_WR_ENABLE (1 << 3)
#define MC_RD_ENABLE(x) ((x) << 4)
#define MC_RD_ENABLE_MASK (3 << 4)
#define INDEX(x) ((x) << 6)
#define INDEX_MASK (0xfff << 6)
#define INDEX_SHIFT 6
#define MC_ARB_CAC_CNTL 0x2750
#define ENABLE (1 << 0)
#define READ_WEIGHT(x) ((x) << 1)
#define READ_WEIGHT_MASK (0x3f << 1)
#define READ_WEIGHT_SHIFT 1
#define WRITE_WEIGHT(x) ((x) << 7)
#define WRITE_WEIGHT_MASK (0x3f << 7)
#define WRITE_WEIGHT_SHIFT 7
#define ALLOW_OVERFLOW (1 << 13)
#define MC_ARB_DRAM_TIMING 0x2774
#define MC_ARB_DRAM_TIMING2 0x2778
#define MC_ARB_RFSH_RATE 0x27b0
#define POWERMODE0(x) ((x) << 0)
#define POWERMODE0_MASK (0xff << 0)
#define POWERMODE0_SHIFT 0
#define POWERMODE1(x) ((x) << 8)
#define POWERMODE1_MASK (0xff << 8)
#define POWERMODE1_SHIFT 8
#define POWERMODE2(x) ((x) << 16)
#define POWERMODE2_MASK (0xff << 16)
#define POWERMODE2_SHIFT 16
#define POWERMODE3(x) ((x) << 24)
#define POWERMODE3_MASK (0xff << 24)
#define POWERMODE3_SHIFT 24
#define MC_ARB_CG 0x27e8
#define CG_ARB_REQ(x) ((x) << 0)
#define CG_ARB_REQ_MASK (0xff << 0)
#define CG_ARB_REQ_SHIFT 0
#define CG_ARB_RESP(x) ((x) << 8)
#define CG_ARB_RESP_MASK (0xff << 8)
#define CG_ARB_RESP_SHIFT 8
#define ARB_CG_REQ(x) ((x) << 16)
#define ARB_CG_REQ_MASK (0xff << 16)
#define ARB_CG_REQ_SHIFT 16
#define ARB_CG_RESP(x) ((x) << 24)
#define ARB_CG_RESP_MASK (0xff << 24)
#define ARB_CG_RESP_SHIFT 24
#define MC_ARB_DRAM_TIMING_1 0x27f0
#define MC_ARB_DRAM_TIMING_2 0x27f4
#define MC_ARB_DRAM_TIMING_3 0x27f8
#define MC_ARB_DRAM_TIMING2_1 0x27fc
#define MC_ARB_DRAM_TIMING2_2 0x2800
#define MC_ARB_DRAM_TIMING2_3 0x2804
#define MC_ARB_BURST_TIME 0x2808
#define STATE0(x) ((x) << 0)
#define STATE0_MASK (0x1f << 0)
#define STATE0_SHIFT 0
#define STATE1(x) ((x) << 5)
#define STATE1_MASK (0x1f << 5)
#define STATE1_SHIFT 5
#define STATE2(x) ((x) << 10)
#define STATE2_MASK (0x1f << 10)
#define STATE2_SHIFT 10
#define STATE3(x) ((x) << 15)
#define STATE3_MASK (0x1f << 15)
#define STATE3_SHIFT 15
#define MC_CG_DATAPORT 0x2884
#define MC_SEQ_RAS_TIMING 0x28a0
#define MC_SEQ_CAS_TIMING 0x28a4
#define MC_SEQ_MISC_TIMING 0x28a8
#define MC_SEQ_MISC_TIMING2 0x28ac
#define MC_SEQ_PMG_TIMING 0x28b0
#define MC_SEQ_RD_CTL_D0 0x28b4
#define MC_SEQ_RD_CTL_D1 0x28b8
#define MC_SEQ_WR_CTL_D0 0x28bc
#define MC_SEQ_WR_CTL_D1 0x28c0
#define MC_SEQ_MISC0 0x2a00
#define MC_SEQ_MISC0_GDDR5_SHIFT 28
#define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000
#define MC_SEQ_MISC0_GDDR5_VALUE 5
#define MC_SEQ_MISC1 0x2a04
#define MC_SEQ_RESERVE_M 0x2a08
#define MC_PMG_CMD_EMRS 0x2a0c
#define MC_SEQ_MISC3 0x2a2c
#define MC_SEQ_MISC5 0x2a54
#define MC_SEQ_MISC6 0x2a58
#define MC_SEQ_MISC7 0x2a64
#define MC_SEQ_RAS_TIMING_LP 0x2a6c
#define MC_SEQ_CAS_TIMING_LP 0x2a70
#define MC_SEQ_MISC_TIMING_LP 0x2a74
#define MC_SEQ_MISC_TIMING2_LP 0x2a78
#define MC_SEQ_WR_CTL_D0_LP 0x2a7c
#define MC_SEQ_WR_CTL_D1_LP 0x2a80
#define MC_SEQ_PMG_CMD_EMRS_LP 0x2a84
#define MC_SEQ_PMG_CMD_MRS_LP 0x2a88
#define MC_PMG_CMD_MRS 0x2aac
#define MC_SEQ_RD_CTL_D0_LP 0x2b1c
#define MC_SEQ_RD_CTL_D1_LP 0x2b20
#define MC_PMG_CMD_MRS1 0x2b44
#define MC_SEQ_PMG_CMD_MRS1_LP 0x2b48
#define MC_SEQ_PMG_TIMING_LP 0x2b4c
#define MC_PMG_CMD_MRS2 0x2b5c
#define MC_SEQ_PMG_CMD_MRS2_LP 0x2b60
#define LB_SYNC_RESET_SEL 0x6b28
#define LB_SYNC_RESET_SEL_MASK (3 << 0)
#define LB_SYNC_RESET_SEL_SHIFT 0
#define DC_STUTTER_CNTL 0x6b30
#define DC_STUTTER_ENABLE_A (1 << 0)
#define DC_STUTTER_ENABLE_B (1 << 1)
#define SQ_CAC_THRESHOLD 0x8e4c
#define VSP(x) ((x) << 0)
#define VSP_MASK (0xff << 0)
#define VSP_SHIFT 0
#define VSP0(x) ((x) << 8)
#define VSP0_MASK (0xff << 8)
#define VSP0_SHIFT 8
#define GPR(x) ((x) << 16)
#define GPR_MASK (0xff << 16)
#define GPR_SHIFT 16
#define SQ_POWER_THROTTLE 0x8e58
#define MIN_POWER(x) ((x) << 0)
#define MIN_POWER_MASK (0x3fff << 0)
#define MIN_POWER_SHIFT 0
#define MAX_POWER(x) ((x) << 16)
#define MAX_POWER_MASK (0x3fff << 16)
#define MAX_POWER_SHIFT 0
#define SQ_POWER_THROTTLE2 0x8e5c
#define MAX_POWER_DELTA(x) ((x) << 0)
#define MAX_POWER_DELTA_MASK (0x3fff << 0)
#define MAX_POWER_DELTA_SHIFT 0
#define STI_SIZE(x) ((x) << 16)
#define STI_SIZE_MASK (0x3ff << 16)
#define STI_SIZE_SHIFT 16
#define LTI_RATIO(x) ((x) << 27)
#define LTI_RATIO_MASK (0xf << 27)
#define LTI_RATIO_SHIFT 27
/* CG indirect registers */
#define CG_CAC_REGION_1_WEIGHT_0 0x83
#define WEIGHT_TCP_SIG0(x) ((x) << 0)
#define WEIGHT_TCP_SIG0_MASK (0x3f << 0)
#define WEIGHT_TCP_SIG0_SHIFT 0
#define WEIGHT_TCP_SIG1(x) ((x) << 6)
#define WEIGHT_TCP_SIG1_MASK (0x3f << 6)
#define WEIGHT_TCP_SIG1_SHIFT 6
#define WEIGHT_TA_SIG(x) ((x) << 12)
#define WEIGHT_TA_SIG_MASK (0x3f << 12)
#define WEIGHT_TA_SIG_SHIFT 12
#define CG_CAC_REGION_1_WEIGHT_1 0x84
#define WEIGHT_TCC_EN0(x) ((x) << 0)
#define WEIGHT_TCC_EN0_MASK (0x3f << 0)
#define WEIGHT_TCC_EN0_SHIFT 0
#define WEIGHT_TCC_EN1(x) ((x) << 6)
#define WEIGHT_TCC_EN1_MASK (0x3f << 6)
#define WEIGHT_TCC_EN1_SHIFT 6
#define WEIGHT_TCC_EN2(x) ((x) << 12)
#define WEIGHT_TCC_EN2_MASK (0x3f << 12)
#define WEIGHT_TCC_EN2_SHIFT 12
#define WEIGHT_TCC_EN3(x) ((x) << 18)
#define WEIGHT_TCC_EN3_MASK (0x3f << 18)
#define WEIGHT_TCC_EN3_SHIFT 18
#define CG_CAC_REGION_2_WEIGHT_0 0x85
#define WEIGHT_CB_EN0(x) ((x) << 0)
#define WEIGHT_CB_EN0_MASK (0x3f << 0)
#define WEIGHT_CB_EN0_SHIFT 0
#define WEIGHT_CB_EN1(x) ((x) << 6)
#define WEIGHT_CB_EN1_MASK (0x3f << 6)
#define WEIGHT_CB_EN1_SHIFT 6
#define WEIGHT_CB_EN2(x) ((x) << 12)
#define WEIGHT_CB_EN2_MASK (0x3f << 12)
#define WEIGHT_CB_EN2_SHIFT 12
#define WEIGHT_CB_EN3(x) ((x) << 18)
#define WEIGHT_CB_EN3_MASK (0x3f << 18)
#define WEIGHT_CB_EN3_SHIFT 18
#define CG_CAC_REGION_2_WEIGHT_1 0x86
#define WEIGHT_DB_SIG0(x) ((x) << 0)
#define WEIGHT_DB_SIG0_MASK (0x3f << 0)
#define WEIGHT_DB_SIG0_SHIFT 0
#define WEIGHT_DB_SIG1(x) ((x) << 6)
#define WEIGHT_DB_SIG1_MASK (0x3f << 6)
#define WEIGHT_DB_SIG1_SHIFT 6
#define WEIGHT_DB_SIG2(x) ((x) << 12)
#define WEIGHT_DB_SIG2_MASK (0x3f << 12)
#define WEIGHT_DB_SIG2_SHIFT 12
#define WEIGHT_DB_SIG3(x) ((x) << 18)
#define WEIGHT_DB_SIG3_MASK (0x3f << 18)
#define WEIGHT_DB_SIG3_SHIFT 18
#define CG_CAC_REGION_2_WEIGHT_2 0x87
#define WEIGHT_SXM_SIG0(x) ((x) << 0)
#define WEIGHT_SXM_SIG0_MASK (0x3f << 0)
#define WEIGHT_SXM_SIG0_SHIFT 0
#define WEIGHT_SXM_SIG1(x) ((x) << 6)
#define WEIGHT_SXM_SIG1_MASK (0x3f << 6)
#define WEIGHT_SXM_SIG1_SHIFT 6
#define WEIGHT_SXM_SIG2(x) ((x) << 12)
#define WEIGHT_SXM_SIG2_MASK (0x3f << 12)
#define WEIGHT_SXM_SIG2_SHIFT 12
#define WEIGHT_SXS_SIG0(x) ((x) << 18)
#define WEIGHT_SXS_SIG0_MASK (0x3f << 18)
#define WEIGHT_SXS_SIG0_SHIFT 18
#define WEIGHT_SXS_SIG1(x) ((x) << 24)
#define WEIGHT_SXS_SIG1_MASK (0x3f << 24)
#define WEIGHT_SXS_SIG1_SHIFT 24
#define CG_CAC_REGION_3_WEIGHT_0 0x88
#define WEIGHT_XBR_0(x) ((x) << 0)
#define WEIGHT_XBR_0_MASK (0x3f << 0)
#define WEIGHT_XBR_0_SHIFT 0
#define WEIGHT_XBR_1(x) ((x) << 6)
#define WEIGHT_XBR_1_MASK (0x3f << 6)
#define WEIGHT_XBR_1_SHIFT 6
#define WEIGHT_XBR_2(x) ((x) << 12)
#define WEIGHT_XBR_2_MASK (0x3f << 12)
#define WEIGHT_XBR_2_SHIFT 12
#define WEIGHT_SPI_SIG0(x) ((x) << 18)
#define WEIGHT_SPI_SIG0_MASK (0x3f << 18)
#define WEIGHT_SPI_SIG0_SHIFT 18
#define CG_CAC_REGION_3_WEIGHT_1 0x89
#define WEIGHT_SPI_SIG1(x) ((x) << 0)
#define WEIGHT_SPI_SIG1_MASK (0x3f << 0)
#define WEIGHT_SPI_SIG1_SHIFT 0
#define WEIGHT_SPI_SIG2(x) ((x) << 6)
#define WEIGHT_SPI_SIG2_MASK (0x3f << 6)
#define WEIGHT_SPI_SIG2_SHIFT 6
#define WEIGHT_SPI_SIG3(x) ((x) << 12)
#define WEIGHT_SPI_SIG3_MASK (0x3f << 12)
#define WEIGHT_SPI_SIG3_SHIFT 12
#define WEIGHT_SPI_SIG4(x) ((x) << 18)
#define WEIGHT_SPI_SIG4_MASK (0x3f << 18)
#define WEIGHT_SPI_SIG4_SHIFT 18
#define WEIGHT_SPI_SIG5(x) ((x) << 24)
#define WEIGHT_SPI_SIG5_MASK (0x3f << 24)
#define WEIGHT_SPI_SIG5_SHIFT 24
#define CG_CAC_REGION_4_WEIGHT_0 0x8a
#define WEIGHT_LDS_SIG0(x) ((x) << 0)
#define WEIGHT_LDS_SIG0_MASK (0x3f << 0)
#define WEIGHT_LDS_SIG0_SHIFT 0
#define WEIGHT_LDS_SIG1(x) ((x) << 6)
#define WEIGHT_LDS_SIG1_MASK (0x3f << 6)
#define WEIGHT_LDS_SIG1_SHIFT 6
#define WEIGHT_SC(x) ((x) << 24)
#define WEIGHT_SC_MASK (0x3f << 24)
#define WEIGHT_SC_SHIFT 24
#define CG_CAC_REGION_4_WEIGHT_1 0x8b
#define WEIGHT_BIF(x) ((x) << 0)
#define WEIGHT_BIF_MASK (0x3f << 0)
#define WEIGHT_BIF_SHIFT 0
#define WEIGHT_CP(x) ((x) << 6)
#define WEIGHT_CP_MASK (0x3f << 6)
#define WEIGHT_CP_SHIFT 6
#define WEIGHT_PA_SIG0(x) ((x) << 12)
#define WEIGHT_PA_SIG0_MASK (0x3f << 12)
#define WEIGHT_PA_SIG0_SHIFT 12
#define WEIGHT_PA_SIG1(x) ((x) << 18)
#define WEIGHT_PA_SIG1_MASK (0x3f << 18)
#define WEIGHT_PA_SIG1_SHIFT 18
#define WEIGHT_VGT_SIG0(x) ((x) << 24)
#define WEIGHT_VGT_SIG0_MASK (0x3f << 24)
#define WEIGHT_VGT_SIG0_SHIFT 24
#define CG_CAC_REGION_4_WEIGHT_2 0x8c
#define WEIGHT_VGT_SIG1(x) ((x) << 0)
#define WEIGHT_VGT_SIG1_MASK (0x3f << 0)
#define WEIGHT_VGT_SIG1_SHIFT 0
#define WEIGHT_VGT_SIG2(x) ((x) << 6)
#define WEIGHT_VGT_SIG2_MASK (0x3f << 6)
#define WEIGHT_VGT_SIG2_SHIFT 6
#define WEIGHT_DC_SIG0(x) ((x) << 12)
#define WEIGHT_DC_SIG0_MASK (0x3f << 12)
#define WEIGHT_DC_SIG0_SHIFT 12
#define WEIGHT_DC_SIG1(x) ((x) << 18)
#define WEIGHT_DC_SIG1_MASK (0x3f << 18)
#define WEIGHT_DC_SIG1_SHIFT 18
#define WEIGHT_DC_SIG2(x) ((x) << 24)
#define WEIGHT_DC_SIG2_MASK (0x3f << 24)
#define WEIGHT_DC_SIG2_SHIFT 24
#define CG_CAC_REGION_4_WEIGHT_3 0x8d
#define WEIGHT_DC_SIG3(x) ((x) << 0)
#define WEIGHT_DC_SIG3_MASK (0x3f << 0)
#define WEIGHT_DC_SIG3_SHIFT 0
#define WEIGHT_UVD_SIG0(x) ((x) << 6)
#define WEIGHT_UVD_SIG0_MASK (0x3f << 6)
#define WEIGHT_UVD_SIG0_SHIFT 6
#define WEIGHT_UVD_SIG1(x) ((x) << 12)
#define WEIGHT_UVD_SIG1_MASK (0x3f << 12)
#define WEIGHT_UVD_SIG1_SHIFT 12
#define WEIGHT_SPARE0(x) ((x) << 18)
#define WEIGHT_SPARE0_MASK (0x3f << 18)
#define WEIGHT_SPARE0_SHIFT 18
#define WEIGHT_SPARE1(x) ((x) << 24)
#define WEIGHT_SPARE1_MASK (0x3f << 24)
#define WEIGHT_SPARE1_SHIFT 24
#define CG_CAC_REGION_5_WEIGHT_0 0x8e
#define WEIGHT_SQ_VSP(x) ((x) << 0)
#define WEIGHT_SQ_VSP_MASK (0x3fff << 0)
#define WEIGHT_SQ_VSP_SHIFT 0
#define WEIGHT_SQ_VSP0(x) ((x) << 14)
#define WEIGHT_SQ_VSP0_MASK (0x3fff << 14)
#define WEIGHT_SQ_VSP0_SHIFT 14
#define CG_CAC_REGION_4_OVERRIDE_4 0xab
#define OVR_MODE_SPARE_0(x) ((x) << 16)
#define OVR_MODE_SPARE_0_MASK (0x1 << 16)
#define OVR_MODE_SPARE_0_SHIFT 16
#define OVR_VAL_SPARE_0(x) ((x) << 17)
#define OVR_VAL_SPARE_0_MASK (0x1 << 17)
#define OVR_VAL_SPARE_0_SHIFT 17
#define OVR_MODE_SPARE_1(x) ((x) << 18)
#define OVR_MODE_SPARE_1_MASK (0x3f << 18)
#define OVR_MODE_SPARE_1_SHIFT 18
#define OVR_VAL_SPARE_1(x) ((x) << 19)
#define OVR_VAL_SPARE_1_MASK (0x3f << 19)
#define OVR_VAL_SPARE_1_SHIFT 19
#define CG_CAC_REGION_5_WEIGHT_1 0xb7
#define WEIGHT_SQ_GPR(x) ((x) << 0)
#define WEIGHT_SQ_GPR_MASK (0x3fff << 0)
#define WEIGHT_SQ_GPR_SHIFT 0
#define WEIGHT_SQ_LDS(x) ((x) << 14)
#define WEIGHT_SQ_LDS_MASK (0x3fff << 14)
#define WEIGHT_SQ_LDS_SHIFT 14
/* PCIE link stuff */
#define PCIE_LC_TRAINING_CNTL 0xa1 /* PCIE_P */
#define PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE_P */
# define LC_LINK_WIDTH_SHIFT 0
# define LC_LINK_WIDTH_MASK 0x7
# define LC_LINK_WIDTH_X0 0
# define LC_LINK_WIDTH_X1 1
# define LC_LINK_WIDTH_X2 2
# define LC_LINK_WIDTH_X4 3
# define LC_LINK_WIDTH_X8 4
# define LC_LINK_WIDTH_X16 6
# define LC_LINK_WIDTH_RD_SHIFT 4
# define LC_LINK_WIDTH_RD_MASK 0x70
# define LC_RECONFIG_ARC_MISSING_ESCAPE (1 << 7)
# define LC_RECONFIG_NOW (1 << 8)
# define LC_RENEGOTIATION_SUPPORT (1 << 9)
# define LC_RENEGOTIATE_EN (1 << 10)
# define LC_SHORT_RECONFIG_EN (1 << 11)
# define LC_UPCONFIGURE_SUPPORT (1 << 12)
# define LC_UPCONFIGURE_DIS (1 << 13)
#define PCIE_LC_SPEED_CNTL 0xa4 /* PCIE_P */
# define LC_GEN2_EN_STRAP (1 << 0)
# define LC_TARGET_LINK_SPEED_OVERRIDE_EN (1 << 1)
# define LC_FORCE_EN_HW_SPEED_CHANGE (1 << 5)
# define LC_FORCE_DIS_HW_SPEED_CHANGE (1 << 6)
# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK (0x3 << 8)
# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT 3
# define LC_CURRENT_DATA_RATE (1 << 11)
# define LC_HW_VOLTAGE_IF_CONTROL(x) ((x) << 12)
# define LC_HW_VOLTAGE_IF_CONTROL_MASK (3 << 12)
# define LC_HW_VOLTAGE_IF_CONTROL_SHIFT 12
# define LC_VOLTAGE_TIMER_SEL_MASK (0xf << 14)
# define LC_CLR_FAILED_SPD_CHANGE_CNT (1 << 21)
# define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 23)
# define LC_OTHER_SIDE_SUPPORTS_GEN2 (1 << 24)
#define MM_CFGREGS_CNTL 0x544c
# define MM_WR_TO_CFG_EN (1 << 3)
#define LINK_CNTL2 0x88 /* F0 */
# define TARGET_LINK_SPEED_MASK (0xf << 0)
# define SELECTABLE_DEEMPHASIS (1 << 6)
/*
* UVD
*/

View File

@ -0,0 +1,329 @@
/*
* Copyright 2012 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.
*
*/
#ifndef __NISLANDS_SMC_H__
#define __NISLANDS_SMC_H__
#pragma pack(push, 1)
#define NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16
struct PP_NIslands_Dpm2PerfLevel
{
uint8_t MaxPS;
uint8_t TgtAct;
uint8_t MaxPS_StepInc;
uint8_t MaxPS_StepDec;
uint8_t PSST;
uint8_t NearTDPDec;
uint8_t AboveSafeInc;
uint8_t BelowSafeInc;
uint8_t PSDeltaLimit;
uint8_t PSDeltaWin;
uint8_t Reserved[6];
};
typedef struct PP_NIslands_Dpm2PerfLevel PP_NIslands_Dpm2PerfLevel;
struct PP_NIslands_DPM2Parameters
{
uint32_t TDPLimit;
uint32_t NearTDPLimit;
uint32_t SafePowerLimit;
uint32_t PowerBoostLimit;
};
typedef struct PP_NIslands_DPM2Parameters PP_NIslands_DPM2Parameters;
struct NISLANDS_SMC_SCLK_VALUE
{
uint32_t vCG_SPLL_FUNC_CNTL;
uint32_t vCG_SPLL_FUNC_CNTL_2;
uint32_t vCG_SPLL_FUNC_CNTL_3;
uint32_t vCG_SPLL_FUNC_CNTL_4;
uint32_t vCG_SPLL_SPREAD_SPECTRUM;
uint32_t vCG_SPLL_SPREAD_SPECTRUM_2;
uint32_t sclk_value;
};
typedef struct NISLANDS_SMC_SCLK_VALUE NISLANDS_SMC_SCLK_VALUE;
struct NISLANDS_SMC_MCLK_VALUE
{
uint32_t vMPLL_FUNC_CNTL;
uint32_t vMPLL_FUNC_CNTL_1;
uint32_t vMPLL_FUNC_CNTL_2;
uint32_t vMPLL_AD_FUNC_CNTL;
uint32_t vMPLL_AD_FUNC_CNTL_2;
uint32_t vMPLL_DQ_FUNC_CNTL;
uint32_t vMPLL_DQ_FUNC_CNTL_2;
uint32_t vMCLK_PWRMGT_CNTL;
uint32_t vDLL_CNTL;
uint32_t vMPLL_SS;
uint32_t vMPLL_SS2;
uint32_t mclk_value;
};
typedef struct NISLANDS_SMC_MCLK_VALUE NISLANDS_SMC_MCLK_VALUE;
struct NISLANDS_SMC_VOLTAGE_VALUE
{
uint16_t value;
uint8_t index;
uint8_t padding;
};
typedef struct NISLANDS_SMC_VOLTAGE_VALUE NISLANDS_SMC_VOLTAGE_VALUE;
struct NISLANDS_SMC_HW_PERFORMANCE_LEVEL
{
uint8_t arbValue;
uint8_t ACIndex;
uint8_t displayWatermark;
uint8_t gen2PCIE;
uint8_t reserved1;
uint8_t reserved2;
uint8_t strobeMode;
uint8_t mcFlags;
uint32_t aT;
uint32_t bSP;
NISLANDS_SMC_SCLK_VALUE sclk;
NISLANDS_SMC_MCLK_VALUE mclk;
NISLANDS_SMC_VOLTAGE_VALUE vddc;
NISLANDS_SMC_VOLTAGE_VALUE mvdd;
NISLANDS_SMC_VOLTAGE_VALUE vddci;
NISLANDS_SMC_VOLTAGE_VALUE std_vddc;
uint32_t powergate_en;
uint8_t hUp;
uint8_t hDown;
uint8_t stateFlags;
uint8_t arbRefreshState;
uint32_t SQPowerThrottle;
uint32_t SQPowerThrottle_2;
uint32_t reserved[2];
PP_NIslands_Dpm2PerfLevel dpm2;
};
#define NISLANDS_SMC_STROBE_RATIO 0x0F
#define NISLANDS_SMC_STROBE_ENABLE 0x10
#define NISLANDS_SMC_MC_EDC_RD_FLAG 0x01
#define NISLANDS_SMC_MC_EDC_WR_FLAG 0x02
#define NISLANDS_SMC_MC_RTT_ENABLE 0x04
#define NISLANDS_SMC_MC_STUTTER_EN 0x08
typedef struct NISLANDS_SMC_HW_PERFORMANCE_LEVEL NISLANDS_SMC_HW_PERFORMANCE_LEVEL;
struct NISLANDS_SMC_SWSTATE
{
uint8_t flags;
uint8_t levelCount;
uint8_t padding2;
uint8_t padding3;
NISLANDS_SMC_HW_PERFORMANCE_LEVEL levels[1];
};
typedef struct NISLANDS_SMC_SWSTATE NISLANDS_SMC_SWSTATE;
#define NISLANDS_SMC_VOLTAGEMASK_VDDC 0
#define NISLANDS_SMC_VOLTAGEMASK_MVDD 1
#define NISLANDS_SMC_VOLTAGEMASK_VDDCI 2
#define NISLANDS_SMC_VOLTAGEMASK_MAX 4
struct NISLANDS_SMC_VOLTAGEMASKTABLE
{
uint8_t highMask[NISLANDS_SMC_VOLTAGEMASK_MAX];
uint32_t lowMask[NISLANDS_SMC_VOLTAGEMASK_MAX];
};
typedef struct NISLANDS_SMC_VOLTAGEMASKTABLE NISLANDS_SMC_VOLTAGEMASKTABLE;
#define NISLANDS_MAX_NO_VREG_STEPS 32
struct NISLANDS_SMC_STATETABLE
{
uint8_t thermalProtectType;
uint8_t systemFlags;
uint8_t maxVDDCIndexInPPTable;
uint8_t extraFlags;
uint8_t highSMIO[NISLANDS_MAX_NO_VREG_STEPS];
uint32_t lowSMIO[NISLANDS_MAX_NO_VREG_STEPS];
NISLANDS_SMC_VOLTAGEMASKTABLE voltageMaskTable;
PP_NIslands_DPM2Parameters dpm2Params;
NISLANDS_SMC_SWSTATE initialState;
NISLANDS_SMC_SWSTATE ACPIState;
NISLANDS_SMC_SWSTATE ULVState;
NISLANDS_SMC_SWSTATE driverState;
NISLANDS_SMC_HW_PERFORMANCE_LEVEL dpmLevels[NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1];
};
typedef struct NISLANDS_SMC_STATETABLE NISLANDS_SMC_STATETABLE;
#define NI_SMC_SOFT_REGISTERS_START 0x108
#define NI_SMC_SOFT_REGISTER_mclk_chg_timeout 0x0
#define NI_SMC_SOFT_REGISTER_delay_bbias 0xC
#define NI_SMC_SOFT_REGISTER_delay_vreg 0x10
#define NI_SMC_SOFT_REGISTER_delay_acpi 0x2C
#define NI_SMC_SOFT_REGISTER_seq_index 0x64
#define NI_SMC_SOFT_REGISTER_mvdd_chg_time 0x68
#define NI_SMC_SOFT_REGISTER_mclk_switch_lim 0x78
#define NI_SMC_SOFT_REGISTER_watermark_threshold 0x80
#define NI_SMC_SOFT_REGISTER_mc_block_delay 0x84
#define NI_SMC_SOFT_REGISTER_uvd_enabled 0x98
#define SMC_NISLANDS_MC_TPP_CAC_NUM_OF_ENTRIES 16
#define SMC_NISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16
#define SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 16
#define SMC_NISLANDS_BIF_LUT_NUM_OF_ENTRIES 4
struct SMC_NISLANDS_MC_TPP_CAC_TABLE
{
uint32_t tpp[SMC_NISLANDS_MC_TPP_CAC_NUM_OF_ENTRIES];
uint32_t cacValue[SMC_NISLANDS_MC_TPP_CAC_NUM_OF_ENTRIES];
};
typedef struct SMC_NISLANDS_MC_TPP_CAC_TABLE SMC_NISLANDS_MC_TPP_CAC_TABLE;
struct PP_NIslands_CACTABLES
{
uint32_t cac_bif_lut[SMC_NISLANDS_BIF_LUT_NUM_OF_ENTRIES];
uint32_t cac_lkge_lut[SMC_NISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES][SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES];
uint32_t pwr_const;
uint32_t dc_cacValue;
uint32_t bif_cacValue;
uint32_t lkge_pwr;
uint8_t cac_width;
uint8_t window_size_p2;
uint8_t num_drop_lsb;
uint8_t padding_0;
uint32_t last_power;
uint8_t AllowOvrflw;
uint8_t MCWrWeight;
uint8_t MCRdWeight;
uint8_t padding_1[9];
uint8_t enableWinAvg;
uint8_t numWin_TDP;
uint8_t l2numWin_TDP;
uint8_t WinIndex;
uint32_t dynPwr_TDP[4];
uint32_t lkgePwr_TDP[4];
uint32_t power_TDP[4];
uint32_t avg_dynPwr_TDP;
uint32_t avg_lkgePwr_TDP;
uint32_t avg_power_TDP;
uint32_t lts_power_TDP;
uint8_t lts_truncate_n;
uint8_t padding_2[7];
};
typedef struct PP_NIslands_CACTABLES PP_NIslands_CACTABLES;
#define SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE 32
#define SMC_NISLANDS_MC_REGISTER_ARRAY_SET_COUNT 20
struct SMC_NIslands_MCRegisterAddress
{
uint16_t s0;
uint16_t s1;
};
typedef struct SMC_NIslands_MCRegisterAddress SMC_NIslands_MCRegisterAddress;
struct SMC_NIslands_MCRegisterSet
{
uint32_t value[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE];
};
typedef struct SMC_NIslands_MCRegisterSet SMC_NIslands_MCRegisterSet;
struct SMC_NIslands_MCRegisters
{
uint8_t last;
uint8_t reserved[3];
SMC_NIslands_MCRegisterAddress address[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE];
SMC_NIslands_MCRegisterSet data[SMC_NISLANDS_MC_REGISTER_ARRAY_SET_COUNT];
};
typedef struct SMC_NIslands_MCRegisters SMC_NIslands_MCRegisters;
struct SMC_NIslands_MCArbDramTimingRegisterSet
{
uint32_t mc_arb_dram_timing;
uint32_t mc_arb_dram_timing2;
uint8_t mc_arb_rfsh_rate;
uint8_t padding[3];
};
typedef struct SMC_NIslands_MCArbDramTimingRegisterSet SMC_NIslands_MCArbDramTimingRegisterSet;
struct SMC_NIslands_MCArbDramTimingRegisters
{
uint8_t arb_current;
uint8_t reserved[3];
SMC_NIslands_MCArbDramTimingRegisterSet data[20];
};
typedef struct SMC_NIslands_MCArbDramTimingRegisters SMC_NIslands_MCArbDramTimingRegisters;
struct SMC_NISLANDS_SPLL_DIV_TABLE
{
uint32_t freq[256];
uint32_t ss[256];
};
#define SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_MASK 0x01ffffff
#define SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT 0
#define SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_MASK 0xfe000000
#define SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT 25
#define SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_MASK 0x000fffff
#define SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT 0
#define SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK 0xfff00000
#define SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT 20
typedef struct SMC_NISLANDS_SPLL_DIV_TABLE SMC_NISLANDS_SPLL_DIV_TABLE;
#define NISLANDS_SMC_FIRMWARE_HEADER_LOCATION 0x100
#define NISLANDS_SMC_FIRMWARE_HEADER_version 0x0
#define NISLANDS_SMC_FIRMWARE_HEADER_flags 0x4
#define NISLANDS_SMC_FIRMWARE_HEADER_softRegisters 0x8
#define NISLANDS_SMC_FIRMWARE_HEADER_stateTable 0xC
#define NISLANDS_SMC_FIRMWARE_HEADER_fanTable 0x10
#define NISLANDS_SMC_FIRMWARE_HEADER_cacTable 0x14
#define NISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable 0x20
#define NISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable 0x2C
#define NISLANDS_SMC_FIRMWARE_HEADER_spllTable 0x30
#pragma pack(pop)
#endif

View File

@ -0,0 +1,113 @@
/*
* Copyright 2011 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.
*
*/
#ifndef PP_SMC_H
#define PP_SMC_H
#pragma pack(push, 1)
#define PPSMC_SWSTATE_FLAG_DC 0x01
#define PPSMC_SWSTATE_FLAG_UVD 0x02
#define PPSMC_SWSTATE_FLAG_VCE 0x04
#define PPSMC_SWSTATE_FLAG_PCIE_X1 0x08
#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00
#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01
#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff
#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01
#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02
#define PPSMC_SYSTEMFLAG_GDDR5 0x04
#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08
#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10
#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20
#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_PROG_GPIO 0x40
#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07
#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08
#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00
#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01
#define PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH 0x02
#define PPSMC_DISPLAY_WATERMARK_LOW 0
#define PPSMC_DISPLAY_WATERMARK_HIGH 1
#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01
#define PPSMC_STATEFLAG_POWERBOOST 0x02
#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20
#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40
#define PPSMC_Result_OK ((uint8_t)0x01)
#define PPSMC_Result_Failed ((uint8_t)0xFF)
typedef uint8_t PPSMC_Result;
#define PPSMC_MSG_Halt ((uint8_t)0x10)
#define PPSMC_MSG_Resume ((uint8_t)0x11)
#define PPSMC_MSG_ZeroLevelsDisabled ((uint8_t)0x13)
#define PPSMC_MSG_OneLevelsDisabled ((uint8_t)0x14)
#define PPSMC_MSG_TwoLevelsDisabled ((uint8_t)0x15)
#define PPSMC_MSG_EnableThermalInterrupt ((uint8_t)0x16)
#define PPSMC_MSG_RunningOnAC ((uint8_t)0x17)
#define PPSMC_MSG_SwitchToSwState ((uint8_t)0x20)
#define PPSMC_MSG_SwitchToInitialState ((uint8_t)0x40)
#define PPSMC_MSG_NoForcedLevel ((uint8_t)0x41)
#define PPSMC_MSG_SwitchToMinimumPower ((uint8_t)0x51)
#define PPSMC_MSG_ResumeFromMinimumPower ((uint8_t)0x52)
#define PPSMC_MSG_EnableCac ((uint8_t)0x53)
#define PPSMC_MSG_DisableCac ((uint8_t)0x54)
#define PPSMC_TDPClampingActive ((uint8_t)0x59)
#define PPSMC_TDPClampingInactive ((uint8_t)0x5A)
#define PPSMC_MSG_NoDisplay ((uint8_t)0x5D)
#define PPSMC_MSG_HasDisplay ((uint8_t)0x5E)
#define PPSMC_MSG_UVDPowerOFF ((uint8_t)0x60)
#define PPSMC_MSG_UVDPowerON ((uint8_t)0x61)
#define PPSMC_MSG_EnableULV ((uint8_t)0x62)
#define PPSMC_MSG_DisableULV ((uint8_t)0x63)
#define PPSMC_MSG_EnterULV ((uint8_t)0x64)
#define PPSMC_MSG_ExitULV ((uint8_t)0x65)
#define PPSMC_CACLongTermAvgEnable ((uint8_t)0x6E)
#define PPSMC_CACLongTermAvgDisable ((uint8_t)0x6F)
#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint8_t)0x7A)
#define PPSMC_FlushDataCache ((uint8_t)0x80)
#define PPSMC_MSG_SetEnabledLevels ((uint8_t)0x82)
#define PPSMC_MSG_SetForcedLevels ((uint8_t)0x83)
#define PPSMC_MSG_ResetToDefaults ((uint8_t)0x84)
#define PPSMC_MSG_EnableDTE ((uint8_t)0x87)
#define PPSMC_MSG_DisableDTE ((uint8_t)0x88)
#define PPSMC_MSG_ThrottleOVRDSCLKDS ((uint8_t)0x96)
#define PPSMC_MSG_CancelThrottleOVRDSCLKDS ((uint8_t)0x97)
/* TN */
#define PPSMC_MSG_DPM_Config ((uint32_t) 0x102)
#define PPSMC_MSG_DPM_ForceState ((uint32_t) 0x104)
#define PPSMC_MSG_PG_SIMD_Config ((uint32_t) 0x108)
#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint32_t) 0x11d)
#define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint32_t) 0x11e)
#define PPSMC_MSG_UVD_DPM_Config ((uint32_t) 0x124)
typedef uint16_t PPSMC_Msg;
#pragma pack(pop)
#endif

View File

@ -38,18 +38,7 @@
#include "r600d.h"
#include "atom.h"
#include "avivod.h"
#define PFP_UCODE_SIZE 576
#define PM4_UCODE_SIZE 1792
#define RLC_UCODE_SIZE 768
#define R700_PFP_UCODE_SIZE 848
#define R700_PM4_UCODE_SIZE 1360
#define R700_RLC_UCODE_SIZE 1024
#define EVERGREEN_PFP_UCODE_SIZE 1120
#define EVERGREEN_PM4_UCODE_SIZE 1376
#define EVERGREEN_RLC_UCODE_SIZE 768
#define CAYMAN_RLC_UCODE_SIZE 1024
#define ARUBA_RLC_UCODE_SIZE 1536
#include "radeon_ucode.h"
/* Firmware Names */
MODULE_FIRMWARE("radeon/R600_pfp.bin");
@ -68,24 +57,32 @@ MODULE_FIRMWARE("radeon/RS780_pfp.bin");
MODULE_FIRMWARE("radeon/RS780_me.bin");
MODULE_FIRMWARE("radeon/RV770_pfp.bin");
MODULE_FIRMWARE("radeon/RV770_me.bin");
MODULE_FIRMWARE("radeon/RV770_smc.bin");
MODULE_FIRMWARE("radeon/RV730_pfp.bin");
MODULE_FIRMWARE("radeon/RV730_me.bin");
MODULE_FIRMWARE("radeon/RV730_smc.bin");
MODULE_FIRMWARE("radeon/RV740_smc.bin");
MODULE_FIRMWARE("radeon/RV710_pfp.bin");
MODULE_FIRMWARE("radeon/RV710_me.bin");
MODULE_FIRMWARE("radeon/RV710_smc.bin");
MODULE_FIRMWARE("radeon/R600_rlc.bin");
MODULE_FIRMWARE("radeon/R700_rlc.bin");
MODULE_FIRMWARE("radeon/CEDAR_pfp.bin");
MODULE_FIRMWARE("radeon/CEDAR_me.bin");
MODULE_FIRMWARE("radeon/CEDAR_rlc.bin");
MODULE_FIRMWARE("radeon/CEDAR_smc.bin");
MODULE_FIRMWARE("radeon/REDWOOD_pfp.bin");
MODULE_FIRMWARE("radeon/REDWOOD_me.bin");
MODULE_FIRMWARE("radeon/REDWOOD_rlc.bin");
MODULE_FIRMWARE("radeon/REDWOOD_smc.bin");
MODULE_FIRMWARE("radeon/JUNIPER_pfp.bin");
MODULE_FIRMWARE("radeon/JUNIPER_me.bin");
MODULE_FIRMWARE("radeon/JUNIPER_rlc.bin");
MODULE_FIRMWARE("radeon/JUNIPER_smc.bin");
MODULE_FIRMWARE("radeon/CYPRESS_pfp.bin");
MODULE_FIRMWARE("radeon/CYPRESS_me.bin");
MODULE_FIRMWARE("radeon/CYPRESS_rlc.bin");
MODULE_FIRMWARE("radeon/CYPRESS_smc.bin");
MODULE_FIRMWARE("radeon/PALM_pfp.bin");
MODULE_FIRMWARE("radeon/PALM_me.bin");
MODULE_FIRMWARE("radeon/SUMO_rlc.bin");
@ -108,6 +105,7 @@ static void r600_gpu_init(struct radeon_device *rdev);
void r600_fini(struct radeon_device *rdev);
void r600_irq_disable(struct radeon_device *rdev);
static void r600_pcie_gen2_enable(struct radeon_device *rdev);
extern int evergreen_rlc_resume(struct radeon_device *rdev);
/**
* r600_get_xclk - get the xclk
@ -2149,7 +2147,8 @@ int r600_init_microcode(struct radeon_device *rdev)
struct platform_device *pdev;
const char *chip_name;
const char *rlc_chip_name;
size_t pfp_req_size, me_req_size, rlc_req_size;
const char *smc_chip_name = "RV770";
size_t pfp_req_size, me_req_size, rlc_req_size, smc_req_size = 0;
char fw_name[30];
int err;
@ -2195,32 +2194,51 @@ int r600_init_microcode(struct radeon_device *rdev)
case CHIP_RV770:
chip_name = "RV770";
rlc_chip_name = "R700";
smc_chip_name = "RV770";
smc_req_size = ALIGN(RV770_SMC_UCODE_SIZE, 4);
break;
case CHIP_RV730:
case CHIP_RV740:
chip_name = "RV730";
rlc_chip_name = "R700";
smc_chip_name = "RV730";
smc_req_size = ALIGN(RV730_SMC_UCODE_SIZE, 4);
break;
case CHIP_RV710:
chip_name = "RV710";
rlc_chip_name = "R700";
smc_chip_name = "RV710";
smc_req_size = ALIGN(RV710_SMC_UCODE_SIZE, 4);
break;
case CHIP_RV740:
chip_name = "RV730";
rlc_chip_name = "R700";
smc_chip_name = "RV740";
smc_req_size = ALIGN(RV740_SMC_UCODE_SIZE, 4);
break;
case CHIP_CEDAR:
chip_name = "CEDAR";
rlc_chip_name = "CEDAR";
smc_chip_name = "CEDAR";
smc_req_size = ALIGN(CEDAR_SMC_UCODE_SIZE, 4);
break;
case CHIP_REDWOOD:
chip_name = "REDWOOD";
rlc_chip_name = "REDWOOD";
smc_chip_name = "REDWOOD";
smc_req_size = ALIGN(REDWOOD_SMC_UCODE_SIZE, 4);
break;
case CHIP_JUNIPER:
chip_name = "JUNIPER";
rlc_chip_name = "JUNIPER";
smc_chip_name = "JUNIPER";
smc_req_size = ALIGN(JUNIPER_SMC_UCODE_SIZE, 4);
break;
case CHIP_CYPRESS:
case CHIP_HEMLOCK:
chip_name = "CYPRESS";
rlc_chip_name = "CYPRESS";
smc_chip_name = "CYPRESS";
smc_req_size = ALIGN(CYPRESS_SMC_UCODE_SIZE, 4);
break;
case CHIP_PALM:
chip_name = "PALM";
@ -2246,9 +2264,9 @@ int r600_init_microcode(struct radeon_device *rdev)
me_req_size = R700_PM4_UCODE_SIZE * 4;
rlc_req_size = R700_RLC_UCODE_SIZE * 4;
} else {
pfp_req_size = PFP_UCODE_SIZE * 4;
me_req_size = PM4_UCODE_SIZE * 12;
rlc_req_size = RLC_UCODE_SIZE * 4;
pfp_req_size = R600_PFP_UCODE_SIZE * 4;
me_req_size = R600_PM4_UCODE_SIZE * 12;
rlc_req_size = R600_RLC_UCODE_SIZE * 4;
}
DRM_INFO("Loading %s Microcode\n", chip_name);
@ -2287,6 +2305,19 @@ int r600_init_microcode(struct radeon_device *rdev)
err = -EINVAL;
}
if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_HEMLOCK)) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", smc_chip_name);
err = request_firmware(&rdev->smc_fw, fw_name, &pdev->dev);
if (err)
goto out;
if (rdev->smc_fw->size != smc_req_size) {
printk(KERN_ERR
"smc: Bogus length %zu in firmware \"%s\"\n",
rdev->smc_fw->size, fw_name);
err = -EINVAL;
}
}
out:
platform_device_unregister(pdev);
@ -2301,6 +2332,8 @@ out:
rdev->me_fw = NULL;
release_firmware(rdev->rlc_fw);
rdev->rlc_fw = NULL;
release_firmware(rdev->smc_fw);
rdev->smc_fw = NULL;
}
return err;
}
@ -2331,13 +2364,13 @@ static int r600_cp_load_microcode(struct radeon_device *rdev)
fw_data = (const __be32 *)rdev->me_fw->data;
WREG32(CP_ME_RAM_WADDR, 0);
for (i = 0; i < PM4_UCODE_SIZE * 3; i++)
for (i = 0; i < R600_PM4_UCODE_SIZE * 3; i++)
WREG32(CP_ME_RAM_DATA,
be32_to_cpup(fw_data++));
fw_data = (const __be32 *)rdev->pfp_fw->data;
WREG32(CP_PFP_UCODE_ADDR, 0);
for (i = 0; i < PFP_UCODE_SIZE; i++)
for (i = 0; i < R600_PFP_UCODE_SIZE; i++)
WREG32(CP_PFP_UCODE_DATA,
be32_to_cpup(fw_data++));
@ -3789,7 +3822,7 @@ static void r600_rlc_start(struct radeon_device *rdev)
WREG32(RLC_CNTL, RLC_ENABLE);
}
static int r600_rlc_init(struct radeon_device *rdev)
static int r600_rlc_resume(struct radeon_device *rdev)
{
u32 i;
const __be32 *fw_data;
@ -3801,45 +3834,22 @@ static int r600_rlc_init(struct radeon_device *rdev)
WREG32(RLC_HB_CNTL, 0);
if (rdev->family == CHIP_ARUBA) {
WREG32(TN_RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8);
WREG32(TN_RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8);
}
if (rdev->family <= CHIP_CAYMAN) {
WREG32(RLC_HB_BASE, 0);
WREG32(RLC_HB_RPTR, 0);
WREG32(RLC_HB_WPTR, 0);
}
if (rdev->family <= CHIP_CAICOS) {
WREG32(RLC_HB_WPTR_LSB_ADDR, 0);
WREG32(RLC_HB_WPTR_MSB_ADDR, 0);
}
WREG32(RLC_HB_BASE, 0);
WREG32(RLC_HB_RPTR, 0);
WREG32(RLC_HB_WPTR, 0);
WREG32(RLC_HB_WPTR_LSB_ADDR, 0);
WREG32(RLC_HB_WPTR_MSB_ADDR, 0);
WREG32(RLC_MC_CNTL, 0);
WREG32(RLC_UCODE_CNTL, 0);
fw_data = (const __be32 *)rdev->rlc_fw->data;
if (rdev->family >= CHIP_ARUBA) {
for (i = 0; i < ARUBA_RLC_UCODE_SIZE; i++) {
WREG32(RLC_UCODE_ADDR, i);
WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
}
} else if (rdev->family >= CHIP_CAYMAN) {
for (i = 0; i < CAYMAN_RLC_UCODE_SIZE; i++) {
WREG32(RLC_UCODE_ADDR, i);
WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
}
} else if (rdev->family >= CHIP_CEDAR) {
for (i = 0; i < EVERGREEN_RLC_UCODE_SIZE; i++) {
WREG32(RLC_UCODE_ADDR, i);
WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
}
} else if (rdev->family >= CHIP_RV770) {
if (rdev->family >= CHIP_RV770) {
for (i = 0; i < R700_RLC_UCODE_SIZE; i++) {
WREG32(RLC_UCODE_ADDR, i);
WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
}
} else {
for (i = 0; i < RLC_UCODE_SIZE; i++) {
for (i = 0; i < R600_RLC_UCODE_SIZE; i++) {
WREG32(RLC_UCODE_ADDR, i);
WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
}
@ -3947,7 +3957,10 @@ int r600_irq_init(struct radeon_device *rdev)
r600_disable_interrupts(rdev);
/* init rlc */
ret = r600_rlc_init(rdev);
if (rdev->family >= CHIP_CEDAR)
ret = evergreen_rlc_resume(rdev);
else
ret = r600_rlc_resume(rdev);
if (ret) {
r600_ih_ring_fini(rdev);
return ret;
@ -4028,6 +4041,7 @@ int r600_irq_set(struct radeon_device *rdev)
u32 hdmi0, hdmi1;
u32 d1grph = 0, d2grph = 0;
u32 dma_cntl;
u32 thermal_int = 0;
if (!rdev->irq.installed) {
WARN(1, "Can't enable IRQ/MSI because no handler is installed\n");
@ -4062,8 +4076,21 @@ int r600_irq_set(struct radeon_device *rdev)
hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
}
dma_cntl = RREG32(DMA_CNTL) & ~TRAP_ENABLE;
if ((rdev->family > CHIP_R600) && (rdev->family < CHIP_RV770)) {
thermal_int = RREG32(CG_THERMAL_INT) &
~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
} else if (rdev->family >= CHIP_RV770) {
thermal_int = RREG32(RV770_CG_THERMAL_INT) &
~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
}
if (rdev->irq.dpm_thermal) {
DRM_DEBUG("dpm thermal\n");
thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
}
if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) {
DRM_DEBUG("r600_irq_set: sw int\n");
cp_int_cntl |= RB_INT_ENABLE;
@ -4145,6 +4172,11 @@ int r600_irq_set(struct radeon_device *rdev)
WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0);
WREG32(HDMI1_AUDIO_PACKET_CONTROL, hdmi1);
}
if ((rdev->family > CHIP_R600) && (rdev->family < CHIP_RV770)) {
WREG32(CG_THERMAL_INT, thermal_int);
} else if (rdev->family >= CHIP_RV770) {
WREG32(RV770_CG_THERMAL_INT, thermal_int);
}
return 0;
}
@ -4336,6 +4368,7 @@ int r600_irq_process(struct radeon_device *rdev)
u32 ring_index;
bool queue_hotplug = false;
bool queue_hdmi = false;
bool queue_thermal = false;
if (!rdev->ih.enabled || rdev->shutdown)
return IRQ_NONE;
@ -4503,6 +4536,16 @@ restart_ih:
DRM_DEBUG("IH: DMA trap\n");
radeon_fence_process(rdev, R600_RING_TYPE_DMA_INDEX);
break;
case 230: /* thermal low to high */
DRM_DEBUG("IH: thermal low to high\n");
rdev->pm.dpm.thermal.high_to_low = false;
queue_thermal = true;
break;
case 231: /* thermal high to low */
DRM_DEBUG("IH: thermal high to low\n");
rdev->pm.dpm.thermal.high_to_low = true;
queue_thermal = true;
break;
case 233: /* GUI IDLE */
DRM_DEBUG("IH: GUI idle\n");
break;
@ -4519,6 +4562,8 @@ restart_ih:
schedule_work(&rdev->hotplug_work);
if (queue_hdmi)
schedule_work(&rdev->audio_work);
if (queue_thermal && rdev->pm.dpm_enabled)
schedule_work(&rdev->pm.dpm.thermal.work);
rdev->ih.rptr = rptr;
WREG32(IH_RB_RPTR, rdev->ih.rptr);
atomic_set(&rdev->ih.lock, 0);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,226 @@
/*
* Copyright 2011 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.
*
*/
#ifndef __R600_DPM_H__
#define __R600_DPM_H__
#define R600_ASI_DFLT 10000
#define R600_BSP_DFLT 0x41EB
#define R600_BSU_DFLT 0x2
#define R600_AH_DFLT 5
#define R600_RLP_DFLT 25
#define R600_RMP_DFLT 65
#define R600_LHP_DFLT 40
#define R600_LMP_DFLT 15
#define R600_TD_DFLT 0
#define R600_UTC_DFLT_00 0x24
#define R600_UTC_DFLT_01 0x22
#define R600_UTC_DFLT_02 0x22
#define R600_UTC_DFLT_03 0x22
#define R600_UTC_DFLT_04 0x22
#define R600_UTC_DFLT_05 0x22
#define R600_UTC_DFLT_06 0x22
#define R600_UTC_DFLT_07 0x22
#define R600_UTC_DFLT_08 0x22
#define R600_UTC_DFLT_09 0x22
#define R600_UTC_DFLT_10 0x22
#define R600_UTC_DFLT_11 0x22
#define R600_UTC_DFLT_12 0x22
#define R600_UTC_DFLT_13 0x22
#define R600_UTC_DFLT_14 0x22
#define R600_DTC_DFLT_00 0x24
#define R600_DTC_DFLT_01 0x22
#define R600_DTC_DFLT_02 0x22
#define R600_DTC_DFLT_03 0x22
#define R600_DTC_DFLT_04 0x22
#define R600_DTC_DFLT_05 0x22
#define R600_DTC_DFLT_06 0x22
#define R600_DTC_DFLT_07 0x22
#define R600_DTC_DFLT_08 0x22
#define R600_DTC_DFLT_09 0x22
#define R600_DTC_DFLT_10 0x22
#define R600_DTC_DFLT_11 0x22
#define R600_DTC_DFLT_12 0x22
#define R600_DTC_DFLT_13 0x22
#define R600_DTC_DFLT_14 0x22
#define R600_VRC_DFLT 0x0000C003
#define R600_VOLTAGERESPONSETIME_DFLT 1000
#define R600_BACKBIASRESPONSETIME_DFLT 1000
#define R600_VRU_DFLT 0x3
#define R600_SPLLSTEPTIME_DFLT 0x1000
#define R600_SPLLSTEPUNIT_DFLT 0x3
#define R600_TPU_DFLT 0
#define R600_TPC_DFLT 0x200
#define R600_SSTU_DFLT 0
#define R600_SST_DFLT 0x00C8
#define R600_GICST_DFLT 0x200
#define R600_FCT_DFLT 0x0400
#define R600_FCTU_DFLT 0
#define R600_CTXCGTT3DRPHC_DFLT 0x20
#define R600_CTXCGTT3DRSDC_DFLT 0x40
#define R600_VDDC3DOORPHC_DFLT 0x100
#define R600_VDDC3DOORSDC_DFLT 0x7
#define R600_VDDC3DOORSU_DFLT 0
#define R600_MPLLLOCKTIME_DFLT 100
#define R600_MPLLRESETTIME_DFLT 150
#define R600_VCOSTEPPCT_DFLT 20
#define R600_ENDINGVCOSTEPPCT_DFLT 5
#define R600_REFERENCEDIVIDER_DFLT 4
#define R600_PM_NUMBER_OF_TC 15
#define R600_PM_NUMBER_OF_SCLKS 20
#define R600_PM_NUMBER_OF_MCLKS 4
#define R600_PM_NUMBER_OF_VOLTAGE_LEVELS 4
#define R600_PM_NUMBER_OF_ACTIVITY_LEVELS 3
/* XXX are these ok? */
#define R600_TEMP_RANGE_MIN (90 * 1000)
#define R600_TEMP_RANGE_MAX (120 * 1000)
enum r600_power_level {
R600_POWER_LEVEL_LOW = 0,
R600_POWER_LEVEL_MEDIUM = 1,
R600_POWER_LEVEL_HIGH = 2,
R600_POWER_LEVEL_CTXSW = 3,
};
enum r600_td {
R600_TD_AUTO,
R600_TD_UP,
R600_TD_DOWN,
};
enum r600_display_watermark {
R600_DISPLAY_WATERMARK_LOW = 0,
R600_DISPLAY_WATERMARK_HIGH = 1,
};
enum r600_display_gap
{
R600_PM_DISPLAY_GAP_VBLANK_OR_WM = 0,
R600_PM_DISPLAY_GAP_VBLANK = 1,
R600_PM_DISPLAY_GAP_WATERMARK = 2,
R600_PM_DISPLAY_GAP_IGNORE = 3,
};
extern const u32 r600_utc[R600_PM_NUMBER_OF_TC];
extern const u32 r600_dtc[R600_PM_NUMBER_OF_TC];
void r600_dpm_print_class_info(u32 class, u32 class2);
void r600_dpm_print_cap_info(u32 caps);
void r600_dpm_print_ps_status(struct radeon_device *rdev,
struct radeon_ps *rps);
bool r600_is_uvd_state(u32 class, u32 class2);
void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b,
u32 *p, u32 *u);
int r600_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th);
void r600_gfx_clockgating_enable(struct radeon_device *rdev, bool enable);
void r600_dynamicpm_enable(struct radeon_device *rdev, bool enable);
void r600_enable_thermal_protection(struct radeon_device *rdev, bool enable);
void r600_enable_acpi_pm(struct radeon_device *rdev);
void r600_enable_dynamic_pcie_gen2(struct radeon_device *rdev, bool enable);
bool r600_dynamicpm_enabled(struct radeon_device *rdev);
void r600_enable_sclk_control(struct radeon_device *rdev, bool enable);
void r600_enable_mclk_control(struct radeon_device *rdev, bool enable);
void r600_enable_spll_bypass(struct radeon_device *rdev, bool enable);
void r600_wait_for_spll_change(struct radeon_device *rdev);
void r600_set_bsp(struct radeon_device *rdev, u32 u, u32 p);
void r600_set_at(struct radeon_device *rdev,
u32 l_to_m, u32 m_to_h,
u32 h_to_m, u32 m_to_l);
void r600_set_tc(struct radeon_device *rdev, u32 index, u32 u_t, u32 d_t);
void r600_select_td(struct radeon_device *rdev, enum r600_td td);
void r600_set_vrc(struct radeon_device *rdev, u32 vrv);
void r600_set_tpu(struct radeon_device *rdev, u32 u);
void r600_set_tpc(struct radeon_device *rdev, u32 c);
void r600_set_sstu(struct radeon_device *rdev, u32 u);
void r600_set_sst(struct radeon_device *rdev, u32 t);
void r600_set_git(struct radeon_device *rdev, u32 t);
void r600_set_fctu(struct radeon_device *rdev, u32 u);
void r600_set_fct(struct radeon_device *rdev, u32 t);
void r600_set_ctxcgtt3d_rphc(struct radeon_device *rdev, u32 p);
void r600_set_ctxcgtt3d_rsdc(struct radeon_device *rdev, u32 s);
void r600_set_vddc3d_oorsu(struct radeon_device *rdev, u32 u);
void r600_set_vddc3d_oorphc(struct radeon_device *rdev, u32 p);
void r600_set_vddc3d_oorsdc(struct radeon_device *rdev, u32 s);
void r600_set_mpll_lock_time(struct radeon_device *rdev, u32 lock_time);
void r600_set_mpll_reset_time(struct radeon_device *rdev, u32 reset_time);
void r600_engine_clock_entry_enable(struct radeon_device *rdev,
u32 index, bool enable);
void r600_engine_clock_entry_enable_pulse_skipping(struct radeon_device *rdev,
u32 index, bool enable);
void r600_engine_clock_entry_enable_post_divider(struct radeon_device *rdev,
u32 index, bool enable);
void r600_engine_clock_entry_set_post_divider(struct radeon_device *rdev,
u32 index, u32 divider);
void r600_engine_clock_entry_set_reference_divider(struct radeon_device *rdev,
u32 index, u32 divider);
void r600_engine_clock_entry_set_feedback_divider(struct radeon_device *rdev,
u32 index, u32 divider);
void r600_engine_clock_entry_set_step_time(struct radeon_device *rdev,
u32 index, u32 step_time);
void r600_vid_rt_set_ssu(struct radeon_device *rdev, u32 u);
void r600_vid_rt_set_vru(struct radeon_device *rdev, u32 u);
void r600_vid_rt_set_vrt(struct radeon_device *rdev, u32 rt);
void r600_voltage_control_enable_pins(struct radeon_device *rdev,
u64 mask);
void r600_voltage_control_program_voltages(struct radeon_device *rdev,
enum r600_power_level index, u64 pins);
void r600_voltage_control_deactivate_static_control(struct radeon_device *rdev,
u64 mask);
void r600_power_level_enable(struct radeon_device *rdev,
enum r600_power_level index, bool enable);
void r600_power_level_set_voltage_index(struct radeon_device *rdev,
enum r600_power_level index, u32 voltage_index);
void r600_power_level_set_mem_clock_index(struct radeon_device *rdev,
enum r600_power_level index, u32 mem_clock_index);
void r600_power_level_set_eng_clock_index(struct radeon_device *rdev,
enum r600_power_level index, u32 eng_clock_index);
void r600_power_level_set_watermark_id(struct radeon_device *rdev,
enum r600_power_level index,
enum r600_display_watermark watermark_id);
void r600_power_level_set_pcie_gen2(struct radeon_device *rdev,
enum r600_power_level index, bool compatible);
enum r600_power_level r600_power_level_get_current_index(struct radeon_device *rdev);
enum r600_power_level r600_power_level_get_target_index(struct radeon_device *rdev);
void r600_power_level_set_enter_index(struct radeon_device *rdev,
enum r600_power_level index);
void r600_wait_for_power_level_unequal(struct radeon_device *rdev,
enum r600_power_level index);
void r600_wait_for_power_level(struct radeon_device *rdev,
enum r600_power_level index);
void r600_start_dpm(struct radeon_device *rdev);
void r600_stop_dpm(struct radeon_device *rdev);
int r600_set_thermal_temperature_range(struct radeon_device *rdev,
int min_temp, int max_temp);
bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor);
int r600_parse_extended_power_table(struct radeon_device *rdev);
void r600_free_extended_power_table(struct radeon_device *rdev);
enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev,
u32 sys_mask,
enum radeon_pcie_gen asic_gen,
enum radeon_pcie_gen default_gen);
#endif

View File

@ -133,14 +133,7 @@ static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
uint32_t offset = dig->afmt->offset;
uint8_t *frame = buffer + 3;
/* Our header values (type, version, length) should be alright, Intel
* is using the same. Checksum function also seems to be OK, it works
* fine for audio infoframe. However calculated value is always lower
* by 2 in comparison to fglrx. It breaks displaying anything in case
* of TVs that strictly check the checksum. Hack it manually here to
* workaround this issue. */
frame[0x0] += 2;
uint8_t *header = buffer;
WREG32(HDMI0_AVI_INFO0 + offset,
frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
@ -149,7 +142,7 @@ static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
WREG32(HDMI0_AVI_INFO2 + offset,
frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
WREG32(HDMI0_AVI_INFO3 + offset,
frame[0xC] | (frame[0xD] << 8));
frame[0xC] | (frame[0xD] << 8) | (header[1] << 24));
}
/*

View File

@ -31,6 +31,12 @@
#define R600_PCIE_PORT_INDEX 0x0038
#define R600_PCIE_PORT_DATA 0x003c
#define R600_RCU_INDEX 0x0100
#define R600_RCU_DATA 0x0104
#define R600_UVD_CTX_INDEX 0xf4a0
#define R600_UVD_CTX_DATA 0xf4a4
#define R600_MC_VM_FB_LOCATION 0x2180
#define R600_MC_FB_BASE_MASK 0x0000FFFF
#define R600_MC_FB_BASE_SHIFT 0

View File

@ -302,10 +302,25 @@
#define GRBM_SOFT_RESET 0x8020
#define SOFT_RESET_CP (1<<0)
#define CG_THERMAL_CTRL 0x7F0
#define DIG_THERM_DPM(x) ((x) << 12)
#define DIG_THERM_DPM_MASK 0x000FF000
#define DIG_THERM_DPM_SHIFT 12
#define CG_THERMAL_STATUS 0x7F4
#define ASIC_T(x) ((x) << 0)
#define ASIC_T_MASK 0x1FF
#define ASIC_T_SHIFT 0
#define CG_THERMAL_INT 0x7F8
#define DIG_THERM_INTH(x) ((x) << 8)
#define DIG_THERM_INTH_MASK 0x0000FF00
#define DIG_THERM_INTH_SHIFT 8
#define DIG_THERM_INTL(x) ((x) << 16)
#define DIG_THERM_INTL_MASK 0x00FF0000
#define DIG_THERM_INTL_SHIFT 16
#define THERM_INT_MASK_HIGH (1 << 24)
#define THERM_INT_MASK_LOW (1 << 25)
#define RV770_CG_THERMAL_INT 0x734
#define HDP_HOST_PATH_CNTL 0x2C00
#define HDP_NONSURFACE_BASE 0x2C04
@ -684,10 +699,6 @@
#define RLC_UCODE_ADDR 0x3f2c
#define RLC_UCODE_DATA 0x3f30
/* new for TN */
#define TN_RLC_SAVE_AND_RESTORE_BASE 0x3f10
#define TN_RLC_CLEAR_STATE_RESTORE_BASE 0x3f20
#define SRBM_SOFT_RESET 0xe60
# define SOFT_RESET_DMA (1 << 12)
# define SOFT_RESET_RLC (1 << 13)
@ -1148,6 +1159,219 @@
# define AFMT_AZ_FORMAT_WTRIG_ACK (1 << 29)
# define AFMT_AZ_AUDIO_ENABLE_CHG_ACK (1 << 30)
/* Power management */
#define CG_SPLL_FUNC_CNTL 0x600
# define SPLL_RESET (1 << 0)
# define SPLL_SLEEP (1 << 1)
# define SPLL_REF_DIV(x) ((x) << 2)
# define SPLL_REF_DIV_MASK (7 << 2)
# define SPLL_FB_DIV(x) ((x) << 5)
# define SPLL_FB_DIV_MASK (0xff << 5)
# define SPLL_PULSEEN (1 << 13)
# define SPLL_PULSENUM(x) ((x) << 14)
# define SPLL_PULSENUM_MASK (3 << 14)
# define SPLL_SW_HILEN(x) ((x) << 16)
# define SPLL_SW_HILEN_MASK (0xf << 16)
# define SPLL_SW_LOLEN(x) ((x) << 20)
# define SPLL_SW_LOLEN_MASK (0xf << 20)
# define SPLL_DIVEN (1 << 24)
# define SPLL_BYPASS_EN (1 << 25)
# define SPLL_CHG_STATUS (1 << 29)
# define SPLL_CTLREQ (1 << 30)
# define SPLL_CTLACK (1 << 31)
#define GENERAL_PWRMGT 0x618
# define GLOBAL_PWRMGT_EN (1 << 0)
# define STATIC_PM_EN (1 << 1)
# define MOBILE_SU (1 << 2)
# define THERMAL_PROTECTION_DIS (1 << 3)
# define THERMAL_PROTECTION_TYPE (1 << 4)
# define ENABLE_GEN2PCIE (1 << 5)
# define SW_GPIO_INDEX(x) ((x) << 6)
# define SW_GPIO_INDEX_MASK (3 << 6)
# define LOW_VOLT_D2_ACPI (1 << 8)
# define LOW_VOLT_D3_ACPI (1 << 9)
# define VOLT_PWRMGT_EN (1 << 10)
#define CG_TPC 0x61c
# define TPCC(x) ((x) << 0)
# define TPCC_MASK (0x7fffff << 0)
# define TPU(x) ((x) << 23)
# define TPU_MASK (0x1f << 23)
#define SCLK_PWRMGT_CNTL 0x620
# define SCLK_PWRMGT_OFF (1 << 0)
# define SCLK_TURNOFF (1 << 1)
# define SPLL_TURNOFF (1 << 2)
# define SU_SCLK_USE_BCLK (1 << 3)
# define DYNAMIC_GFX_ISLAND_PWR_DOWN (1 << 4)
# define DYNAMIC_GFX_ISLAND_PWR_LP (1 << 5)
# define CLK_TURN_ON_STAGGER (1 << 6)
# define CLK_TURN_OFF_STAGGER (1 << 7)
# define FIR_FORCE_TREND_SEL (1 << 8)
# define FIR_TREND_MODE (1 << 9)
# define DYN_GFX_CLK_OFF_EN (1 << 10)
# define VDDC3D_TURNOFF_D1 (1 << 11)
# define VDDC3D_TURNOFF_D2 (1 << 12)
# define VDDC3D_TURNOFF_D3 (1 << 13)
# define SPLL_TURNOFF_D2 (1 << 14)
# define SCLK_LOW_D1 (1 << 15)
# define DYN_GFX_CLK_OFF_MC_EN (1 << 16)
#define MCLK_PWRMGT_CNTL 0x624
# define MPLL_PWRMGT_OFF (1 << 0)
# define YCLK_TURNOFF (1 << 1)
# define MPLL_TURNOFF (1 << 2)
# define SU_MCLK_USE_BCLK (1 << 3)
# define DLL_READY (1 << 4)
# define MC_BUSY (1 << 5)
# define MC_INT_CNTL (1 << 7)
# define MRDCKA_SLEEP (1 << 8)
# define MRDCKB_SLEEP (1 << 9)
# define MRDCKC_SLEEP (1 << 10)
# define MRDCKD_SLEEP (1 << 11)
# define MRDCKE_SLEEP (1 << 12)
# define MRDCKF_SLEEP (1 << 13)
# define MRDCKG_SLEEP (1 << 14)
# define MRDCKH_SLEEP (1 << 15)
# define MRDCKA_RESET (1 << 16)
# define MRDCKB_RESET (1 << 17)
# define MRDCKC_RESET (1 << 18)
# define MRDCKD_RESET (1 << 19)
# define MRDCKE_RESET (1 << 20)
# define MRDCKF_RESET (1 << 21)
# define MRDCKG_RESET (1 << 22)
# define MRDCKH_RESET (1 << 23)
# define DLL_READY_READ (1 << 24)
# define USE_DISPLAY_GAP (1 << 25)
# define USE_DISPLAY_URGENT_NORMAL (1 << 26)
# define USE_DISPLAY_GAP_CTXSW (1 << 27)
# define MPLL_TURNOFF_D2 (1 << 28)
# define USE_DISPLAY_URGENT_CTXSW (1 << 29)
#define MPLL_TIME 0x634
# define MPLL_LOCK_TIME(x) ((x) << 0)
# define MPLL_LOCK_TIME_MASK (0xffff << 0)
# define MPLL_RESET_TIME(x) ((x) << 16)
# define MPLL_RESET_TIME_MASK (0xffff << 16)
#define SCLK_FREQ_SETTING_STEP_0_PART1 0x648
# define STEP_0_SPLL_POST_DIV(x) ((x) << 0)
# define STEP_0_SPLL_POST_DIV_MASK (0xff << 0)
# define STEP_0_SPLL_FB_DIV(x) ((x) << 8)
# define STEP_0_SPLL_FB_DIV_MASK (0xff << 8)
# define STEP_0_SPLL_REF_DIV(x) ((x) << 16)
# define STEP_0_SPLL_REF_DIV_MASK (7 << 16)
# define STEP_0_SPLL_STEP_TIME(x) ((x) << 19)
# define STEP_0_SPLL_STEP_TIME_MASK (0x1fff << 19)
#define SCLK_FREQ_SETTING_STEP_0_PART2 0x64c
# define STEP_0_PULSE_HIGH_CNT(x) ((x) << 0)
# define STEP_0_PULSE_HIGH_CNT_MASK (0x1ff << 0)
# define STEP_0_POST_DIV_EN (1 << 9)
# define STEP_0_SPLL_STEP_ENABLE (1 << 30)
# define STEP_0_SPLL_ENTRY_VALID (1 << 31)
#define VID_RT 0x6f8
# define VID_CRT(x) ((x) << 0)
# define VID_CRT_MASK (0x1fff << 0)
# define VID_CRTU(x) ((x) << 13)
# define VID_CRTU_MASK (7 << 13)
# define SSTU(x) ((x) << 16)
# define SSTU_MASK (7 << 16)
#define CTXSW_PROFILE_INDEX 0x6fc
# define CTXSW_FREQ_VIDS_CFG_INDEX(x) ((x) << 0)
# define CTXSW_FREQ_VIDS_CFG_INDEX_MASK (3 << 0)
# define CTXSW_FREQ_VIDS_CFG_INDEX_SHIFT 0
# define CTXSW_FREQ_MCLK_CFG_INDEX(x) ((x) << 2)
# define CTXSW_FREQ_MCLK_CFG_INDEX_MASK (3 << 2)
# define CTXSW_FREQ_MCLK_CFG_INDEX_SHIFT 2
# define CTXSW_FREQ_SCLK_CFG_INDEX(x) ((x) << 4)
# define CTXSW_FREQ_SCLK_CFG_INDEX_MASK (0x1f << 4)
# define CTXSW_FREQ_SCLK_CFG_INDEX_SHIFT 4
# define CTXSW_FREQ_STATE_SPLL_RESET_EN (1 << 9)
# define CTXSW_FREQ_STATE_ENABLE (1 << 10)
# define CTXSW_FREQ_DISPLAY_WATERMARK (1 << 11)
# define CTXSW_FREQ_GEN2PCIE_VOLT (1 << 12)
#define TARGET_AND_CURRENT_PROFILE_INDEX 0x70c
# define TARGET_PROFILE_INDEX_MASK (3 << 0)
# define TARGET_PROFILE_INDEX_SHIFT 0
# define CURRENT_PROFILE_INDEX_MASK (3 << 2)
# define CURRENT_PROFILE_INDEX_SHIFT 2
# define DYN_PWR_ENTER_INDEX(x) ((x) << 4)
# define DYN_PWR_ENTER_INDEX_MASK (3 << 4)
# define DYN_PWR_ENTER_INDEX_SHIFT 4
# define CURR_MCLK_INDEX_MASK (3 << 6)
# define CURR_MCLK_INDEX_SHIFT 6
# define CURR_SCLK_INDEX_MASK (0x1f << 8)
# define CURR_SCLK_INDEX_SHIFT 8
# define CURR_VID_INDEX_MASK (3 << 13)
# define CURR_VID_INDEX_SHIFT 13
#define LOWER_GPIO_ENABLE 0x710
#define UPPER_GPIO_ENABLE 0x714
#define CTXSW_VID_LOWER_GPIO_CNTL 0x718
#define VID_UPPER_GPIO_CNTL 0x740
#define CG_CTX_CGTT3D_R 0x744
# define PHC(x) ((x) << 0)
# define PHC_MASK (0x1ff << 0)
# define SDC(x) ((x) << 9)
# define SDC_MASK (0x3fff << 9)
#define CG_VDDC3D_OOR 0x748
# define SU(x) ((x) << 23)
# define SU_MASK (0xf << 23)
#define CG_FTV 0x74c
#define CG_FFCT_0 0x750
# define UTC_0(x) ((x) << 0)
# define UTC_0_MASK (0x3ff << 0)
# define DTC_0(x) ((x) << 10)
# define DTC_0_MASK (0x3ff << 10)
#define CG_BSP 0x78c
# define BSP(x) ((x) << 0)
# define BSP_MASK (0xffff << 0)
# define BSU(x) ((x) << 16)
# define BSU_MASK (0xf << 16)
#define CG_RT 0x790
# define FLS(x) ((x) << 0)
# define FLS_MASK (0xffff << 0)
# define FMS(x) ((x) << 16)
# define FMS_MASK (0xffff << 16)
#define CG_LT 0x794
# define FHS(x) ((x) << 0)
# define FHS_MASK (0xffff << 0)
#define CG_GIT 0x798
# define CG_GICST(x) ((x) << 0)
# define CG_GICST_MASK (0xffff << 0)
# define CG_GIPOT(x) ((x) << 16)
# define CG_GIPOT_MASK (0xffff << 16)
#define CG_SSP 0x7a8
# define CG_SST(x) ((x) << 0)
# define CG_SST_MASK (0xffff << 0)
# define CG_SSTU(x) ((x) << 16)
# define CG_SSTU_MASK (0xf << 16)
#define CG_RLC_REQ_AND_RSP 0x7c4
# define RLC_CG_REQ_TYPE_MASK 0xf
# define RLC_CG_REQ_TYPE_SHIFT 0
# define CG_RLC_RSP_TYPE_MASK 0xf0
# define CG_RLC_RSP_TYPE_SHIFT 4
#define CG_FC_T 0x7cc
# define FC_T(x) ((x) << 0)
# define FC_T_MASK (0xffff << 0)
# define FC_TU(x) ((x) << 16)
# define FC_TU_MASK (0x1f << 16)
#define GPIOPAD_MASK 0x1798
#define GPIOPAD_A 0x179c
#define GPIOPAD_EN 0x17a0
#define GRBM_PWR_CNTL 0x800c
# define REQ_TYPE_MASK 0xf
# define REQ_TYPE_SHIFT 0
# define RSP_TYPE_MASK 0xf0
# define RSP_TYPE_SHIFT 4
/*
* UVD
*/

View File

@ -96,6 +96,7 @@ extern int radeon_pcie_gen2;
extern int radeon_msi;
extern int radeon_lockup_timeout;
extern int radeon_fastfb;
extern int radeon_dpm;
/*
* Copy from radeon_drv.h so we don't have to include both and have conflicting
@ -150,6 +151,13 @@ extern int radeon_fastfb;
#define RADEON_RESET_MC (1 << 10)
#define RADEON_RESET_DISPLAY (1 << 11)
/* max cursor sizes (in pixels) */
#define CURSOR_WIDTH 64
#define CURSOR_HEIGHT 64
#define CIK_CURSOR_WIDTH 128
#define CIK_CURSOR_HEIGHT 128
/*
* Errata workarounds.
*/
@ -192,6 +200,7 @@ struct radeon_clock {
uint32_t default_mclk;
uint32_t default_sclk;
uint32_t default_dispclk;
uint32_t current_dispclk;
uint32_t dp_extclk;
uint32_t max_pixel_clock;
};
@ -211,13 +220,51 @@ int radeon_atom_get_clock_dividers(struct radeon_device *rdev,
u32 clock,
bool strobe_mode,
struct atom_clock_dividers *dividers);
int radeon_atom_get_memory_pll_dividers(struct radeon_device *rdev,
u32 clock,
bool strobe_mode,
struct atom_mpll_param *mpll_param);
void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type);
int radeon_atom_get_voltage_gpio_settings(struct radeon_device *rdev,
u16 voltage_level, u8 voltage_type,
u32 *gpio_value, u32 *gpio_mask);
void radeon_atom_set_engine_dram_timings(struct radeon_device *rdev,
u32 eng_clock, u32 mem_clock);
int radeon_atom_get_voltage_step(struct radeon_device *rdev,
u8 voltage_type, u16 *voltage_step);
int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type,
u16 voltage_id, u16 *voltage);
int radeon_atom_get_leakage_vddc_based_on_leakage_idx(struct radeon_device *rdev,
u16 *voltage,
u16 leakage_idx);
int radeon_atom_round_to_true_voltage(struct radeon_device *rdev,
u8 voltage_type,
u16 nominal_voltage,
u16 *true_voltage);
int radeon_atom_get_min_voltage(struct radeon_device *rdev,
u8 voltage_type, u16 *min_voltage);
int radeon_atom_get_max_voltage(struct radeon_device *rdev,
u8 voltage_type, u16 *max_voltage);
int radeon_atom_get_voltage_table(struct radeon_device *rdev,
u8 voltage_type, u8 voltage_mode,
struct atom_voltage_table *voltage_table);
bool radeon_atom_is_voltage_gpio(struct radeon_device *rdev,
u8 voltage_type, u8 voltage_mode);
void radeon_atom_update_memory_dll(struct radeon_device *rdev,
u32 mem_clock);
void radeon_atom_set_ac_timing(struct radeon_device *rdev,
u32 mem_clock);
int radeon_atom_init_mc_reg_table(struct radeon_device *rdev,
u8 module_index,
struct atom_mc_reg_table *reg_table);
int radeon_atom_get_memory_info(struct radeon_device *rdev,
u8 module_index, struct atom_memory_info *mem_info);
int radeon_atom_get_mclk_range_table(struct radeon_device *rdev,
bool gddr5, u8 module_index,
struct atom_memory_clock_range_table *mclk_range_table);
int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type,
u16 voltage_id, u16 *voltage);
void rs690_pm_info(struct radeon_device *rdev);
extern int rv6xx_get_temp(struct radeon_device *rdev);
extern int rv770_get_temp(struct radeon_device *rdev);
extern int evergreen_get_temp(struct radeon_device *rdev);
extern int sumo_get_temp(struct radeon_device *rdev);
extern int si_get_temp(struct radeon_device *rdev);
extern void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw,
unsigned *bankh, unsigned *mtaspect,
unsigned *tile_split);
@ -549,6 +596,20 @@ struct radeon_scratch {
int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg);
void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg);
/*
* GPU doorbell structures, functions & helpers
*/
struct radeon_doorbell {
u32 num_pages;
bool free[1024];
/* doorbell mmio */
resource_size_t base;
resource_size_t size;
void __iomem *ptr;
};
int radeon_doorbell_get(struct radeon_device *rdev, u32 *page);
void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell);
/*
* IRQS.
@ -600,10 +661,21 @@ struct evergreen_irq_stat_regs {
u32 afmt_status6;
};
struct cik_irq_stat_regs {
u32 disp_int;
u32 disp_int_cont;
u32 disp_int_cont2;
u32 disp_int_cont3;
u32 disp_int_cont4;
u32 disp_int_cont5;
u32 disp_int_cont6;
};
union radeon_irq_stat_regs {
struct r500_irq_stat_regs r500;
struct r600_irq_stat_regs r600;
struct evergreen_irq_stat_regs evergreen;
struct cik_irq_stat_regs cik;
};
#define RADEON_MAX_HPD_PINS 6
@ -620,6 +692,7 @@ struct radeon_irq {
bool hpd[RADEON_MAX_HPD_PINS];
bool afmt[RADEON_MAX_AFMT_BLOCKS];
union radeon_irq_stat_regs stat_regs;
bool dpm_thermal;
};
int radeon_irq_kms_init(struct radeon_device *rdev);
@ -677,6 +750,22 @@ struct radeon_ring {
u32 idx;
u64 last_semaphore_signal_addr;
u64 last_semaphore_wait_addr;
/* for CIK queues */
u32 me;
u32 pipe;
u32 queue;
struct radeon_bo *mqd_obj;
u32 doorbell_page_num;
u32 doorbell_offset;
unsigned wptr_offs;
};
struct radeon_mec {
struct radeon_bo *hpd_eop_obj;
u64 hpd_eop_gpu_addr;
u32 num_pipe;
u32 num_mec;
u32 num_queue;
};
/*
@ -778,15 +867,22 @@ struct r600_blit {
};
/*
* SI RLC stuff
* RLC stuff
*/
struct si_rlc {
#include "clearstate_defs.h"
struct radeon_rlc {
/* for power gating */
struct radeon_bo *save_restore_obj;
uint64_t save_restore_gpu_addr;
volatile uint32_t *sr_ptr;
u32 *reg_list;
u32 reg_list_size;
/* for clear state */
struct radeon_bo *clear_state_obj;
uint64_t clear_state_gpu_addr;
volatile uint32_t *cs_ptr;
struct cs_section_def *cs_data;
};
int radeon_ib_get(struct radeon_device *rdev, int ring,
@ -934,6 +1030,8 @@ struct radeon_wb {
#define CAYMAN_WB_DMA1_RPTR_OFFSET 2304
#define R600_WB_UVD_RPTR_OFFSET 2560
#define R600_WB_EVENT_OFFSET 3072
#define CIK_WB_CP1_WPTR_OFFSET 3328
#define CIK_WB_CP2_WPTR_OFFSET 3584
/**
* struct radeon_pm - power management datas
@ -958,6 +1056,7 @@ struct radeon_wb {
enum radeon_pm_method {
PM_METHOD_PROFILE,
PM_METHOD_DYNPM,
PM_METHOD_DPM,
};
enum radeon_dynpm_state {
@ -983,11 +1082,23 @@ enum radeon_voltage_type {
};
enum radeon_pm_state_type {
/* not used for dpm */
POWER_STATE_TYPE_DEFAULT,
POWER_STATE_TYPE_POWERSAVE,
/* user selectable states */
POWER_STATE_TYPE_BATTERY,
POWER_STATE_TYPE_BALANCED,
POWER_STATE_TYPE_PERFORMANCE,
/* internal states */
POWER_STATE_TYPE_INTERNAL_UVD,
POWER_STATE_TYPE_INTERNAL_UVD_SD,
POWER_STATE_TYPE_INTERNAL_UVD_HD,
POWER_STATE_TYPE_INTERNAL_UVD_HD2,
POWER_STATE_TYPE_INTERNAL_UVD_MVC,
POWER_STATE_TYPE_INTERNAL_BOOT,
POWER_STATE_TYPE_INTERNAL_THERMAL,
POWER_STATE_TYPE_INTERNAL_ACPI,
POWER_STATE_TYPE_INTERNAL_ULV,
};
enum radeon_pm_profile_type {
@ -1016,12 +1127,17 @@ struct radeon_pm_profile {
enum radeon_int_thermal_type {
THERMAL_TYPE_NONE,
THERMAL_TYPE_EXTERNAL,
THERMAL_TYPE_EXTERNAL_GPIO,
THERMAL_TYPE_RV6XX,
THERMAL_TYPE_RV770,
THERMAL_TYPE_ADT7473_WITH_INTERNAL,
THERMAL_TYPE_EVERGREEN,
THERMAL_TYPE_SUMO,
THERMAL_TYPE_NI,
THERMAL_TYPE_SI,
THERMAL_TYPE_EMC2103_WITH_INTERNAL,
THERMAL_TYPE_CI,
};
struct radeon_voltage {
@ -1075,6 +1191,193 @@ struct radeon_power_state {
*/
#define RADEON_MODE_OVERCLOCK_MARGIN 500 /* 5 MHz */
enum radeon_dpm_auto_throttle_src {
RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL,
RADEON_DPM_AUTO_THROTTLE_SRC_EXTERNAL
};
enum radeon_dpm_event_src {
RADEON_DPM_EVENT_SRC_ANALOG = 0,
RADEON_DPM_EVENT_SRC_EXTERNAL = 1,
RADEON_DPM_EVENT_SRC_DIGITAL = 2,
RADEON_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,
RADEON_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4
};
struct radeon_ps {
u32 caps; /* vbios flags */
u32 class; /* vbios flags */
u32 class2; /* vbios flags */
/* UVD clocks */
u32 vclk;
u32 dclk;
/* asic priv */
void *ps_priv;
};
struct radeon_dpm_thermal {
/* thermal interrupt work */
struct work_struct work;
/* low temperature threshold */
int min_temp;
/* high temperature threshold */
int max_temp;
/* was interrupt low to high or high to low */
bool high_to_low;
};
enum radeon_clk_action
{
RADEON_SCLK_UP = 1,
RADEON_SCLK_DOWN
};
struct radeon_blacklist_clocks
{
u32 sclk;
u32 mclk;
enum radeon_clk_action action;
};
struct radeon_clock_and_voltage_limits {
u32 sclk;
u32 mclk;
u32 vddc;
u32 vddci;
};
struct radeon_clock_array {
u32 count;
u32 *values;
};
struct radeon_clock_voltage_dependency_entry {
u32 clk;
u16 v;
};
struct radeon_clock_voltage_dependency_table {
u32 count;
struct radeon_clock_voltage_dependency_entry *entries;
};
struct radeon_cac_leakage_entry {
u16 vddc;
u32 leakage;
};
struct radeon_cac_leakage_table {
u32 count;
struct radeon_cac_leakage_entry *entries;
};
struct radeon_phase_shedding_limits_entry {
u16 voltage;
u32 sclk;
u32 mclk;
};
struct radeon_phase_shedding_limits_table {
u32 count;
struct radeon_phase_shedding_limits_entry *entries;
};
struct radeon_ppm_table {
u8 ppm_design;
u16 cpu_core_number;
u32 platform_tdp;
u32 small_ac_platform_tdp;
u32 platform_tdc;
u32 small_ac_platform_tdc;
u32 apu_tdp;
u32 dgpu_tdp;
u32 dgpu_ulv_power;
u32 tj_max;
};
struct radeon_dpm_dynamic_state {
struct radeon_clock_voltage_dependency_table vddc_dependency_on_sclk;
struct radeon_clock_voltage_dependency_table vddci_dependency_on_mclk;
struct radeon_clock_voltage_dependency_table vddc_dependency_on_mclk;
struct radeon_clock_voltage_dependency_table vddc_dependency_on_dispclk;
struct radeon_clock_array valid_sclk_values;
struct radeon_clock_array valid_mclk_values;
struct radeon_clock_and_voltage_limits max_clock_voltage_on_dc;
struct radeon_clock_and_voltage_limits max_clock_voltage_on_ac;
u32 mclk_sclk_ratio;
u32 sclk_mclk_delta;
u16 vddc_vddci_delta;
u16 min_vddc_for_pcie_gen2;
struct radeon_cac_leakage_table cac_leakage_table;
struct radeon_phase_shedding_limits_table phase_shedding_limits_table;
struct radeon_ppm_table *ppm_table;
};
struct radeon_dpm_fan {
u16 t_min;
u16 t_med;
u16 t_high;
u16 pwm_min;
u16 pwm_med;
u16 pwm_high;
u8 t_hyst;
u32 cycle_delay;
u16 t_max;
bool ucode_fan_control;
};
enum radeon_pcie_gen {
RADEON_PCIE_GEN1 = 0,
RADEON_PCIE_GEN2 = 1,
RADEON_PCIE_GEN3 = 2,
RADEON_PCIE_GEN_INVALID = 0xffff
};
struct radeon_dpm {
struct radeon_ps *ps;
/* number of valid power states */
int num_ps;
/* current power state that is active */
struct radeon_ps *current_ps;
/* requested power state */
struct radeon_ps *requested_ps;
/* boot up power state */
struct radeon_ps *boot_ps;
/* default uvd power state */
struct radeon_ps *uvd_ps;
enum radeon_pm_state_type state;
enum radeon_pm_state_type user_state;
u32 platform_caps;
u32 voltage_response_time;
u32 backbias_response_time;
void *priv;
u32 new_active_crtcs;
int new_active_crtc_count;
u32 current_active_crtcs;
int current_active_crtc_count;
struct radeon_dpm_dynamic_state dyn_state;
struct radeon_dpm_fan fan;
u32 tdp_limit;
u32 near_tdp_limit;
u32 near_tdp_limit_adjusted;
u32 sq_ramping_threshold;
u32 cac_leakage;
u16 tdp_od_limit;
u32 tdp_adjustment;
u16 load_line_slope;
bool power_control;
bool ac_power;
/* special states active */
bool thermal_active;
bool uvd_active;
/* thermal handling */
struct radeon_dpm_thermal thermal;
};
void radeon_dpm_enable_power_state(struct radeon_device *rdev,
enum radeon_pm_state_type dpm_state);
struct radeon_pm {
struct mutex mutex;
/* write locked while reprogramming mclk */
@ -1128,6 +1431,9 @@ struct radeon_pm {
/* internal thermal controller on rv6xx+ */
enum radeon_int_thermal_type int_thermal_type;
struct device *int_hwmon_dev;
/* dpm */
bool dpm_enabled;
struct radeon_dpm dpm;
};
int radeon_pm_get_type_index(struct radeon_device *rdev,
@ -1266,6 +1572,10 @@ struct radeon_asic {
int (*ib_test)(struct radeon_device *rdev, struct radeon_ring *cp);
bool (*is_lockup)(struct radeon_device *rdev, struct radeon_ring *cp);
void (*vm_flush)(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
u32 (*get_rptr)(struct radeon_device *rdev, struct radeon_ring *ring);
u32 (*get_wptr)(struct radeon_device *rdev, struct radeon_ring *ring);
void (*set_wptr)(struct radeon_device *rdev, struct radeon_ring *ring);
} ring[RADEON_NUM_RINGS];
/* irqs */
struct {
@ -1325,7 +1635,7 @@ struct radeon_asic {
bool (*sense)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
void (*set_polarity)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
} hpd;
/* power management */
/* static power management */
struct {
void (*misc)(struct radeon_device *rdev);
void (*prepare)(struct radeon_device *rdev);
@ -1340,7 +1650,23 @@ struct radeon_asic {
void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
void (*set_clock_gating)(struct radeon_device *rdev, int enable);
int (*set_uvd_clocks)(struct radeon_device *rdev, u32 vclk, u32 dclk);
int (*get_temperature)(struct radeon_device *rdev);
} pm;
/* dynamic power management */
struct {
int (*init)(struct radeon_device *rdev);
void (*setup_asic)(struct radeon_device *rdev);
int (*enable)(struct radeon_device *rdev);
void (*disable)(struct radeon_device *rdev);
int (*pre_set_power_state)(struct radeon_device *rdev);
int (*set_power_state)(struct radeon_device *rdev);
void (*post_set_power_state)(struct radeon_device *rdev);
void (*display_configuration_changed)(struct radeon_device *rdev);
void (*fini)(struct radeon_device *rdev);
u32 (*get_sclk)(struct radeon_device *rdev, bool low);
u32 (*get_mclk)(struct radeon_device *rdev, bool low);
void (*print_power_state)(struct radeon_device *rdev, struct radeon_ps *ps);
} dpm;
/* pageflipping */
struct {
void (*pre_page_flip)(struct radeon_device *rdev, int crtc);
@ -1505,6 +1831,36 @@ struct si_asic {
uint32_t tile_mode_array[32];
};
struct cik_asic {
unsigned max_shader_engines;
unsigned max_tile_pipes;
unsigned max_cu_per_sh;
unsigned max_sh_per_se;
unsigned max_backends_per_se;
unsigned max_texture_channel_caches;
unsigned max_gprs;
unsigned max_gs_threads;
unsigned max_hw_contexts;
unsigned sc_prim_fifo_size_frontend;
unsigned sc_prim_fifo_size_backend;
unsigned sc_hiz_tile_fifo_size;
unsigned sc_earlyz_tile_fifo_size;
unsigned num_tile_pipes;
unsigned num_backends_per_se;
unsigned backend_disable_mask_per_asic;
unsigned backend_map;
unsigned num_texture_channel_caches;
unsigned mem_max_burst_length_bytes;
unsigned mem_row_size_in_kb;
unsigned shader_engine_tile_size;
unsigned num_gpus;
unsigned multi_gpu_tile_size;
unsigned tile_config;
uint32_t tile_mode_array[32];
};
union radeon_asic_config {
struct r300_asic r300;
struct r100_asic r100;
@ -1513,6 +1869,7 @@ union radeon_asic_config {
struct evergreen_asic evergreen;
struct cayman_asic cayman;
struct si_asic si;
struct cik_asic cik;
};
/*
@ -1657,6 +2014,7 @@ struct radeon_device {
struct radeon_gart gart;
struct radeon_mode_info mode_info;
struct radeon_scratch scratch;
struct radeon_doorbell doorbell;
struct radeon_mman mman;
struct radeon_fence_driver fence_drv[RADEON_NUM_RINGS];
wait_queue_head_t fence_queue;
@ -1684,13 +2042,18 @@ struct radeon_device {
const struct firmware *mc_fw; /* NI MC firmware */
const struct firmware *ce_fw; /* SI CE firmware */
const struct firmware *uvd_fw; /* UVD firmware */
const struct firmware *mec_fw; /* CIK MEC firmware */
const struct firmware *sdma_fw; /* CIK SDMA firmware */
const struct firmware *smc_fw; /* SMC firmware */
struct r600_blit r600_blit;
struct r600_vram_scratch vram_scratch;
int msi_enabled; /* msi enabled */
struct r600_ih ih; /* r6/700 interrupt ring */
struct si_rlc rlc;
struct radeon_rlc rlc;
struct radeon_mec mec;
struct work_struct hotplug_work;
struct work_struct audio_work;
struct work_struct reset_work;
int num_crtc; /* number of crtcs */
struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
bool audio_enabled;
@ -1727,6 +2090,9 @@ void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
u32 r100_io_rreg(struct radeon_device *rdev, u32 reg);
void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 offset);
void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v);
/*
* Cast helper
*/
@ -1754,6 +2120,18 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
#define WREG32_PCIE(reg, v) rv370_pcie_wreg(rdev, (reg), (v))
#define RREG32_PCIE_PORT(reg) rdev->pciep_rreg(rdev, (reg))
#define WREG32_PCIE_PORT(reg, v) rdev->pciep_wreg(rdev, (reg), (v))
#define RREG32_SMC(reg) tn_smc_rreg(rdev, (reg))
#define WREG32_SMC(reg, v) tn_smc_wreg(rdev, (reg), (v))
#define RREG32_RCU(reg) r600_rcu_rreg(rdev, (reg))
#define WREG32_RCU(reg, v) r600_rcu_wreg(rdev, (reg), (v))
#define RREG32_CG(reg) eg_cg_rreg(rdev, (reg))
#define WREG32_CG(reg, v) eg_cg_wreg(rdev, (reg), (v))
#define RREG32_PIF_PHY0(reg) eg_pif_phy0_rreg(rdev, (reg))
#define WREG32_PIF_PHY0(reg, v) eg_pif_phy0_wreg(rdev, (reg), (v))
#define RREG32_PIF_PHY1(reg) eg_pif_phy1_rreg(rdev, (reg))
#define WREG32_PIF_PHY1(reg, v) eg_pif_phy1_wreg(rdev, (reg), (v))
#define RREG32_UVD_CTX(reg) r600_uvd_ctx_rreg(rdev, (reg))
#define WREG32_UVD_CTX(reg, v) r600_uvd_ctx_wreg(rdev, (reg), (v))
#define WREG32_P(reg, val, mask) \
do { \
uint32_t tmp_ = RREG32(reg); \
@ -1774,6 +2152,9 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
#define RREG32_IO(reg) r100_io_rreg(rdev, (reg))
#define WREG32_IO(reg, v) r100_io_wreg(rdev, (reg), (v))
#define RDOORBELL32(offset) cik_mm_rdoorbell(rdev, (offset))
#define WDOORBELL32(offset, v) cik_mm_wdoorbell(rdev, (offset), (v))
/*
* Indirect registers accessor
*/
@ -1792,6 +2173,96 @@ static inline void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uin
WREG32(RADEON_PCIE_DATA, (v));
}
static inline u32 tn_smc_rreg(struct radeon_device *rdev, u32 reg)
{
u32 r;
WREG32(TN_SMC_IND_INDEX_0, (reg));
r = RREG32(TN_SMC_IND_DATA_0);
return r;
}
static inline void tn_smc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
WREG32(TN_SMC_IND_INDEX_0, (reg));
WREG32(TN_SMC_IND_DATA_0, (v));
}
static inline u32 r600_rcu_rreg(struct radeon_device *rdev, u32 reg)
{
u32 r;
WREG32(R600_RCU_INDEX, ((reg) & 0x1fff));
r = RREG32(R600_RCU_DATA);
return r;
}
static inline void r600_rcu_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
WREG32(R600_RCU_INDEX, ((reg) & 0x1fff));
WREG32(R600_RCU_DATA, (v));
}
static inline u32 eg_cg_rreg(struct radeon_device *rdev, u32 reg)
{
u32 r;
WREG32(EVERGREEN_CG_IND_ADDR, ((reg) & 0xffff));
r = RREG32(EVERGREEN_CG_IND_DATA);
return r;
}
static inline void eg_cg_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
WREG32(EVERGREEN_CG_IND_ADDR, ((reg) & 0xffff));
WREG32(EVERGREEN_CG_IND_DATA, (v));
}
static inline u32 eg_pif_phy0_rreg(struct radeon_device *rdev, u32 reg)
{
u32 r;
WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff));
r = RREG32(EVERGREEN_PIF_PHY0_DATA);
return r;
}
static inline void eg_pif_phy0_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff));
WREG32(EVERGREEN_PIF_PHY0_DATA, (v));
}
static inline u32 eg_pif_phy1_rreg(struct radeon_device *rdev, u32 reg)
{
u32 r;
WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff));
r = RREG32(EVERGREEN_PIF_PHY1_DATA);
return r;
}
static inline void eg_pif_phy1_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff));
WREG32(EVERGREEN_PIF_PHY1_DATA, (v));
}
static inline u32 r600_uvd_ctx_rreg(struct radeon_device *rdev, u32 reg)
{
u32 r;
WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff));
r = RREG32(R600_UVD_CTX_DATA);
return r;
}
static inline void r600_uvd_ctx_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff));
WREG32(R600_UVD_CTX_DATA, (v));
}
void r100_pll_errata_after_index(struct radeon_device *rdev);
@ -1840,6 +2311,16 @@ void r100_pll_errata_after_index(struct radeon_device *rdev);
(rdev->flags & RADEON_IS_IGP))
#define ASIC_IS_DCE64(rdev) ((rdev->family == CHIP_OLAND))
#define ASIC_IS_NODCE(rdev) ((rdev->family == CHIP_HAINAN))
#define ASIC_IS_DCE8(rdev) ((rdev->family >= CHIP_BONAIRE))
#define ASIC_IS_LOMBOK(rdev) ((rdev->ddev->pdev->device == 0x6849) || \
(rdev->ddev->pdev->device == 0x6850) || \
(rdev->ddev->pdev->device == 0x6858) || \
(rdev->ddev->pdev->device == 0x6859) || \
(rdev->ddev->pdev->device == 0x6840) || \
(rdev->ddev->pdev->device == 0x6841) || \
(rdev->ddev->pdev->device == 0x6842) || \
(rdev->ddev->pdev->device == 0x6843))
/*
* BIOS helpers.
@ -1892,6 +2373,9 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
#define radeon_ring_ib_parse(rdev, r, ib) (rdev)->asic->ring[(r)].ib_parse((rdev), (ib))
#define radeon_ring_is_lockup(rdev, r, cp) (rdev)->asic->ring[(r)].is_lockup((rdev), (cp))
#define radeon_ring_vm_flush(rdev, r, vm) (rdev)->asic->ring[(r)].vm_flush((rdev), (r), (vm))
#define radeon_ring_get_rptr(rdev, r) (rdev)->asic->ring[(r)->idx].get_rptr((rdev), (r))
#define radeon_ring_get_wptr(rdev, r) (rdev)->asic->ring[(r)->idx].get_wptr((rdev), (r))
#define radeon_ring_set_wptr(rdev, r) (rdev)->asic->ring[(r)->idx].set_wptr((rdev), (r))
#define radeon_irq_set(rdev) (rdev)->asic->irq.set((rdev))
#define radeon_irq_process(rdev) (rdev)->asic->irq.process((rdev))
#define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->display.get_vblank_counter((rdev), (crtc))
@ -1915,6 +2399,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
#define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->pm.set_pcie_lanes((rdev), (l))
#define radeon_set_clock_gating(rdev, e) (rdev)->asic->pm.set_clock_gating((rdev), (e))
#define radeon_set_uvd_clocks(rdev, v, d) (rdev)->asic->pm.set_uvd_clocks((rdev), (v), (d))
#define radeon_get_temperature(rdev) (rdev)->asic->pm.get_temperature((rdev))
#define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->surface.set_reg((rdev), (r), (f), (p), (o), (s)))
#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->surface.clear_reg((rdev), (r)))
#define radeon_bandwidth_update(rdev) (rdev)->asic->display.bandwidth_update((rdev))
@ -1935,6 +2420,18 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
#define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev))
#define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev))
#define radeon_get_gpu_clock_counter(rdev) (rdev)->asic->get_gpu_clock_counter((rdev))
#define radeon_dpm_init(rdev) rdev->asic->dpm.init((rdev))
#define radeon_dpm_setup_asic(rdev) rdev->asic->dpm.setup_asic((rdev))
#define radeon_dpm_enable(rdev) rdev->asic->dpm.enable((rdev))
#define radeon_dpm_disable(rdev) rdev->asic->dpm.disable((rdev))
#define radeon_dpm_pre_set_power_state(rdev) rdev->asic->dpm.pre_set_power_state((rdev))
#define radeon_dpm_set_power_state(rdev) rdev->asic->dpm.set_power_state((rdev))
#define radeon_dpm_post_set_power_state(rdev) rdev->asic->dpm.post_set_power_state((rdev))
#define radeon_dpm_display_configuration_changed(rdev) rdev->asic->dpm.display_configuration_changed((rdev))
#define radeon_dpm_fini(rdev) rdev->asic->dpm.fini((rdev))
#define radeon_dpm_get_sclk(rdev, l) rdev->asic->dpm.get_sclk((rdev), (l))
#define radeon_dpm_get_mclk(rdev, l) rdev->asic->dpm.get_mclk((rdev), (l))
#define radeon_dpm_print_power_state(rdev, ps) rdev->asic->dpm.print_power_state((rdev), (ps))
/* Common functions */
/* AGP */
@ -2054,6 +2551,10 @@ extern int ni_mc_load_microcode(struct radeon_device *rdev);
#if defined(CONFIG_ACPI)
extern int radeon_acpi_init(struct radeon_device *rdev);
extern void radeon_acpi_fini(struct radeon_device *rdev);
extern bool radeon_acpi_is_pcie_performance_request_supported(struct radeon_device *rdev);
extern int radeon_acpi_pcie_performance_request(struct radeon_device *rdev,
u8 perf_req, bool advertise);
extern int radeon_acpi_pcie_notify_device_ready(struct radeon_device *rdev);
#else
static inline int radeon_acpi_init(struct radeon_device *rdev) { return 0; }
static inline void radeon_acpi_fini(struct radeon_device *rdev) { }

View File

@ -78,6 +78,22 @@ struct atcs_verify_interface {
u32 function_bits; /* supported functions bit vector */
} __packed;
#define ATCS_VALID_FLAGS_MASK 0x3
struct atcs_pref_req_input {
u16 size; /* structure size in bytes (includes size field) */
u16 client_id; /* client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */
u16 valid_flags_mask; /* valid flags mask */
u16 flags; /* flags */
u8 req_type; /* request type */
u8 perf_req; /* performance request */
} __packed;
struct atcs_pref_req_output {
u16 size; /* structure size in bytes (includes size field) */
u8 ret_val; /* return value */
} __packed;
/* Call the ATIF method
*/
/**
@ -505,6 +521,135 @@ out:
return err;
}
/**
* radeon_acpi_is_pcie_performance_request_supported
*
* @rdev: radeon_device pointer
*
* Check if the ATCS pcie_perf_req and pcie_dev_rdy methods
* are supported (all asics).
* returns true if supported, false if not.
*/
bool radeon_acpi_is_pcie_performance_request_supported(struct radeon_device *rdev)
{
struct radeon_atcs *atcs = &rdev->atcs;
if (atcs->functions.pcie_perf_req && atcs->functions.pcie_dev_rdy)
return true;
return false;
}
/**
* radeon_acpi_pcie_notify_device_ready
*
* @rdev: radeon_device pointer
*
* Executes the PCIE_DEVICE_READY_NOTIFICATION method
* (all asics).
* returns 0 on success, error on failure.
*/
int radeon_acpi_pcie_notify_device_ready(struct radeon_device *rdev)
{
acpi_handle handle;
union acpi_object *info;
struct radeon_atcs *atcs = &rdev->atcs;
/* Get the device handle */
handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev);
if (!handle)
return -EINVAL;
if (!atcs->functions.pcie_dev_rdy)
return -EINVAL;
info = radeon_atcs_call(handle, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION, NULL);
if (!info)
return -EIO;
kfree(info);
return 0;
}
/**
* radeon_acpi_pcie_performance_request
*
* @rdev: radeon_device pointer
* @perf_req: requested perf level (pcie gen speed)
* @advertise: set advertise caps flag if set
*
* Executes the PCIE_PERFORMANCE_REQUEST method to
* change the pcie gen speed (all asics).
* returns 0 on success, error on failure.
*/
int radeon_acpi_pcie_performance_request(struct radeon_device *rdev,
u8 perf_req, bool advertise)
{
acpi_handle handle;
union acpi_object *info;
struct radeon_atcs *atcs = &rdev->atcs;
struct atcs_pref_req_input atcs_input;
struct atcs_pref_req_output atcs_output;
struct acpi_buffer params;
size_t size;
u32 retry = 3;
/* Get the device handle */
handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev);
if (!handle)
return -EINVAL;
if (!atcs->functions.pcie_perf_req)
return -EINVAL;
atcs_input.size = sizeof(struct atcs_pref_req_input);
/* client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */
atcs_input.client_id = rdev->pdev->devfn | (rdev->pdev->bus->number << 8);
atcs_input.valid_flags_mask = ATCS_VALID_FLAGS_MASK;
atcs_input.flags = ATCS_WAIT_FOR_COMPLETION;
if (advertise)
atcs_input.flags |= ATCS_ADVERTISE_CAPS;
atcs_input.req_type = ATCS_PCIE_LINK_SPEED;
atcs_input.perf_req = perf_req;
params.length = sizeof(struct atcs_pref_req_input);
params.pointer = &atcs_input;
while (retry--) {
info = radeon_atcs_call(handle, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST, &params);
if (!info)
return -EIO;
memset(&atcs_output, 0, sizeof(atcs_output));
size = *(u16 *) info->buffer.pointer;
if (size < 3) {
DRM_INFO("ATCS buffer is too small: %zu\n", size);
kfree(info);
return -EINVAL;
}
size = min(sizeof(atcs_output), size);
memcpy(&atcs_output, info->buffer.pointer, size);
kfree(info);
switch (atcs_output.ret_val) {
case ATCS_REQUEST_REFUSED:
default:
return -EINVAL;
case ATCS_REQUEST_COMPLETE:
return 0;
case ATCS_REQUEST_IN_PROGRESS:
udelay(10);
break;
}
}
return 0;
}
/**
* radeon_acpi_event - handle notify events
*

File diff suppressed because it is too large Load Diff

View File

@ -47,6 +47,12 @@ u8 atombios_get_backlight_level(struct radeon_encoder *radeon_encoder);
void radeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level);
u8 radeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder);
u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev,
struct radeon_ring *ring);
u32 radeon_ring_generic_get_wptr(struct radeon_device *rdev,
struct radeon_ring *ring);
void radeon_ring_generic_set_wptr(struct radeon_device *rdev,
struct radeon_ring *ring);
/*
* r100,rv100,rs100,rv200,rs200
@ -395,6 +401,33 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
int r600_mc_wait_for_idle(struct radeon_device *rdev);
u32 r600_get_xclk(struct radeon_device *rdev);
uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev);
int rv6xx_get_temp(struct radeon_device *rdev);
int r600_dpm_pre_set_power_state(struct radeon_device *rdev);
void r600_dpm_post_set_power_state(struct radeon_device *rdev);
/* rv6xx dpm */
int rv6xx_dpm_init(struct radeon_device *rdev);
int rv6xx_dpm_enable(struct radeon_device *rdev);
void rv6xx_dpm_disable(struct radeon_device *rdev);
int rv6xx_dpm_set_power_state(struct radeon_device *rdev);
void rv6xx_setup_asic(struct radeon_device *rdev);
void rv6xx_dpm_display_configuration_changed(struct radeon_device *rdev);
void rv6xx_dpm_fini(struct radeon_device *rdev);
u32 rv6xx_dpm_get_sclk(struct radeon_device *rdev, bool low);
u32 rv6xx_dpm_get_mclk(struct radeon_device *rdev, bool low);
void rv6xx_dpm_print_power_state(struct radeon_device *rdev,
struct radeon_ps *ps);
/* rs780 dpm */
int rs780_dpm_init(struct radeon_device *rdev);
int rs780_dpm_enable(struct radeon_device *rdev);
void rs780_dpm_disable(struct radeon_device *rdev);
int rs780_dpm_set_power_state(struct radeon_device *rdev);
void rs780_dpm_setup_asic(struct radeon_device *rdev);
void rs780_dpm_display_configuration_changed(struct radeon_device *rdev);
void rs780_dpm_fini(struct radeon_device *rdev);
u32 rs780_dpm_get_sclk(struct radeon_device *rdev, bool low);
u32 rs780_dpm_get_mclk(struct radeon_device *rdev, bool low);
void rs780_dpm_print_power_state(struct radeon_device *rdev,
struct radeon_ps *ps);
/* uvd */
int r600_uvd_init(struct radeon_device *rdev);
@ -428,6 +461,19 @@ int rv770_copy_dma(struct radeon_device *rdev,
u32 rv770_get_xclk(struct radeon_device *rdev);
int rv770_uvd_resume(struct radeon_device *rdev);
int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
int rv770_get_temp(struct radeon_device *rdev);
/* rv7xx pm */
int rv770_dpm_init(struct radeon_device *rdev);
int rv770_dpm_enable(struct radeon_device *rdev);
void rv770_dpm_disable(struct radeon_device *rdev);
int rv770_dpm_set_power_state(struct radeon_device *rdev);
void rv770_dpm_setup_asic(struct radeon_device *rdev);
void rv770_dpm_display_configuration_changed(struct radeon_device *rdev);
void rv770_dpm_fini(struct radeon_device *rdev);
u32 rv770_dpm_get_sclk(struct radeon_device *rdev, bool low);
u32 rv770_dpm_get_mclk(struct radeon_device *rdev, bool low);
void rv770_dpm_print_power_state(struct radeon_device *rdev,
struct radeon_ps *ps);
/*
* evergreen
@ -482,6 +528,39 @@ int evergreen_copy_dma(struct radeon_device *rdev,
struct radeon_fence **fence);
void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable);
void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
int evergreen_get_temp(struct radeon_device *rdev);
int sumo_get_temp(struct radeon_device *rdev);
int tn_get_temp(struct radeon_device *rdev);
int cypress_dpm_init(struct radeon_device *rdev);
void cypress_dpm_setup_asic(struct radeon_device *rdev);
int cypress_dpm_enable(struct radeon_device *rdev);
void cypress_dpm_disable(struct radeon_device *rdev);
int cypress_dpm_set_power_state(struct radeon_device *rdev);
void cypress_dpm_display_configuration_changed(struct radeon_device *rdev);
void cypress_dpm_fini(struct radeon_device *rdev);
int btc_dpm_init(struct radeon_device *rdev);
void btc_dpm_setup_asic(struct radeon_device *rdev);
int btc_dpm_enable(struct radeon_device *rdev);
void btc_dpm_disable(struct radeon_device *rdev);
int btc_dpm_pre_set_power_state(struct radeon_device *rdev);
int btc_dpm_set_power_state(struct radeon_device *rdev);
void btc_dpm_post_set_power_state(struct radeon_device *rdev);
void btc_dpm_fini(struct radeon_device *rdev);
u32 btc_dpm_get_sclk(struct radeon_device *rdev, bool low);
u32 btc_dpm_get_mclk(struct radeon_device *rdev, bool low);
int sumo_dpm_init(struct radeon_device *rdev);
int sumo_dpm_enable(struct radeon_device *rdev);
void sumo_dpm_disable(struct radeon_device *rdev);
int sumo_dpm_pre_set_power_state(struct radeon_device *rdev);
int sumo_dpm_set_power_state(struct radeon_device *rdev);
void sumo_dpm_post_set_power_state(struct radeon_device *rdev);
void sumo_dpm_setup_asic(struct radeon_device *rdev);
void sumo_dpm_display_configuration_changed(struct radeon_device *rdev);
void sumo_dpm_fini(struct radeon_device *rdev);
u32 sumo_dpm_get_sclk(struct radeon_device *rdev, bool low);
u32 sumo_dpm_get_mclk(struct radeon_device *rdev, bool low);
void sumo_dpm_print_power_state(struct radeon_device *rdev,
struct radeon_ps *ps);
/*
* cayman
@ -516,6 +595,32 @@ bool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
int ni_dpm_init(struct radeon_device *rdev);
void ni_dpm_setup_asic(struct radeon_device *rdev);
int ni_dpm_enable(struct radeon_device *rdev);
void ni_dpm_disable(struct radeon_device *rdev);
int ni_dpm_pre_set_power_state(struct radeon_device *rdev);
int ni_dpm_set_power_state(struct radeon_device *rdev);
void ni_dpm_post_set_power_state(struct radeon_device *rdev);
void ni_dpm_fini(struct radeon_device *rdev);
u32 ni_dpm_get_sclk(struct radeon_device *rdev, bool low);
u32 ni_dpm_get_mclk(struct radeon_device *rdev, bool low);
void ni_dpm_print_power_state(struct radeon_device *rdev,
struct radeon_ps *ps);
int trinity_dpm_init(struct radeon_device *rdev);
int trinity_dpm_enable(struct radeon_device *rdev);
void trinity_dpm_disable(struct radeon_device *rdev);
int trinity_dpm_pre_set_power_state(struct radeon_device *rdev);
int trinity_dpm_set_power_state(struct radeon_device *rdev);
void trinity_dpm_post_set_power_state(struct radeon_device *rdev);
void trinity_dpm_setup_asic(struct radeon_device *rdev);
void trinity_dpm_display_configuration_changed(struct radeon_device *rdev);
void trinity_dpm_fini(struct radeon_device *rdev);
u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low);
u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low);
void trinity_dpm_print_power_state(struct radeon_device *rdev,
struct radeon_ps *ps);
/* DCE6 - SI */
void dce6_bandwidth_update(struct radeon_device *rdev);
@ -552,5 +657,78 @@ void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
u32 si_get_xclk(struct radeon_device *rdev);
uint64_t si_get_gpu_clock_counter(struct radeon_device *rdev);
int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
int si_get_temp(struct radeon_device *rdev);
int si_dpm_init(struct radeon_device *rdev);
void si_dpm_setup_asic(struct radeon_device *rdev);
int si_dpm_enable(struct radeon_device *rdev);
void si_dpm_disable(struct radeon_device *rdev);
int si_dpm_pre_set_power_state(struct radeon_device *rdev);
int si_dpm_set_power_state(struct radeon_device *rdev);
void si_dpm_post_set_power_state(struct radeon_device *rdev);
void si_dpm_fini(struct radeon_device *rdev);
void si_dpm_display_configuration_changed(struct radeon_device *rdev);
/* DCE8 - CIK */
void dce8_bandwidth_update(struct radeon_device *rdev);
/*
* cik
*/
uint64_t cik_get_gpu_clock_counter(struct radeon_device *rdev);
u32 cik_get_xclk(struct radeon_device *rdev);
uint32_t cik_pciep_rreg(struct radeon_device *rdev, uint32_t reg);
void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
int cik_uvd_resume(struct radeon_device *rdev);
void cik_sdma_fence_ring_emit(struct radeon_device *rdev,
struct radeon_fence *fence);
void cik_sdma_semaphore_ring_emit(struct radeon_device *rdev,
struct radeon_ring *ring,
struct radeon_semaphore *semaphore,
bool emit_wait);
void cik_sdma_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
int cik_copy_dma(struct radeon_device *rdev,
uint64_t src_offset, uint64_t dst_offset,
unsigned num_gpu_pages,
struct radeon_fence **fence);
int cik_sdma_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
bool cik_sdma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
void cik_fence_gfx_ring_emit(struct radeon_device *rdev,
struct radeon_fence *fence);
void cik_fence_compute_ring_emit(struct radeon_device *rdev,
struct radeon_fence *fence);
void cik_semaphore_ring_emit(struct radeon_device *rdev,
struct radeon_ring *cp,
struct radeon_semaphore *semaphore,
bool emit_wait);
void cik_pcie_gart_tlb_flush(struct radeon_device *rdev);
int cik_init(struct radeon_device *rdev);
void cik_fini(struct radeon_device *rdev);
int cik_suspend(struct radeon_device *rdev);
int cik_resume(struct radeon_device *rdev);
bool cik_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
int cik_asic_reset(struct radeon_device *rdev);
void cik_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
int cik_irq_set(struct radeon_device *rdev);
int cik_irq_process(struct radeon_device *rdev);
int cik_vm_init(struct radeon_device *rdev);
void cik_vm_fini(struct radeon_device *rdev);
void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
void cik_vm_set_page(struct radeon_device *rdev,
struct radeon_ib *ib,
uint64_t pe,
uint64_t addr, unsigned count,
uint32_t incr, uint32_t flags);
void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
int cik_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
struct radeon_ring *ring);
u32 cik_compute_ring_get_wptr(struct radeon_device *rdev,
struct radeon_ring *ring);
void cik_compute_ring_set_wptr(struct radeon_device *rdev,
struct radeon_ring *ring);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -550,6 +550,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
return r;
}
/* XXX pick SD/HD/MVC */
if (parser.ring == R600_RING_TYPE_UVD_INDEX)
radeon_uvd_note_usage(rdev);

View File

@ -27,9 +27,6 @@
#include <drm/radeon_drm.h>
#include "radeon.h"
#define CURSOR_WIDTH 64
#define CURSOR_HEIGHT 64
static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock)
{
struct radeon_device *rdev = crtc->dev->dev_private;
@ -167,7 +164,8 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
goto unpin;
}
if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
if ((width > radeon_crtc->max_cursor_width) ||
(height > radeon_crtc->max_cursor_height)) {
DRM_ERROR("bad cursor width or height %d x %d\n", width, height);
return -EINVAL;
}
@ -233,11 +231,11 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
if (x < 0) {
xorigin = min(-x, CURSOR_WIDTH - 1);
xorigin = min(-x, radeon_crtc->max_cursor_width - 1);
x = 0;
}
if (y < 0) {
yorigin = min(-y, CURSOR_HEIGHT - 1);
yorigin = min(-y, radeon_crtc->max_cursor_height - 1);
y = 0;
}

View File

@ -95,6 +95,9 @@ static const char radeon_family_name[][16] = {
"VERDE",
"OLAND",
"HAINAN",
"BONAIRE",
"KAVERI",
"KABINI",
"LAST",
};
@ -228,6 +231,94 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg)
}
}
/*
* GPU doorbell aperture helpers function.
*/
/**
* radeon_doorbell_init - Init doorbell driver information.
*
* @rdev: radeon_device pointer
*
* Init doorbell driver information (CIK)
* Returns 0 on success, error on failure.
*/
int radeon_doorbell_init(struct radeon_device *rdev)
{
int i;
/* doorbell bar mapping */
rdev->doorbell.base = pci_resource_start(rdev->pdev, 2);
rdev->doorbell.size = pci_resource_len(rdev->pdev, 2);
/* limit to 4 MB for now */
if (rdev->doorbell.size > (4 * 1024 * 1024))
rdev->doorbell.size = 4 * 1024 * 1024;
rdev->doorbell.ptr = ioremap(rdev->doorbell.base, rdev->doorbell.size);
if (rdev->doorbell.ptr == NULL) {
return -ENOMEM;
}
DRM_INFO("doorbell mmio base: 0x%08X\n", (uint32_t)rdev->doorbell.base);
DRM_INFO("doorbell mmio size: %u\n", (unsigned)rdev->doorbell.size);
rdev->doorbell.num_pages = rdev->doorbell.size / PAGE_SIZE;
for (i = 0; i < rdev->doorbell.num_pages; i++) {
rdev->doorbell.free[i] = true;
}
return 0;
}
/**
* radeon_doorbell_fini - Tear down doorbell driver information.
*
* @rdev: radeon_device pointer
*
* Tear down doorbell driver information (CIK)
*/
void radeon_doorbell_fini(struct radeon_device *rdev)
{
iounmap(rdev->doorbell.ptr);
rdev->doorbell.ptr = NULL;
}
/**
* radeon_doorbell_get - Allocate a doorbell page
*
* @rdev: radeon_device pointer
* @doorbell: doorbell page number
*
* Allocate a doorbell page for use by the driver (all asics).
* Returns 0 on success or -EINVAL on failure.
*/
int radeon_doorbell_get(struct radeon_device *rdev, u32 *doorbell)
{
int i;
for (i = 0; i < rdev->doorbell.num_pages; i++) {
if (rdev->doorbell.free[i]) {
rdev->doorbell.free[i] = false;
*doorbell = i;
return 0;
}
}
return -EINVAL;
}
/**
* radeon_doorbell_free - Free a doorbell page
*
* @rdev: radeon_device pointer
* @doorbell: doorbell page number
*
* Free a doorbell page allocated for use by the driver (all asics)
*/
void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell)
{
if (doorbell < rdev->doorbell.num_pages)
rdev->doorbell.free[doorbell] = true;
}
/*
* radeon_wb_*()
* Writeback is the the method by which the the GPU updates special pages
@ -1145,8 +1236,13 @@ int radeon_device_init(struct radeon_device *rdev,
/* Registers mapping */
/* TODO: block userspace mapping of io register */
spin_lock_init(&rdev->mmio_idx_lock);
rdev->rmmio_base = pci_resource_start(rdev->pdev, 2);
rdev->rmmio_size = pci_resource_len(rdev->pdev, 2);
if (rdev->family >= CHIP_BONAIRE) {
rdev->rmmio_base = pci_resource_start(rdev->pdev, 5);
rdev->rmmio_size = pci_resource_len(rdev->pdev, 5);
} else {
rdev->rmmio_base = pci_resource_start(rdev->pdev, 2);
rdev->rmmio_size = pci_resource_len(rdev->pdev, 2);
}
rdev->rmmio = ioremap(rdev->rmmio_base, rdev->rmmio_size);
if (rdev->rmmio == NULL) {
return -ENOMEM;
@ -1154,6 +1250,10 @@ int radeon_device_init(struct radeon_device *rdev,
DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base);
DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size);
/* doorbell bar mapping */
if (rdev->family >= CHIP_BONAIRE)
radeon_doorbell_init(rdev);
/* io port mapping */
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
if (pci_resource_flags(rdev->pdev, i) & IORESOURCE_IO) {
@ -1231,6 +1331,8 @@ void radeon_device_fini(struct radeon_device *rdev)
rdev->rio_mem = NULL;
iounmap(rdev->rmmio);
rdev->rmmio = NULL;
if (rdev->family >= CHIP_BONAIRE)
radeon_doorbell_fini(rdev);
radeon_debugfs_remove_files(rdev);
}

View File

@ -153,7 +153,13 @@ static void dce5_crtc_load_lut(struct drm_crtc *crtc)
NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS)));
/* XXX match this to the depth of the crtc fmt block, move to modeset? */
WREG32(0x6940 + radeon_crtc->crtc_offset, 0);
if (ASIC_IS_DCE8(rdev)) {
/* XXX this only needs to be programmed once per crtc at startup,
* not sure where the best place for it is
*/
WREG32(CIK_ALPHA_CONTROL + radeon_crtc->crtc_offset,
CIK_CURSOR_ALPHA_BLND_ENA);
}
}
static void legacy_crtc_load_lut(struct drm_crtc *crtc)
@ -512,6 +518,14 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
radeon_crtc->crtc_id = index;
rdev->mode_info.crtcs[index] = radeon_crtc;
if (rdev->family >= CHIP_BONAIRE) {
radeon_crtc->max_cursor_width = CIK_CURSOR_WIDTH;
radeon_crtc->max_cursor_height = CIK_CURSOR_HEIGHT;
} else {
radeon_crtc->max_cursor_width = CURSOR_WIDTH;
radeon_crtc->max_cursor_height = CURSOR_HEIGHT;
}
#if 0
radeon_crtc->mode_set.crtc = &radeon_crtc->base;
radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1);
@ -530,7 +544,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
radeon_legacy_init_crtc(dev, radeon_crtc);
}
static const char *encoder_names[37] = {
static const char *encoder_names[38] = {
"NONE",
"INTERNAL_LVDS",
"INTERNAL_TMDS1",
@ -567,7 +581,8 @@ static const char *encoder_names[37] = {
"INTERNAL_UNIPHY2",
"NUTMEG",
"TRAVIS",
"INTERNAL_VCE"
"INTERNAL_VCE",
"INTERNAL_UNIPHY3",
};
static const char *hpd_names[6] = {

View File

@ -74,9 +74,10 @@
* 2.31.0 - Add fastfb support for rs690
* 2.32.0 - new info request for rings working
* 2.33.0 - Add SI tiling mode array query
* 2.34.0 - Add CIK tiling mode array query
*/
#define KMS_DRIVER_MAJOR 2
#define KMS_DRIVER_MINOR 33
#define KMS_DRIVER_MINOR 34
#define KMS_DRIVER_PATCHLEVEL 0
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
int radeon_driver_unload_kms(struct drm_device *dev);
@ -164,6 +165,7 @@ int radeon_pcie_gen2 = -1;
int radeon_msi = -1;
int radeon_lockup_timeout = 10000;
int radeon_fastfb = 0;
int radeon_dpm = -1;
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
module_param_named(no_wb, radeon_no_wb, int, 0444);
@ -219,6 +221,9 @@ module_param_named(lockup_timeout, radeon_lockup_timeout, int, 0444);
MODULE_PARM_DESC(fastfb, "Direct FB access for IGP chips (0 = disable, 1 = enable)");
module_param_named(fastfb, radeon_fastfb, int, 0444);
MODULE_PARM_DESC(dpm, "DPM support (1 = enable, 0 = disable, -1 = auto)");
module_param_named(dpm, radeon_dpm, int, 0444);
static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
};

View File

@ -93,6 +93,9 @@ enum radeon_family {
CHIP_VERDE,
CHIP_OLAND,
CHIP_HAINAN,
CHIP_BONAIRE,
CHIP_KAVERI,
CHIP_KABINI,
CHIP_LAST,
};

View File

@ -81,6 +81,23 @@ static void radeon_hotplug_work_func(struct work_struct *work)
drm_helper_hpd_irq_event(dev);
}
/**
* radeon_irq_reset_work_func - execute gpu reset
*
* @work: work struct
*
* Execute scheduled gpu reset (cayman+).
* This function is called when the irq handler
* thinks we need a gpu reset.
*/
static void radeon_irq_reset_work_func(struct work_struct *work)
{
struct radeon_device *rdev = container_of(work, struct radeon_device,
reset_work);
radeon_gpu_reset(rdev);
}
/**
* radeon_driver_irq_preinstall_kms - drm irq preinstall callback
*
@ -99,6 +116,7 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
/* Disable *all* interrupts */
for (i = 0; i < RADEON_NUM_RINGS; i++)
atomic_set(&rdev->irq.ring_int[i], 0);
rdev->irq.dpm_thermal = false;
for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
rdev->irq.hpd[i] = false;
for (i = 0; i < RADEON_MAX_CRTCS; i++) {
@ -146,6 +164,7 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
/* Disable *all* interrupts */
for (i = 0; i < RADEON_NUM_RINGS; i++)
atomic_set(&rdev->irq.ring_int[i], 0);
rdev->irq.dpm_thermal = false;
for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
rdev->irq.hpd[i] = false;
for (i = 0; i < RADEON_MAX_CRTCS; i++) {
@ -243,6 +262,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi);
INIT_WORK(&rdev->reset_work, radeon_irq_reset_work_func);
spin_lock_init(&rdev->irq.lock);
r = drm_vblank_init(rdev->ddev, rdev->num_crtc);

View File

@ -229,7 +229,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
*value = rdev->accel_working;
break;
case RADEON_INFO_TILING_CONFIG:
if (rdev->family >= CHIP_TAHITI)
if (rdev->family >= CHIP_BONAIRE)
*value = rdev->config.cik.tile_config;
else if (rdev->family >= CHIP_TAHITI)
*value = rdev->config.si.tile_config;
else if (rdev->family >= CHIP_CAYMAN)
*value = rdev->config.cayman.tile_config;
@ -281,7 +283,10 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
*value = rdev->clock.spll.reference_freq * 10;
break;
case RADEON_INFO_NUM_BACKENDS:
if (rdev->family >= CHIP_TAHITI)
if (rdev->family >= CHIP_BONAIRE)
*value = rdev->config.cik.max_backends_per_se *
rdev->config.cik.max_shader_engines;
else if (rdev->family >= CHIP_TAHITI)
*value = rdev->config.si.max_backends_per_se *
rdev->config.si.max_shader_engines;
else if (rdev->family >= CHIP_CAYMAN)
@ -298,7 +303,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
}
break;
case RADEON_INFO_NUM_TILE_PIPES:
if (rdev->family >= CHIP_TAHITI)
if (rdev->family >= CHIP_BONAIRE)
*value = rdev->config.cik.max_tile_pipes;
else if (rdev->family >= CHIP_TAHITI)
*value = rdev->config.si.max_tile_pipes;
else if (rdev->family >= CHIP_CAYMAN)
*value = rdev->config.cayman.max_tile_pipes;
@ -316,7 +323,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
*value = 1;
break;
case RADEON_INFO_BACKEND_MAP:
if (rdev->family >= CHIP_TAHITI)
if (rdev->family >= CHIP_BONAIRE)
return -EINVAL;
else if (rdev->family >= CHIP_TAHITI)
*value = rdev->config.si.backend_map;
else if (rdev->family >= CHIP_CAYMAN)
*value = rdev->config.cayman.backend_map;
@ -343,7 +352,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
*value = RADEON_IB_VM_MAX_SIZE;
break;
case RADEON_INFO_MAX_PIPES:
if (rdev->family >= CHIP_TAHITI)
if (rdev->family >= CHIP_BONAIRE)
*value = rdev->config.cik.max_cu_per_sh;
else if (rdev->family >= CHIP_TAHITI)
*value = rdev->config.si.max_cu_per_sh;
else if (rdev->family >= CHIP_CAYMAN)
*value = rdev->config.cayman.max_pipes_per_simd;
@ -367,7 +378,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
value64 = radeon_get_gpu_clock_counter(rdev);
break;
case RADEON_INFO_MAX_SE:
if (rdev->family >= CHIP_TAHITI)
if (rdev->family >= CHIP_BONAIRE)
*value = rdev->config.cik.max_shader_engines;
else if (rdev->family >= CHIP_TAHITI)
*value = rdev->config.si.max_shader_engines;
else if (rdev->family >= CHIP_CAYMAN)
*value = rdev->config.cayman.max_shader_engines;
@ -377,7 +390,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
*value = 1;
break;
case RADEON_INFO_MAX_SH_PER_SE:
if (rdev->family >= CHIP_TAHITI)
if (rdev->family >= CHIP_BONAIRE)
*value = rdev->config.cik.max_sh_per_se;
else if (rdev->family >= CHIP_TAHITI)
*value = rdev->config.si.max_sh_per_se;
else
return -EINVAL;
@ -407,12 +422,16 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
}
break;
case RADEON_INFO_SI_TILE_MODE_ARRAY:
if (rdev->family < CHIP_TAHITI) {
DRM_DEBUG_KMS("tile mode array is si only!\n");
if (rdev->family >= CHIP_BONAIRE) {
value = rdev->config.cik.tile_mode_array;
value_size = sizeof(uint32_t)*32;
} else if (rdev->family >= CHIP_TAHITI) {
value = rdev->config.si.tile_mode_array;
value_size = sizeof(uint32_t)*32;
} else {
DRM_DEBUG_KMS("tile mode array is si+ only!\n");
return -EINVAL;
}
value = rdev->config.si.tile_mode_array;
value_size = sizeof(uint32_t)*32;
break;
default:
DRM_DEBUG_KMS("Invalid request %d\n", info->request);

View File

@ -307,6 +307,8 @@ struct radeon_crtc {
uint64_t cursor_addr;
int cursor_width;
int cursor_height;
int max_cursor_width;
int max_cursor_height;
uint32_t legacy_display_base_addr;
uint32_t legacy_cursor_offset;
enum radeon_rmx_type rmx_type;
@ -329,6 +331,10 @@ struct radeon_crtc {
u32 pll_flags;
struct drm_encoder *encoder;
struct drm_connector *connector;
/* for dpm */
u32 line_time;
u32 wm_low;
u32 wm_high;
};
struct radeon_encoder_primary_dac {
@ -512,12 +518,99 @@ struct atom_clock_dividers {
bool enable_dithen;
u32 vco_mode;
u32 real_clock;
/* added for CI */
u32 post_divider;
u32 flags;
};
struct atom_mpll_param {
union {
struct {
#ifdef __BIG_ENDIAN
u32 reserved : 8;
u32 clkfrac : 12;
u32 clkf : 12;
#else
u32 clkf : 12;
u32 clkfrac : 12;
u32 reserved : 8;
#endif
};
u32 fb_div;
};
u32 post_div;
u32 bwcntl;
u32 dll_speed;
u32 vco_mode;
u32 yclk_sel;
u32 qdr;
u32 half_rate;
};
#define MEM_TYPE_GDDR5 0x50
#define MEM_TYPE_GDDR4 0x40
#define MEM_TYPE_GDDR3 0x30
#define MEM_TYPE_DDR2 0x20
#define MEM_TYPE_GDDR1 0x10
#define MEM_TYPE_DDR3 0xb0
#define MEM_TYPE_MASK 0xf0
struct atom_memory_info {
u8 mem_vendor;
u8 mem_type;
};
#define MAX_AC_TIMING_ENTRIES 16
struct atom_memory_clock_range_table
{
u8 num_entries;
u8 rsv[3];
u32 mclk[MAX_AC_TIMING_ENTRIES];
};
#define VBIOS_MC_REGISTER_ARRAY_SIZE 32
#define VBIOS_MAX_AC_TIMING_ENTRIES 20
struct atom_mc_reg_entry {
u32 mclk_max;
u32 mc_data[VBIOS_MC_REGISTER_ARRAY_SIZE];
};
struct atom_mc_register_address {
u16 s1;
u8 pre_reg_data;
};
struct atom_mc_reg_table {
u8 last;
u8 num_entries;
struct atom_mc_reg_entry mc_reg_table_entry[VBIOS_MAX_AC_TIMING_ENTRIES];
struct atom_mc_register_address mc_reg_address[VBIOS_MC_REGISTER_ARRAY_SIZE];
};
#define MAX_VOLTAGE_ENTRIES 32
struct atom_voltage_table_entry
{
u16 value;
u32 smio_low;
};
struct atom_voltage_table
{
u32 count;
u32 mask_low;
u32 phase_delay;
struct atom_voltage_table_entry entries[MAX_VOLTAGE_ENTRIES];
};
extern enum radeon_tv_std
radeon_combios_get_tv_info(struct radeon_device *rdev);
extern enum radeon_tv_std
radeon_atombios_get_tv_info(struct radeon_device *rdev);
extern void radeon_atombios_get_default_voltages(struct radeon_device *rdev,
u16 *vddc, u16 *vddci, u16 *mvdd);
extern struct drm_connector *
radeon_get_connector_for_encoder(struct drm_encoder *encoder);

View File

@ -388,7 +388,8 @@ static ssize_t radeon_get_pm_method(struct device *dev,
int pm = rdev->pm.pm_method;
return snprintf(buf, PAGE_SIZE, "%s\n",
(pm == PM_METHOD_DYNPM) ? "dynpm" : "profile");
(pm == PM_METHOD_DYNPM) ? "dynpm" :
(pm == PM_METHOD_PROFILE) ? "profile" : "dpm");
}
static ssize_t radeon_set_pm_method(struct device *dev,
@ -399,6 +400,11 @@ static ssize_t radeon_set_pm_method(struct device *dev,
struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
struct radeon_device *rdev = ddev->dev_private;
/* we don't support the legacy modes with dpm */
if (rdev->pm.pm_method == PM_METHOD_DPM) {
count = -EINVAL;
goto fail;
}
if (strncmp("dynpm", buf, strlen("dynpm")) == 0) {
mutex_lock(&rdev->pm.mutex);
@ -423,8 +429,48 @@ fail:
return count;
}
static ssize_t radeon_get_dpm_state(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
struct radeon_device *rdev = ddev->dev_private;
enum radeon_pm_state_type pm = rdev->pm.dpm.user_state;
return snprintf(buf, PAGE_SIZE, "%s\n",
(pm == POWER_STATE_TYPE_BATTERY) ? "battery" :
(pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance");
}
static ssize_t radeon_set_dpm_state(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
struct radeon_device *rdev = ddev->dev_private;
mutex_lock(&rdev->pm.mutex);
if (strncmp("battery", buf, strlen("battery")) == 0)
rdev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY;
else if (strncmp("balanced", buf, strlen("balanced")) == 0)
rdev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED;
else if (strncmp("performance", buf, strlen("performance")) == 0)
rdev->pm.dpm.user_state = POWER_STATE_TYPE_PERFORMANCE;
else {
mutex_unlock(&rdev->pm.mutex);
count = -EINVAL;
goto fail;
}
mutex_unlock(&rdev->pm.mutex);
radeon_pm_compute_clocks(rdev);
fail:
return count;
}
static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile);
static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method);
static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, radeon_get_dpm_state, radeon_set_dpm_state);
static ssize_t radeon_hwmon_show_temp(struct device *dev,
struct device_attribute *attr,
@ -434,27 +480,10 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev,
struct radeon_device *rdev = ddev->dev_private;
int temp;
switch (rdev->pm.int_thermal_type) {
case THERMAL_TYPE_RV6XX:
temp = rv6xx_get_temp(rdev);
break;
case THERMAL_TYPE_RV770:
temp = rv770_get_temp(rdev);
break;
case THERMAL_TYPE_EVERGREEN:
case THERMAL_TYPE_NI:
temp = evergreen_get_temp(rdev);
break;
case THERMAL_TYPE_SUMO:
temp = sumo_get_temp(rdev);
break;
case THERMAL_TYPE_SI:
temp = si_get_temp(rdev);
break;
default:
if (rdev->asic->pm.get_temperature)
temp = radeon_get_temperature(rdev);
else
temp = 0;
break;
}
return snprintf(buf, PAGE_SIZE, "%d\n", temp);
}
@ -492,8 +521,7 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
case THERMAL_TYPE_NI:
case THERMAL_TYPE_SUMO:
case THERMAL_TYPE_SI:
/* No support for TN yet */
if (rdev->family == CHIP_ARUBA)
if (rdev->asic->pm.get_temperature == NULL)
return err;
rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev);
if (IS_ERR(rdev->pm.int_hwmon_dev)) {
@ -526,7 +554,270 @@ static void radeon_hwmon_fini(struct radeon_device *rdev)
}
}
void radeon_pm_suspend(struct radeon_device *rdev)
static void radeon_dpm_thermal_work_handler(struct work_struct *work)
{
struct radeon_device *rdev =
container_of(work, struct radeon_device,
pm.dpm.thermal.work);
/* switch to the thermal state */
enum radeon_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL;
if (!rdev->pm.dpm_enabled)
return;
if (rdev->asic->pm.get_temperature) {
int temp = radeon_get_temperature(rdev);
if (temp < rdev->pm.dpm.thermal.min_temp)
/* switch back the user state */
dpm_state = rdev->pm.dpm.user_state;
} else {
if (rdev->pm.dpm.thermal.high_to_low)
/* switch back the user state */
dpm_state = rdev->pm.dpm.user_state;
}
radeon_dpm_enable_power_state(rdev, dpm_state);
}
static struct radeon_ps *radeon_dpm_pick_power_state(struct radeon_device *rdev,
enum radeon_pm_state_type dpm_state)
{
int i;
struct radeon_ps *ps;
u32 ui_class;
restart_search:
/* balanced states don't exist at the moment */
if (dpm_state == POWER_STATE_TYPE_BALANCED)
dpm_state = POWER_STATE_TYPE_PERFORMANCE;
/* Pick the best power state based on current conditions */
for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
ps = &rdev->pm.dpm.ps[i];
ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK;
switch (dpm_state) {
/* user states */
case POWER_STATE_TYPE_BATTERY:
if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) {
if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) {
if (rdev->pm.dpm.new_active_crtc_count < 2)
return ps;
} else
return ps;
}
break;
case POWER_STATE_TYPE_BALANCED:
if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) {
if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) {
if (rdev->pm.dpm.new_active_crtc_count < 2)
return ps;
} else
return ps;
}
break;
case POWER_STATE_TYPE_PERFORMANCE:
if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) {
if (rdev->pm.dpm.new_active_crtc_count < 2)
return ps;
} else
return ps;
}
break;
/* internal states */
case POWER_STATE_TYPE_INTERNAL_UVD:
return rdev->pm.dpm.uvd_ps;
case POWER_STATE_TYPE_INTERNAL_UVD_SD:
if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
return ps;
break;
case POWER_STATE_TYPE_INTERNAL_UVD_HD:
if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
return ps;
break;
case POWER_STATE_TYPE_INTERNAL_UVD_HD2:
if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
return ps;
break;
case POWER_STATE_TYPE_INTERNAL_UVD_MVC:
if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
return ps;
break;
case POWER_STATE_TYPE_INTERNAL_BOOT:
return rdev->pm.dpm.boot_ps;
case POWER_STATE_TYPE_INTERNAL_THERMAL:
if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
return ps;
break;
case POWER_STATE_TYPE_INTERNAL_ACPI:
if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI)
return ps;
break;
case POWER_STATE_TYPE_INTERNAL_ULV:
if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
return ps;
break;
default:
break;
}
}
/* use a fallback state if we didn't match */
switch (dpm_state) {
case POWER_STATE_TYPE_INTERNAL_UVD_SD:
case POWER_STATE_TYPE_INTERNAL_UVD_HD:
case POWER_STATE_TYPE_INTERNAL_UVD_HD2:
case POWER_STATE_TYPE_INTERNAL_UVD_MVC:
return rdev->pm.dpm.uvd_ps;
case POWER_STATE_TYPE_INTERNAL_THERMAL:
dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI;
goto restart_search;
case POWER_STATE_TYPE_INTERNAL_ACPI:
dpm_state = POWER_STATE_TYPE_BATTERY;
goto restart_search;
case POWER_STATE_TYPE_BATTERY:
dpm_state = POWER_STATE_TYPE_PERFORMANCE;
goto restart_search;
default:
break;
}
return NULL;
}
static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
{
int i;
struct radeon_ps *ps;
enum radeon_pm_state_type dpm_state;
int ret;
/* if dpm init failed */
if (!rdev->pm.dpm_enabled)
return;
if (rdev->pm.dpm.user_state != rdev->pm.dpm.state) {
/* add other state override checks here */
if ((!rdev->pm.dpm.thermal_active) &&
(!rdev->pm.dpm.uvd_active))
rdev->pm.dpm.state = rdev->pm.dpm.user_state;
}
dpm_state = rdev->pm.dpm.state;
ps = radeon_dpm_pick_power_state(rdev, dpm_state);
if (ps)
rdev->pm.dpm.requested_ps = ps;
else
return;
/* no need to reprogram if nothing changed unless we are on BTC+ */
if (rdev->pm.dpm.current_ps == rdev->pm.dpm.requested_ps) {
if ((rdev->family < CHIP_BARTS) || (rdev->flags & RADEON_IS_IGP)) {
/* for pre-BTC and APUs if the num crtcs changed but state is the same,
* all we need to do is update the display configuration.
*/
if (rdev->pm.dpm.new_active_crtcs != rdev->pm.dpm.current_active_crtcs) {
/* update display watermarks based on new power state */
radeon_bandwidth_update(rdev);
/* update displays */
radeon_dpm_display_configuration_changed(rdev);
rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
}
return;
} else {
/* for BTC+ if the num crtcs hasn't changed and state is the same,
* nothing to do, if the num crtcs is > 1 and state is the same,
* update display configuration.
*/
if (rdev->pm.dpm.new_active_crtcs ==
rdev->pm.dpm.current_active_crtcs) {
return;
} else {
if ((rdev->pm.dpm.current_active_crtc_count > 1) &&
(rdev->pm.dpm.new_active_crtc_count > 1)) {
/* update display watermarks based on new power state */
radeon_bandwidth_update(rdev);
/* update displays */
radeon_dpm_display_configuration_changed(rdev);
rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
return;
}
}
}
}
printk("switching from power state:\n");
radeon_dpm_print_power_state(rdev, rdev->pm.dpm.current_ps);
printk("switching to power state:\n");
radeon_dpm_print_power_state(rdev, rdev->pm.dpm.requested_ps);
mutex_lock(&rdev->ddev->struct_mutex);
down_write(&rdev->pm.mclk_lock);
mutex_lock(&rdev->ring_lock);
ret = radeon_dpm_pre_set_power_state(rdev);
if (ret)
goto done;
/* update display watermarks based on new power state */
radeon_bandwidth_update(rdev);
/* update displays */
radeon_dpm_display_configuration_changed(rdev);
rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
/* wait for the rings to drain */
for (i = 0; i < RADEON_NUM_RINGS; i++) {
struct radeon_ring *ring = &rdev->ring[i];
if (ring->ready)
radeon_fence_wait_empty_locked(rdev, i);
}
/* program the new power state */
radeon_dpm_set_power_state(rdev);
/* update current power state */
rdev->pm.dpm.current_ps = rdev->pm.dpm.requested_ps;
radeon_dpm_post_set_power_state(rdev);
done:
mutex_unlock(&rdev->ring_lock);
up_write(&rdev->pm.mclk_lock);
mutex_unlock(&rdev->ddev->struct_mutex);
}
void radeon_dpm_enable_power_state(struct radeon_device *rdev,
enum radeon_pm_state_type dpm_state)
{
if (!rdev->pm.dpm_enabled)
return;
mutex_lock(&rdev->pm.mutex);
switch (dpm_state) {
case POWER_STATE_TYPE_INTERNAL_THERMAL:
rdev->pm.dpm.thermal_active = true;
break;
case POWER_STATE_TYPE_INTERNAL_UVD:
case POWER_STATE_TYPE_INTERNAL_UVD_SD:
case POWER_STATE_TYPE_INTERNAL_UVD_HD:
case POWER_STATE_TYPE_INTERNAL_UVD_HD2:
case POWER_STATE_TYPE_INTERNAL_UVD_MVC:
rdev->pm.dpm.uvd_active = true;
break;
default:
rdev->pm.dpm.thermal_active = false;
rdev->pm.dpm.uvd_active = false;
break;
}
rdev->pm.dpm.state = dpm_state;
mutex_unlock(&rdev->pm.mutex);
radeon_pm_compute_clocks(rdev);
}
static void radeon_pm_suspend_old(struct radeon_device *rdev)
{
mutex_lock(&rdev->pm.mutex);
if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
@ -538,7 +829,26 @@ void radeon_pm_suspend(struct radeon_device *rdev)
cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
}
void radeon_pm_resume(struct radeon_device *rdev)
static void radeon_pm_suspend_dpm(struct radeon_device *rdev)
{
mutex_lock(&rdev->pm.mutex);
/* disable dpm */
radeon_dpm_disable(rdev);
/* reset the power state */
rdev->pm.dpm.current_ps = rdev->pm.dpm.requested_ps = rdev->pm.dpm.boot_ps;
rdev->pm.dpm_enabled = false;
mutex_unlock(&rdev->pm.mutex);
}
void radeon_pm_suspend(struct radeon_device *rdev)
{
if (rdev->pm.pm_method == PM_METHOD_DPM)
radeon_pm_suspend_dpm(rdev);
else
radeon_pm_suspend_old(rdev);
}
static void radeon_pm_resume_old(struct radeon_device *rdev)
{
/* set up the default clocks if the MC ucode is loaded */
if ((rdev->family >= CHIP_BARTS) &&
@ -573,12 +883,50 @@ void radeon_pm_resume(struct radeon_device *rdev)
radeon_pm_compute_clocks(rdev);
}
int radeon_pm_init(struct radeon_device *rdev)
static void radeon_pm_resume_dpm(struct radeon_device *rdev)
{
int ret;
/* asic init will reset to the boot state */
mutex_lock(&rdev->pm.mutex);
rdev->pm.dpm.current_ps = rdev->pm.dpm.requested_ps = rdev->pm.dpm.boot_ps;
radeon_dpm_setup_asic(rdev);
ret = radeon_dpm_enable(rdev);
mutex_unlock(&rdev->pm.mutex);
if (ret) {
DRM_ERROR("radeon: dpm resume failed\n");
if ((rdev->family >= CHIP_BARTS) &&
(rdev->family <= CHIP_CAYMAN) &&
rdev->mc_fw) {
if (rdev->pm.default_vddc)
radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
SET_VOLTAGE_TYPE_ASIC_VDDC);
if (rdev->pm.default_vddci)
radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
SET_VOLTAGE_TYPE_ASIC_VDDCI);
if (rdev->pm.default_sclk)
radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
if (rdev->pm.default_mclk)
radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
}
} else {
rdev->pm.dpm_enabled = true;
radeon_pm_compute_clocks(rdev);
}
}
void radeon_pm_resume(struct radeon_device *rdev)
{
if (rdev->pm.pm_method == PM_METHOD_DPM)
radeon_pm_resume_dpm(rdev);
else
radeon_pm_resume_old(rdev);
}
static int radeon_pm_init_old(struct radeon_device *rdev)
{
int ret;
/* default to profile method */
rdev->pm.pm_method = PM_METHOD_PROFILE;
rdev->pm.profile = PM_PROFILE_DEFAULT;
rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
@ -640,7 +988,137 @@ int radeon_pm_init(struct radeon_device *rdev)
return 0;
}
void radeon_pm_fini(struct radeon_device *rdev)
static void radeon_dpm_print_power_states(struct radeon_device *rdev)
{
int i;
for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
printk("== power state %d ==\n", i);
radeon_dpm_print_power_state(rdev, &rdev->pm.dpm.ps[i]);
}
}
static int radeon_pm_init_dpm(struct radeon_device *rdev)
{
int ret;
/* default to performance state */
rdev->pm.dpm.state = POWER_STATE_TYPE_PERFORMANCE;
rdev->pm.dpm.user_state = POWER_STATE_TYPE_PERFORMANCE;
rdev->pm.default_sclk = rdev->clock.default_sclk;
rdev->pm.default_mclk = rdev->clock.default_mclk;
rdev->pm.current_sclk = rdev->clock.default_sclk;
rdev->pm.current_mclk = rdev->clock.default_mclk;
rdev->pm.int_thermal_type = THERMAL_TYPE_NONE;
if (rdev->bios && rdev->is_atom_bios)
radeon_atombios_get_power_modes(rdev);
else
return -EINVAL;
/* set up the internal thermal sensor if applicable */
ret = radeon_hwmon_init(rdev);
if (ret)
return ret;
INIT_WORK(&rdev->pm.dpm.thermal.work, radeon_dpm_thermal_work_handler);
mutex_lock(&rdev->pm.mutex);
radeon_dpm_init(rdev);
rdev->pm.dpm.current_ps = rdev->pm.dpm.requested_ps = rdev->pm.dpm.boot_ps;
radeon_dpm_print_power_states(rdev);
radeon_dpm_setup_asic(rdev);
ret = radeon_dpm_enable(rdev);
mutex_unlock(&rdev->pm.mutex);
if (ret) {
rdev->pm.dpm_enabled = false;
if ((rdev->family >= CHIP_BARTS) &&
(rdev->family <= CHIP_CAYMAN) &&
rdev->mc_fw) {
if (rdev->pm.default_vddc)
radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
SET_VOLTAGE_TYPE_ASIC_VDDC);
if (rdev->pm.default_vddci)
radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
SET_VOLTAGE_TYPE_ASIC_VDDCI);
if (rdev->pm.default_sclk)
radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
if (rdev->pm.default_mclk)
radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
}
DRM_ERROR("radeon: dpm initialization failed\n");
return ret;
}
rdev->pm.dpm_enabled = true;
radeon_pm_compute_clocks(rdev);
if (rdev->pm.num_power_states > 1) {
ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
if (ret)
DRM_ERROR("failed to create device file for dpm state\n");
/* XXX: these are noops for dpm but are here for backwards compat */
ret = device_create_file(rdev->dev, &dev_attr_power_profile);
if (ret)
DRM_ERROR("failed to create device file for power profile\n");
ret = device_create_file(rdev->dev, &dev_attr_power_method);
if (ret)
DRM_ERROR("failed to create device file for power method\n");
DRM_INFO("radeon: dpm initialized\n");
}
return 0;
}
int radeon_pm_init(struct radeon_device *rdev)
{
/* enable dpm on rv6xx+ */
switch (rdev->family) {
case CHIP_RV610:
case CHIP_RV630:
case CHIP_RV620:
case CHIP_RV635:
case CHIP_RV670:
case CHIP_RS780:
case CHIP_RS880:
case CHIP_RV770:
case CHIP_RV730:
case CHIP_RV710:
case CHIP_RV740:
case CHIP_CEDAR:
case CHIP_REDWOOD:
case CHIP_JUNIPER:
case CHIP_CYPRESS:
case CHIP_HEMLOCK:
case CHIP_PALM:
case CHIP_SUMO:
case CHIP_SUMO2:
case CHIP_BARTS:
case CHIP_TURKS:
case CHIP_CAICOS:
case CHIP_CAYMAN:
case CHIP_ARUBA:
case CHIP_TAHITI:
case CHIP_PITCAIRN:
case CHIP_VERDE:
case CHIP_OLAND:
case CHIP_HAINAN:
if (radeon_dpm == 1)
rdev->pm.pm_method = PM_METHOD_DPM;
else
rdev->pm.pm_method = PM_METHOD_PROFILE;
break;
default:
/* default to profile method */
rdev->pm.pm_method = PM_METHOD_PROFILE;
break;
}
if (rdev->pm.pm_method == PM_METHOD_DPM)
return radeon_pm_init_dpm(rdev);
else
return radeon_pm_init_old(rdev);
}
static void radeon_pm_fini_old(struct radeon_device *rdev)
{
if (rdev->pm.num_power_states > 1) {
mutex_lock(&rdev->pm.mutex);
@ -668,7 +1146,35 @@ void radeon_pm_fini(struct radeon_device *rdev)
radeon_hwmon_fini(rdev);
}
void radeon_pm_compute_clocks(struct radeon_device *rdev)
static void radeon_pm_fini_dpm(struct radeon_device *rdev)
{
if (rdev->pm.num_power_states > 1) {
mutex_lock(&rdev->pm.mutex);
radeon_dpm_disable(rdev);
mutex_unlock(&rdev->pm.mutex);
device_remove_file(rdev->dev, &dev_attr_power_dpm_state);
/* XXX backwards compat */
device_remove_file(rdev->dev, &dev_attr_power_profile);
device_remove_file(rdev->dev, &dev_attr_power_method);
}
radeon_dpm_fini(rdev);
if (rdev->pm.power_state)
kfree(rdev->pm.power_state);
radeon_hwmon_fini(rdev);
}
void radeon_pm_fini(struct radeon_device *rdev)
{
if (rdev->pm.pm_method == PM_METHOD_DPM)
radeon_pm_fini_dpm(rdev);
else
radeon_pm_fini_old(rdev);
}
static void radeon_pm_compute_clocks_old(struct radeon_device *rdev)
{
struct drm_device *ddev = rdev->ddev;
struct drm_crtc *crtc;
@ -677,6 +1183,7 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
if (rdev->pm.num_power_states < 2)
return;
INIT_WORK(&rdev->pm.dpm.thermal.work, radeon_dpm_thermal_work_handler);
mutex_lock(&rdev->pm.mutex);
rdev->pm.active_crtcs = 0;
@ -739,6 +1246,46 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
mutex_unlock(&rdev->pm.mutex);
}
static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
{
struct drm_device *ddev = rdev->ddev;
struct drm_crtc *crtc;
struct radeon_crtc *radeon_crtc;
mutex_lock(&rdev->pm.mutex);
/* update active crtc counts */
rdev->pm.dpm.new_active_crtcs = 0;
rdev->pm.dpm.new_active_crtc_count = 0;
list_for_each_entry(crtc,
&ddev->mode_config.crtc_list, head) {
radeon_crtc = to_radeon_crtc(crtc);
if (crtc->enabled) {
rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id);
rdev->pm.dpm.new_active_crtc_count++;
}
}
/* update battery/ac status */
if (power_supply_is_system_supplied() > 0)
rdev->pm.dpm.ac_power = true;
else
rdev->pm.dpm.ac_power = false;
radeon_dpm_change_power_state_locked(rdev);
mutex_unlock(&rdev->pm.mutex);
}
void radeon_pm_compute_clocks(struct radeon_device *rdev)
{
if (rdev->pm.pm_method == PM_METHOD_DPM)
radeon_pm_compute_clocks_dpm(rdev);
else
radeon_pm_compute_clocks_old(rdev);
}
static bool radeon_pm_in_vbl(struct radeon_device *rdev)
{
int crtc, vpos, hpos, vbl_status;

View File

@ -57,6 +57,7 @@
#include "evergreen_reg.h"
#include "ni_reg.h"
#include "si_reg.h"
#include "cik_reg.h"
#define RADEON_MC_AGP_LOCATION 0x014c
#define RADEON_MC_AGP_START_MASK 0x0000FFFF

View File

@ -357,6 +357,38 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev,
}
}
u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev,
struct radeon_ring *ring)
{
u32 rptr;
if (rdev->wb.enabled && ring != &rdev->ring[R600_RING_TYPE_UVD_INDEX])
rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
else
rptr = RREG32(ring->rptr_reg);
rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift;
return rptr;
}
u32 radeon_ring_generic_get_wptr(struct radeon_device *rdev,
struct radeon_ring *ring)
{
u32 wptr;
wptr = RREG32(ring->wptr_reg);
wptr = (wptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift;
return wptr;
}
void radeon_ring_generic_set_wptr(struct radeon_device *rdev,
struct radeon_ring *ring)
{
WREG32(ring->wptr_reg, (ring->wptr << ring->ptr_reg_shift) & ring->ptr_reg_mask);
(void)RREG32(ring->wptr_reg);
}
/**
* radeon_ring_free_size - update the free size
*
@ -367,13 +399,7 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev,
*/
void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring)
{
u32 rptr;
if (rdev->wb.enabled && ring != &rdev->ring[R600_RING_TYPE_UVD_INDEX])
rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
else
rptr = RREG32(ring->rptr_reg);
ring->rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift;
ring->rptr = radeon_ring_get_rptr(rdev, ring);
/* This works because ring_size is a power of 2 */
ring->ring_free_dw = (ring->rptr + (ring->ring_size / 4));
ring->ring_free_dw -= ring->wptr;
@ -465,8 +491,7 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring)
radeon_ring_write(ring, ring->nop);
}
DRM_MEMORYBARRIER();
WREG32(ring->wptr_reg, (ring->wptr << ring->ptr_reg_shift) & ring->ptr_reg_mask);
(void)RREG32(ring->wptr_reg);
radeon_ring_set_wptr(rdev, ring);
}
/**
@ -568,7 +593,6 @@ void radeon_ring_lockup_update(struct radeon_ring *ring)
bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
{
unsigned long cjiffies, elapsed;
uint32_t rptr;
cjiffies = jiffies;
if (!time_after(cjiffies, ring->last_activity)) {
@ -576,8 +600,7 @@ bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *rin
radeon_ring_lockup_update(ring);
return false;
}
rptr = RREG32(ring->rptr_reg);
ring->rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift;
ring->rptr = radeon_ring_get_rptr(rdev, ring);
if (ring->rptr != ring->last_rptr) {
/* CP is still working no lockup */
radeon_ring_lockup_update(ring);
@ -804,9 +827,9 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
radeon_ring_free_size(rdev, ring);
count = (ring->ring_size / 4) - ring->ring_free_dw;
tmp = RREG32(ring->wptr_reg) >> ring->ptr_reg_shift;
tmp = radeon_ring_get_wptr(rdev, ring);
seq_printf(m, "wptr(0x%04x): 0x%08x [%5d]\n", ring->wptr_reg, tmp, tmp);
tmp = RREG32(ring->rptr_reg) >> ring->ptr_reg_shift;
tmp = radeon_ring_get_rptr(rdev, ring);
seq_printf(m, "rptr(0x%04x): 0x%08x [%5d]\n", ring->rptr_reg, tmp, tmp);
if (ring->rptr_save_reg) {
seq_printf(m, "rptr next(0x%04x): 0x%08x\n", ring->rptr_save_reg,

View File

@ -0,0 +1,129 @@
/*
* Copyright 2012 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.
*
*/
#ifndef __RADEON_UCODE_H__
#define __RADEON_UCODE_H__
/* CP */
#define R600_PFP_UCODE_SIZE 576
#define R600_PM4_UCODE_SIZE 1792
#define R700_PFP_UCODE_SIZE 848
#define R700_PM4_UCODE_SIZE 1360
#define EVERGREEN_PFP_UCODE_SIZE 1120
#define EVERGREEN_PM4_UCODE_SIZE 1376
#define CAYMAN_PFP_UCODE_SIZE 2176
#define CAYMAN_PM4_UCODE_SIZE 2176
#define SI_PFP_UCODE_SIZE 2144
#define SI_PM4_UCODE_SIZE 2144
#define SI_CE_UCODE_SIZE 2144
/* RLC */
#define R600_RLC_UCODE_SIZE 768
#define R700_RLC_UCODE_SIZE 1024
#define EVERGREEN_RLC_UCODE_SIZE 768
#define CAYMAN_RLC_UCODE_SIZE 1024
#define ARUBA_RLC_UCODE_SIZE 1536
#define SI_RLC_UCODE_SIZE 2048
/* MC */
#define BTC_MC_UCODE_SIZE 6024
#define CAYMAN_MC_UCODE_SIZE 6037
#define SI_MC_UCODE_SIZE 7769
#define OLAND_MC_UCODE_SIZE 7863
/* SMC */
#define RV770_SMC_UCODE_START 0x0100
#define RV770_SMC_UCODE_SIZE 0x410d
#define RV770_SMC_INT_VECTOR_START 0xffc0
#define RV770_SMC_INT_VECTOR_SIZE 0x0040
#define RV730_SMC_UCODE_START 0x0100
#define RV730_SMC_UCODE_SIZE 0x412c
#define RV730_SMC_INT_VECTOR_START 0xffc0
#define RV730_SMC_INT_VECTOR_SIZE 0x0040
#define RV710_SMC_UCODE_START 0x0100
#define RV710_SMC_UCODE_SIZE 0x3f1f
#define RV710_SMC_INT_VECTOR_START 0xffc0
#define RV710_SMC_INT_VECTOR_SIZE 0x0040
#define RV740_SMC_UCODE_START 0x0100
#define RV740_SMC_UCODE_SIZE 0x41c5
#define RV740_SMC_INT_VECTOR_START 0xffc0
#define RV740_SMC_INT_VECTOR_SIZE 0x0040
#define CEDAR_SMC_UCODE_START 0x0100
#define CEDAR_SMC_UCODE_SIZE 0x5d50
#define CEDAR_SMC_INT_VECTOR_START 0xffc0
#define CEDAR_SMC_INT_VECTOR_SIZE 0x0040
#define REDWOOD_SMC_UCODE_START 0x0100
#define REDWOOD_SMC_UCODE_SIZE 0x5f0a
#define REDWOOD_SMC_INT_VECTOR_START 0xffc0
#define REDWOOD_SMC_INT_VECTOR_SIZE 0x0040
#define JUNIPER_SMC_UCODE_START 0x0100
#define JUNIPER_SMC_UCODE_SIZE 0x5f1f
#define JUNIPER_SMC_INT_VECTOR_START 0xffc0
#define JUNIPER_SMC_INT_VECTOR_SIZE 0x0040
#define CYPRESS_SMC_UCODE_START 0x0100
#define CYPRESS_SMC_UCODE_SIZE 0x61f7
#define CYPRESS_SMC_INT_VECTOR_START 0xffc0
#define CYPRESS_SMC_INT_VECTOR_SIZE 0x0040
#define BARTS_SMC_UCODE_START 0x0100
#define BARTS_SMC_UCODE_SIZE 0x6107
#define BARTS_SMC_INT_VECTOR_START 0xffc0
#define BARTS_SMC_INT_VECTOR_SIZE 0x0040
#define TURKS_SMC_UCODE_START 0x0100
#define TURKS_SMC_UCODE_SIZE 0x605b
#define TURKS_SMC_INT_VECTOR_START 0xffc0
#define TURKS_SMC_INT_VECTOR_SIZE 0x0040
#define CAICOS_SMC_UCODE_START 0x0100
#define CAICOS_SMC_UCODE_SIZE 0x5fbd
#define CAICOS_SMC_INT_VECTOR_START 0xffc0
#define CAICOS_SMC_INT_VECTOR_SIZE 0x0040
#define CAYMAN_SMC_UCODE_START 0x0100
#define CAYMAN_SMC_UCODE_SIZE 0x79ec
#define CAYMAN_SMC_INT_VECTOR_START 0xffc0
#define CAYMAN_SMC_INT_VECTOR_SIZE 0x0040
#define TAHITI_SMC_UCODE_START 0x10000
#define TAHITI_SMC_UCODE_SIZE 0xf458
#define PITCAIRN_SMC_UCODE_START 0x10000
#define PITCAIRN_SMC_UCODE_SIZE 0xe9f4
#define VERDE_SMC_UCODE_START 0x10000
#define VERDE_SMC_UCODE_SIZE 0xebe4
#define OLAND_SMC_UCODE_START 0x10000
#define OLAND_SMC_UCODE_SIZE 0xe7b4
#define HAINAN_SMC_UCODE_START 0x10000
#define HAINAN_SMC_UCODE_SIZE 0xe67C
#endif

View File

@ -44,11 +44,13 @@
#define FIRMWARE_CYPRESS "radeon/CYPRESS_uvd.bin"
#define FIRMWARE_SUMO "radeon/SUMO_uvd.bin"
#define FIRMWARE_TAHITI "radeon/TAHITI_uvd.bin"
#define FIRMWARE_BONAIRE "radeon/BONAIRE_uvd.bin"
MODULE_FIRMWARE(FIRMWARE_RV710);
MODULE_FIRMWARE(FIRMWARE_CYPRESS);
MODULE_FIRMWARE(FIRMWARE_SUMO);
MODULE_FIRMWARE(FIRMWARE_TAHITI);
MODULE_FIRMWARE(FIRMWARE_BONAIRE);
static void radeon_uvd_idle_work_handler(struct work_struct *work);
@ -100,6 +102,12 @@ int radeon_uvd_init(struct radeon_device *rdev)
fw_name = FIRMWARE_TAHITI;
break;
case CHIP_BONAIRE:
case CHIP_KABINI:
case CHIP_KAVERI:
fw_name = FIRMWARE_BONAIRE;
break;
default:
return -EINVAL;
}
@ -691,11 +699,19 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work)
struct radeon_device *rdev =
container_of(work, struct radeon_device, uvd.idle_work.work);
if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0)
radeon_set_uvd_clocks(rdev, 0, 0);
else
if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0) {
if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
mutex_lock(&rdev->pm.mutex);
rdev->pm.dpm.uvd_active = false;
mutex_unlock(&rdev->pm.mutex);
radeon_pm_compute_clocks(rdev);
} else {
radeon_set_uvd_clocks(rdev, 0, 0);
}
} else {
schedule_delayed_work(&rdev->uvd.idle_work,
msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS));
}
}
void radeon_uvd_note_usage(struct radeon_device *rdev)
@ -703,8 +719,14 @@ void radeon_uvd_note_usage(struct radeon_device *rdev)
bool set_clocks = !cancel_delayed_work_sync(&rdev->uvd.idle_work);
set_clocks &= schedule_delayed_work(&rdev->uvd.idle_work,
msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS));
if (set_clocks)
radeon_set_uvd_clocks(rdev, 53300, 40000);
if (set_clocks) {
if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
/* XXX pick SD/HD/MVC */
radeon_dpm_enable_power_state(rdev, POWER_STATE_TYPE_INTERNAL_UVD);
} else {
radeon_set_uvd_clocks(rdev, 53300, 40000);
}
}
}
static unsigned radeon_uvd_calc_upll_post_div(unsigned vco_freq,

View File

@ -248,13 +248,16 @@ struct rs690_watermark {
};
static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
struct radeon_crtc *crtc,
struct rs690_watermark *wm)
struct radeon_crtc *crtc,
struct rs690_watermark *wm,
bool low)
{
struct drm_display_mode *mode = &crtc->base.mode;
fixed20_12 a, b, c;
fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
fixed20_12 sclk, core_bandwidth, max_bandwidth;
u32 selected_sclk;
if (!crtc->base.enabled) {
/* FIXME: wouldn't it better to set priority mark to maximum */
@ -262,6 +265,21 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
return;
}
if (((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880)) &&
(rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled)
selected_sclk = radeon_dpm_get_sclk(rdev, low);
else
selected_sclk = rdev->pm.current_sclk;
/* sclk in Mhz */
a.full = dfixed_const(100);
sclk.full = dfixed_const(selected_sclk);
sclk.full = dfixed_div(sclk, a);
/* core_bandwidth = sclk(Mhz) * 16 */
a.full = dfixed_const(16);
core_bandwidth.full = dfixed_div(rdev->pm.sclk, a);
if (crtc->vsc.full > dfixed_const(2))
wm->num_line_pair.full = dfixed_const(2);
else
@ -322,36 +340,36 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
wm->active_time.full = dfixed_div(wm->active_time, a);
/* Maximun bandwidth is the minimun bandwidth of all component */
rdev->pm.max_bandwidth = rdev->pm.core_bandwidth;
max_bandwidth = core_bandwidth;
if (rdev->mc.igp_sideport_enabled) {
if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&
if (max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&
rdev->pm.sideport_bandwidth.full)
rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth;
max_bandwidth = rdev->pm.sideport_bandwidth;
read_delay_latency.full = dfixed_const(370 * 800 * 1000);
read_delay_latency.full = dfixed_div(read_delay_latency,
rdev->pm.igp_sideport_mclk);
} else {
if (rdev->pm.max_bandwidth.full > rdev->pm.k8_bandwidth.full &&
if (max_bandwidth.full > rdev->pm.k8_bandwidth.full &&
rdev->pm.k8_bandwidth.full)
rdev->pm.max_bandwidth = rdev->pm.k8_bandwidth;
if (rdev->pm.max_bandwidth.full > rdev->pm.ht_bandwidth.full &&
max_bandwidth = rdev->pm.k8_bandwidth;
if (max_bandwidth.full > rdev->pm.ht_bandwidth.full &&
rdev->pm.ht_bandwidth.full)
rdev->pm.max_bandwidth = rdev->pm.ht_bandwidth;
max_bandwidth = rdev->pm.ht_bandwidth;
read_delay_latency.full = dfixed_const(5000);
}
/* sclk = system clocks(ns) = 1000 / max_bandwidth / 16 */
a.full = dfixed_const(16);
rdev->pm.sclk.full = dfixed_mul(rdev->pm.max_bandwidth, a);
sclk.full = dfixed_mul(max_bandwidth, a);
a.full = dfixed_const(1000);
rdev->pm.sclk.full = dfixed_div(a, rdev->pm.sclk);
sclk.full = dfixed_div(a, sclk);
/* Determine chunk time
* ChunkTime = the time it takes the DCP to send one chunk of data
* to the LB which consists of pipeline delay and inter chunk gap
* sclk = system clock(ns)
*/
a.full = dfixed_const(256 * 13);
chunk_time.full = dfixed_mul(rdev->pm.sclk, a);
chunk_time.full = dfixed_mul(sclk, a);
a.full = dfixed_const(10);
chunk_time.full = dfixed_div(chunk_time, a);
@ -415,17 +433,147 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
}
}
static void rs690_compute_mode_priority(struct radeon_device *rdev,
struct rs690_watermark *wm0,
struct rs690_watermark *wm1,
struct drm_display_mode *mode0,
struct drm_display_mode *mode1,
u32 *d1mode_priority_a_cnt,
u32 *d2mode_priority_a_cnt)
{
fixed20_12 priority_mark02, priority_mark12, fill_rate;
fixed20_12 a, b;
*d1mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1);
*d2mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1);
if (mode0 && mode1) {
if (dfixed_trunc(wm0->dbpp) > 64)
a.full = dfixed_mul(wm0->dbpp, wm0->num_line_pair);
else
a.full = wm0->num_line_pair.full;
if (dfixed_trunc(wm1->dbpp) > 64)
b.full = dfixed_mul(wm1->dbpp, wm1->num_line_pair);
else
b.full = wm1->num_line_pair.full;
a.full += b.full;
fill_rate.full = dfixed_div(wm0->sclk, a);
if (wm0->consumption_rate.full > fill_rate.full) {
b.full = wm0->consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm0->active_time);
a.full = dfixed_mul(wm0->worst_case_latency,
wm0->consumption_rate);
a.full = a.full + b.full;
b.full = dfixed_const(16 * 1000);
priority_mark02.full = dfixed_div(a, b);
} else {
a.full = dfixed_mul(wm0->worst_case_latency,
wm0->consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark02.full = dfixed_div(a, b);
}
if (wm1->consumption_rate.full > fill_rate.full) {
b.full = wm1->consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm1->active_time);
a.full = dfixed_mul(wm1->worst_case_latency,
wm1->consumption_rate);
a.full = a.full + b.full;
b.full = dfixed_const(16 * 1000);
priority_mark12.full = dfixed_div(a, b);
} else {
a.full = dfixed_mul(wm1->worst_case_latency,
wm1->consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark12.full = dfixed_div(a, b);
}
if (wm0->priority_mark.full > priority_mark02.full)
priority_mark02.full = wm0->priority_mark.full;
if (dfixed_trunc(priority_mark02) < 0)
priority_mark02.full = 0;
if (wm0->priority_mark_max.full > priority_mark02.full)
priority_mark02.full = wm0->priority_mark_max.full;
if (wm1->priority_mark.full > priority_mark12.full)
priority_mark12.full = wm1->priority_mark.full;
if (dfixed_trunc(priority_mark12) < 0)
priority_mark12.full = 0;
if (wm1->priority_mark_max.full > priority_mark12.full)
priority_mark12.full = wm1->priority_mark_max.full;
*d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);
*d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);
if (rdev->disp_priority == 2) {
*d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1);
*d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1);
}
} else if (mode0) {
if (dfixed_trunc(wm0->dbpp) > 64)
a.full = dfixed_mul(wm0->dbpp, wm0->num_line_pair);
else
a.full = wm0->num_line_pair.full;
fill_rate.full = dfixed_div(wm0->sclk, a);
if (wm0->consumption_rate.full > fill_rate.full) {
b.full = wm0->consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm0->active_time);
a.full = dfixed_mul(wm0->worst_case_latency,
wm0->consumption_rate);
a.full = a.full + b.full;
b.full = dfixed_const(16 * 1000);
priority_mark02.full = dfixed_div(a, b);
} else {
a.full = dfixed_mul(wm0->worst_case_latency,
wm0->consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark02.full = dfixed_div(a, b);
}
if (wm0->priority_mark.full > priority_mark02.full)
priority_mark02.full = wm0->priority_mark.full;
if (dfixed_trunc(priority_mark02) < 0)
priority_mark02.full = 0;
if (wm0->priority_mark_max.full > priority_mark02.full)
priority_mark02.full = wm0->priority_mark_max.full;
*d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);
if (rdev->disp_priority == 2)
*d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1);
} else if (mode1) {
if (dfixed_trunc(wm1->dbpp) > 64)
a.full = dfixed_mul(wm1->dbpp, wm1->num_line_pair);
else
a.full = wm1->num_line_pair.full;
fill_rate.full = dfixed_div(wm1->sclk, a);
if (wm1->consumption_rate.full > fill_rate.full) {
b.full = wm1->consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm1->active_time);
a.full = dfixed_mul(wm1->worst_case_latency,
wm1->consumption_rate);
a.full = a.full + b.full;
b.full = dfixed_const(16 * 1000);
priority_mark12.full = dfixed_div(a, b);
} else {
a.full = dfixed_mul(wm1->worst_case_latency,
wm1->consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark12.full = dfixed_div(a, b);
}
if (wm1->priority_mark.full > priority_mark12.full)
priority_mark12.full = wm1->priority_mark.full;
if (dfixed_trunc(priority_mark12) < 0)
priority_mark12.full = 0;
if (wm1->priority_mark_max.full > priority_mark12.full)
priority_mark12.full = wm1->priority_mark_max.full;
*d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);
if (rdev->disp_priority == 2)
*d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1);
}
}
void rs690_bandwidth_update(struct radeon_device *rdev)
{
struct drm_display_mode *mode0 = NULL;
struct drm_display_mode *mode1 = NULL;
struct rs690_watermark wm0;
struct rs690_watermark wm1;
struct rs690_watermark wm0_high, wm0_low;
struct rs690_watermark wm1_high, wm1_low;
u32 tmp;
u32 d1mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1);
u32 d2mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1);
fixed20_12 priority_mark02, priority_mark12, fill_rate;
fixed20_12 a, b;
u32 d1mode_priority_a_cnt, d1mode_priority_b_cnt;
u32 d2mode_priority_a_cnt, d2mode_priority_b_cnt;
radeon_update_display_priority(rdev);
@ -456,134 +604,29 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
WREG32(R_006C9C_DCP_CONTROL, 2);
rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0);
rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1);
rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0_high, false);
rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1_high, false);
tmp = (wm0.lb_request_fifo_depth - 1);
tmp |= (wm1.lb_request_fifo_depth - 1) << 16;
rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0_low, true);
rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1_low, true);
tmp = (wm0_high.lb_request_fifo_depth - 1);
tmp |= (wm1_high.lb_request_fifo_depth - 1) << 16;
WREG32(R_006D58_LB_MAX_REQ_OUTSTANDING, tmp);
if (mode0 && mode1) {
if (dfixed_trunc(wm0.dbpp) > 64)
a.full = dfixed_mul(wm0.dbpp, wm0.num_line_pair);
else
a.full = wm0.num_line_pair.full;
if (dfixed_trunc(wm1.dbpp) > 64)
b.full = dfixed_mul(wm1.dbpp, wm1.num_line_pair);
else
b.full = wm1.num_line_pair.full;
a.full += b.full;
fill_rate.full = dfixed_div(wm0.sclk, a);
if (wm0.consumption_rate.full > fill_rate.full) {
b.full = wm0.consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm0.active_time);
a.full = dfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
a.full = a.full + b.full;
b.full = dfixed_const(16 * 1000);
priority_mark02.full = dfixed_div(a, b);
} else {
a.full = dfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark02.full = dfixed_div(a, b);
}
if (wm1.consumption_rate.full > fill_rate.full) {
b.full = wm1.consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm1.active_time);
a.full = dfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
a.full = a.full + b.full;
b.full = dfixed_const(16 * 1000);
priority_mark12.full = dfixed_div(a, b);
} else {
a.full = dfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark12.full = dfixed_div(a, b);
}
if (wm0.priority_mark.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark.full;
if (dfixed_trunc(priority_mark02) < 0)
priority_mark02.full = 0;
if (wm0.priority_mark_max.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark_max.full;
if (wm1.priority_mark.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark.full;
if (dfixed_trunc(priority_mark12) < 0)
priority_mark12.full = 0;
if (wm1.priority_mark_max.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark_max.full;
d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);
d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);
if (rdev->disp_priority == 2) {
d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1);
d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1);
}
} else if (mode0) {
if (dfixed_trunc(wm0.dbpp) > 64)
a.full = dfixed_mul(wm0.dbpp, wm0.num_line_pair);
else
a.full = wm0.num_line_pair.full;
fill_rate.full = dfixed_div(wm0.sclk, a);
if (wm0.consumption_rate.full > fill_rate.full) {
b.full = wm0.consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm0.active_time);
a.full = dfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
a.full = a.full + b.full;
b.full = dfixed_const(16 * 1000);
priority_mark02.full = dfixed_div(a, b);
} else {
a.full = dfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark02.full = dfixed_div(a, b);
}
if (wm0.priority_mark.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark.full;
if (dfixed_trunc(priority_mark02) < 0)
priority_mark02.full = 0;
if (wm0.priority_mark_max.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark_max.full;
d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);
if (rdev->disp_priority == 2)
d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1);
} else if (mode1) {
if (dfixed_trunc(wm1.dbpp) > 64)
a.full = dfixed_mul(wm1.dbpp, wm1.num_line_pair);
else
a.full = wm1.num_line_pair.full;
fill_rate.full = dfixed_div(wm1.sclk, a);
if (wm1.consumption_rate.full > fill_rate.full) {
b.full = wm1.consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm1.active_time);
a.full = dfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
a.full = a.full + b.full;
b.full = dfixed_const(16 * 1000);
priority_mark12.full = dfixed_div(a, b);
} else {
a.full = dfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark12.full = dfixed_div(a, b);
}
if (wm1.priority_mark.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark.full;
if (dfixed_trunc(priority_mark12) < 0)
priority_mark12.full = 0;
if (wm1.priority_mark_max.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark_max.full;
d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);
if (rdev->disp_priority == 2)
d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1);
}
rs690_compute_mode_priority(rdev,
&wm0_high, &wm1_high,
mode0, mode1,
&d1mode_priority_a_cnt, &d2mode_priority_a_cnt);
rs690_compute_mode_priority(rdev,
&wm0_low, &wm1_low,
mode0, mode1,
&d1mode_priority_b_cnt, &d2mode_priority_b_cnt);
WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_b_cnt);
WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_b_cnt);
}
uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg)

View File

@ -0,0 +1,963 @@
/*
* Copyright 2011 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: Alex Deucher
*/
#include "drmP.h"
#include "radeon.h"
#include "rs780d.h"
#include "r600_dpm.h"
#include "rs780_dpm.h"
#include "atom.h"
static struct igp_ps *rs780_get_ps(struct radeon_ps *rps)
{
struct igp_ps *ps = rps->ps_priv;
return ps;
}
static struct igp_power_info *rs780_get_pi(struct radeon_device *rdev)
{
struct igp_power_info *pi = rdev->pm.dpm.priv;
return pi;
}
static void rs780_get_pm_mode_parameters(struct radeon_device *rdev)
{
struct igp_power_info *pi = rs780_get_pi(rdev);
struct radeon_mode_info *minfo = &rdev->mode_info;
struct drm_crtc *crtc;
struct radeon_crtc *radeon_crtc;
int i;
/* defaults */
pi->crtc_id = 0;
pi->refresh_rate = 60;
for (i = 0; i < rdev->num_crtc; i++) {
crtc = (struct drm_crtc *)minfo->crtcs[i];
if (crtc && crtc->enabled) {
radeon_crtc = to_radeon_crtc(crtc);
pi->crtc_id = radeon_crtc->crtc_id;
if (crtc->mode.htotal && crtc->mode.vtotal)
pi->refresh_rate =
(crtc->mode.clock * 1000) /
(crtc->mode.htotal * crtc->mode.vtotal);
break;
}
}
}
static void rs780_voltage_scaling_enable(struct radeon_device *rdev, bool enable);
static int rs780_initialize_dpm_power_state(struct radeon_device *rdev,
struct radeon_ps *boot_ps)
{
struct atom_clock_dividers dividers;
struct igp_ps *default_state = rs780_get_ps(boot_ps);
int i, ret;
ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
default_state->sclk_low, false, &dividers);
if (ret)
return ret;
r600_engine_clock_entry_set_reference_divider(rdev, 0, dividers.ref_div);
r600_engine_clock_entry_set_feedback_divider(rdev, 0, dividers.fb_div);
r600_engine_clock_entry_set_post_divider(rdev, 0, dividers.post_div);
if (dividers.enable_post_div)
r600_engine_clock_entry_enable_post_divider(rdev, 0, true);
else
r600_engine_clock_entry_enable_post_divider(rdev, 0, false);
r600_engine_clock_entry_set_step_time(rdev, 0, R600_SST_DFLT);
r600_engine_clock_entry_enable_pulse_skipping(rdev, 0, false);
r600_engine_clock_entry_enable(rdev, 0, true);
for (i = 1; i < R600_PM_NUMBER_OF_SCLKS; i++)
r600_engine_clock_entry_enable(rdev, i, false);
r600_enable_mclk_control(rdev, false);
r600_voltage_control_enable_pins(rdev, 0);
return 0;
}
static int rs780_initialize_dpm_parameters(struct radeon_device *rdev,
struct radeon_ps *boot_ps)
{
int ret = 0;
int i;
r600_set_bsp(rdev, R600_BSU_DFLT, R600_BSP_DFLT);
r600_set_at(rdev, 0, 0, 0, 0);
r600_set_git(rdev, R600_GICST_DFLT);
for (i = 0; i < R600_PM_NUMBER_OF_TC; i++)
r600_set_tc(rdev, i, 0, 0);
r600_select_td(rdev, R600_TD_DFLT);
r600_set_vrc(rdev, 0);
r600_set_tpu(rdev, R600_TPU_DFLT);
r600_set_tpc(rdev, R600_TPC_DFLT);
r600_set_sstu(rdev, R600_SSTU_DFLT);
r600_set_sst(rdev, R600_SST_DFLT);
r600_set_fctu(rdev, R600_FCTU_DFLT);
r600_set_fct(rdev, R600_FCT_DFLT);
r600_set_vddc3d_oorsu(rdev, R600_VDDC3DOORSU_DFLT);
r600_set_vddc3d_oorphc(rdev, R600_VDDC3DOORPHC_DFLT);
r600_set_vddc3d_oorsdc(rdev, R600_VDDC3DOORSDC_DFLT);
r600_set_ctxcgtt3d_rphc(rdev, R600_CTXCGTT3DRPHC_DFLT);
r600_set_ctxcgtt3d_rsdc(rdev, R600_CTXCGTT3DRSDC_DFLT);
r600_vid_rt_set_vru(rdev, R600_VRU_DFLT);
r600_vid_rt_set_vrt(rdev, R600_VOLTAGERESPONSETIME_DFLT);
r600_vid_rt_set_ssu(rdev, R600_SPLLSTEPUNIT_DFLT);
ret = rs780_initialize_dpm_power_state(rdev, boot_ps);
r600_power_level_set_voltage_index(rdev, R600_POWER_LEVEL_LOW, 0);
r600_power_level_set_voltage_index(rdev, R600_POWER_LEVEL_MEDIUM, 0);
r600_power_level_set_voltage_index(rdev, R600_POWER_LEVEL_HIGH, 0);
r600_power_level_set_mem_clock_index(rdev, R600_POWER_LEVEL_LOW, 0);
r600_power_level_set_mem_clock_index(rdev, R600_POWER_LEVEL_MEDIUM, 0);
r600_power_level_set_mem_clock_index(rdev, R600_POWER_LEVEL_HIGH, 0);
r600_power_level_set_eng_clock_index(rdev, R600_POWER_LEVEL_LOW, 0);
r600_power_level_set_eng_clock_index(rdev, R600_POWER_LEVEL_MEDIUM, 0);
r600_power_level_set_eng_clock_index(rdev, R600_POWER_LEVEL_HIGH, 0);
r600_power_level_set_watermark_id(rdev, R600_POWER_LEVEL_LOW, R600_DISPLAY_WATERMARK_HIGH);
r600_power_level_set_watermark_id(rdev, R600_POWER_LEVEL_MEDIUM, R600_DISPLAY_WATERMARK_HIGH);
r600_power_level_set_watermark_id(rdev, R600_POWER_LEVEL_HIGH, R600_DISPLAY_WATERMARK_HIGH);
r600_power_level_enable(rdev, R600_POWER_LEVEL_CTXSW, false);
r600_power_level_enable(rdev, R600_POWER_LEVEL_HIGH, false);
r600_power_level_enable(rdev, R600_POWER_LEVEL_MEDIUM, false);
r600_power_level_enable(rdev, R600_POWER_LEVEL_LOW, true);
r600_power_level_set_enter_index(rdev, R600_POWER_LEVEL_LOW);
r600_set_vrc(rdev, RS780_CGFTV_DFLT);
return ret;
}
static void rs780_start_dpm(struct radeon_device *rdev)
{
r600_enable_sclk_control(rdev, false);
r600_enable_mclk_control(rdev, false);
r600_dynamicpm_enable(rdev, true);
radeon_wait_for_vblank(rdev, 0);
radeon_wait_for_vblank(rdev, 1);
r600_enable_spll_bypass(rdev, true);
r600_wait_for_spll_change(rdev);
r600_enable_spll_bypass(rdev, false);
r600_wait_for_spll_change(rdev);
r600_enable_spll_bypass(rdev, true);
r600_wait_for_spll_change(rdev);
r600_enable_spll_bypass(rdev, false);
r600_wait_for_spll_change(rdev);
r600_enable_sclk_control(rdev, true);
}
static void rs780_preset_ranges_slow_clk_fbdiv_en(struct radeon_device *rdev)
{
WREG32_P(FVTHROT_SLOW_CLK_FEEDBACK_DIV_REG1, RANGE_SLOW_CLK_FEEDBACK_DIV_EN,
~RANGE_SLOW_CLK_FEEDBACK_DIV_EN);
WREG32_P(FVTHROT_SLOW_CLK_FEEDBACK_DIV_REG1,
RANGE0_SLOW_CLK_FEEDBACK_DIV(RS780_SLOWCLKFEEDBACKDIV_DFLT),
~RANGE0_SLOW_CLK_FEEDBACK_DIV_MASK);
}
static void rs780_preset_starting_fbdiv(struct radeon_device *rdev)
{
u32 fbdiv = (RREG32(CG_SPLL_FUNC_CNTL) & SPLL_FB_DIV_MASK) >> SPLL_FB_DIV_SHIFT;
WREG32_P(FVTHROT_FBDIV_REG1, STARTING_FEEDBACK_DIV(fbdiv),
~STARTING_FEEDBACK_DIV_MASK);
WREG32_P(FVTHROT_FBDIV_REG2, FORCED_FEEDBACK_DIV(fbdiv),
~FORCED_FEEDBACK_DIV_MASK);
WREG32_P(FVTHROT_FBDIV_REG1, FORCE_FEEDBACK_DIV, ~FORCE_FEEDBACK_DIV);
}
static void rs780_voltage_scaling_init(struct radeon_device *rdev)
{
struct igp_power_info *pi = rs780_get_pi(rdev);
struct drm_device *dev = rdev->ddev;
u32 fv_throt_pwm_fb_div_range[3];
u32 fv_throt_pwm_range[4];
if (dev->pdev->device == 0x9614) {
fv_throt_pwm_fb_div_range[0] = RS780D_FVTHROTPWMFBDIVRANGEREG0_DFLT;
fv_throt_pwm_fb_div_range[1] = RS780D_FVTHROTPWMFBDIVRANGEREG1_DFLT;
fv_throt_pwm_fb_div_range[2] = RS780D_FVTHROTPWMFBDIVRANGEREG2_DFLT;
} else if ((dev->pdev->device == 0x9714) ||
(dev->pdev->device == 0x9715)) {
fv_throt_pwm_fb_div_range[0] = RS880D_FVTHROTPWMFBDIVRANGEREG0_DFLT;
fv_throt_pwm_fb_div_range[1] = RS880D_FVTHROTPWMFBDIVRANGEREG1_DFLT;
fv_throt_pwm_fb_div_range[2] = RS880D_FVTHROTPWMFBDIVRANGEREG2_DFLT;
} else {
fv_throt_pwm_fb_div_range[0] = RS780_FVTHROTPWMFBDIVRANGEREG0_DFLT;
fv_throt_pwm_fb_div_range[1] = RS780_FVTHROTPWMFBDIVRANGEREG1_DFLT;
fv_throt_pwm_fb_div_range[2] = RS780_FVTHROTPWMFBDIVRANGEREG2_DFLT;
}
if (pi->pwm_voltage_control) {
fv_throt_pwm_range[0] = pi->min_voltage;
fv_throt_pwm_range[1] = pi->min_voltage;
fv_throt_pwm_range[2] = pi->max_voltage;
fv_throt_pwm_range[3] = pi->max_voltage;
} else {
fv_throt_pwm_range[0] = pi->invert_pwm_required ?
RS780_FVTHROTPWMRANGE3_GPIO_DFLT : RS780_FVTHROTPWMRANGE0_GPIO_DFLT;
fv_throt_pwm_range[1] = pi->invert_pwm_required ?
RS780_FVTHROTPWMRANGE2_GPIO_DFLT : RS780_FVTHROTPWMRANGE1_GPIO_DFLT;
fv_throt_pwm_range[2] = pi->invert_pwm_required ?
RS780_FVTHROTPWMRANGE1_GPIO_DFLT : RS780_FVTHROTPWMRANGE2_GPIO_DFLT;
fv_throt_pwm_range[3] = pi->invert_pwm_required ?
RS780_FVTHROTPWMRANGE0_GPIO_DFLT : RS780_FVTHROTPWMRANGE3_GPIO_DFLT;
}
WREG32_P(FVTHROT_PWM_CTRL_REG0,
STARTING_PWM_HIGHTIME(pi->max_voltage),
~STARTING_PWM_HIGHTIME_MASK);
WREG32_P(FVTHROT_PWM_CTRL_REG0,
NUMBER_OF_CYCLES_IN_PERIOD(pi->num_of_cycles_in_period),
~NUMBER_OF_CYCLES_IN_PERIOD_MASK);
WREG32_P(FVTHROT_PWM_CTRL_REG0, FORCE_STARTING_PWM_HIGHTIME,
~FORCE_STARTING_PWM_HIGHTIME);
if (pi->invert_pwm_required)
WREG32_P(FVTHROT_PWM_CTRL_REG0, INVERT_PWM_WAVEFORM, ~INVERT_PWM_WAVEFORM);
else
WREG32_P(FVTHROT_PWM_CTRL_REG0, 0, ~INVERT_PWM_WAVEFORM);
rs780_voltage_scaling_enable(rdev, true);
WREG32(FVTHROT_PWM_CTRL_REG1,
(MIN_PWM_HIGHTIME(pi->min_voltage) |
MAX_PWM_HIGHTIME(pi->max_voltage)));
WREG32(FVTHROT_PWM_US_REG0, RS780_FVTHROTPWMUSREG0_DFLT);
WREG32(FVTHROT_PWM_US_REG1, RS780_FVTHROTPWMUSREG1_DFLT);
WREG32(FVTHROT_PWM_DS_REG0, RS780_FVTHROTPWMDSREG0_DFLT);
WREG32(FVTHROT_PWM_DS_REG1, RS780_FVTHROTPWMDSREG1_DFLT);
WREG32_P(FVTHROT_PWM_FEEDBACK_DIV_REG1,
RANGE0_PWM_FEEDBACK_DIV(fv_throt_pwm_fb_div_range[0]),
~RANGE0_PWM_FEEDBACK_DIV_MASK);
WREG32(FVTHROT_PWM_FEEDBACK_DIV_REG2,
(RANGE1_PWM_FEEDBACK_DIV(fv_throt_pwm_fb_div_range[1]) |
RANGE2_PWM_FEEDBACK_DIV(fv_throt_pwm_fb_div_range[2])));
WREG32(FVTHROT_PWM_FEEDBACK_DIV_REG3,
(RANGE0_PWM(fv_throt_pwm_range[1]) |
RANGE1_PWM(fv_throt_pwm_range[2])));
WREG32(FVTHROT_PWM_FEEDBACK_DIV_REG4,
(RANGE2_PWM(fv_throt_pwm_range[1]) |
RANGE3_PWM(fv_throt_pwm_range[2])));
}
static void rs780_clk_scaling_enable(struct radeon_device *rdev, bool enable)
{
if (enable)
WREG32_P(FVTHROT_CNTRL_REG, ENABLE_FV_THROT | ENABLE_FV_UPDATE,
~(ENABLE_FV_THROT | ENABLE_FV_UPDATE));
else
WREG32_P(FVTHROT_CNTRL_REG, 0,
~(ENABLE_FV_THROT | ENABLE_FV_UPDATE));
}
static void rs780_voltage_scaling_enable(struct radeon_device *rdev, bool enable)
{
if (enable)
WREG32_P(FVTHROT_CNTRL_REG, ENABLE_FV_THROT_IO, ~ENABLE_FV_THROT_IO);
else
WREG32_P(FVTHROT_CNTRL_REG, 0, ~ENABLE_FV_THROT_IO);
}
static void rs780_set_engine_clock_wfc(struct radeon_device *rdev)
{
WREG32(FVTHROT_UTC0, RS780_FVTHROTUTC0_DFLT);
WREG32(FVTHROT_UTC1, RS780_FVTHROTUTC1_DFLT);
WREG32(FVTHROT_UTC2, RS780_FVTHROTUTC2_DFLT);
WREG32(FVTHROT_UTC3, RS780_FVTHROTUTC3_DFLT);
WREG32(FVTHROT_UTC4, RS780_FVTHROTUTC4_DFLT);
WREG32(FVTHROT_DTC0, RS780_FVTHROTDTC0_DFLT);
WREG32(FVTHROT_DTC1, RS780_FVTHROTDTC1_DFLT);
WREG32(FVTHROT_DTC2, RS780_FVTHROTDTC2_DFLT);
WREG32(FVTHROT_DTC3, RS780_FVTHROTDTC3_DFLT);
WREG32(FVTHROT_DTC4, RS780_FVTHROTDTC4_DFLT);
}
static void rs780_set_engine_clock_sc(struct radeon_device *rdev)
{
WREG32_P(FVTHROT_FBDIV_REG2,
FB_DIV_TIMER_VAL(RS780_FBDIVTIMERVAL_DFLT),
~FB_DIV_TIMER_VAL_MASK);
WREG32_P(FVTHROT_CNTRL_REG,
REFRESH_RATE_DIVISOR(0) | MINIMUM_CIP(0xf),
~(REFRESH_RATE_DIVISOR_MASK | MINIMUM_CIP_MASK));
}
static void rs780_set_engine_clock_tdc(struct radeon_device *rdev)
{
WREG32_P(FVTHROT_CNTRL_REG, 0, ~(FORCE_TREND_SEL | TREND_SEL_MODE));
}
static void rs780_set_engine_clock_ssc(struct radeon_device *rdev)
{
WREG32(FVTHROT_FB_US_REG0, RS780_FVTHROTFBUSREG0_DFLT);
WREG32(FVTHROT_FB_US_REG1, RS780_FVTHROTFBUSREG1_DFLT);
WREG32(FVTHROT_FB_DS_REG0, RS780_FVTHROTFBDSREG0_DFLT);
WREG32(FVTHROT_FB_DS_REG1, RS780_FVTHROTFBDSREG1_DFLT);
WREG32_P(FVTHROT_FBDIV_REG1, MAX_FEEDBACK_STEP(1), ~MAX_FEEDBACK_STEP_MASK);
}
static void rs780_program_at(struct radeon_device *rdev)
{
struct igp_power_info *pi = rs780_get_pi(rdev);
WREG32(FVTHROT_TARGET_REG, 30000000 / pi->refresh_rate);
WREG32(FVTHROT_CB1, 1000000 * 5 / pi->refresh_rate);
WREG32(FVTHROT_CB2, 1000000 * 10 / pi->refresh_rate);
WREG32(FVTHROT_CB3, 1000000 * 30 / pi->refresh_rate);
WREG32(FVTHROT_CB4, 1000000 * 50 / pi->refresh_rate);
}
static void rs780_disable_vbios_powersaving(struct radeon_device *rdev)
{
WREG32_P(CG_INTGFX_MISC, 0, ~0xFFF00000);
}
static void rs780_force_voltage_to_high(struct radeon_device *rdev)
{
struct igp_power_info *pi = rs780_get_pi(rdev);
struct igp_ps *current_state = rs780_get_ps(rdev->pm.dpm.current_ps);
if ((current_state->max_voltage == RS780_VDDC_LEVEL_HIGH) &&
(current_state->min_voltage == RS780_VDDC_LEVEL_HIGH))
return;
WREG32_P(GFX_MACRO_BYPASS_CNTL, SPLL_BYPASS_CNTL, ~SPLL_BYPASS_CNTL);
udelay(1);
WREG32_P(FVTHROT_PWM_CTRL_REG0,
STARTING_PWM_HIGHTIME(pi->max_voltage),
~STARTING_PWM_HIGHTIME_MASK);
WREG32_P(FVTHROT_PWM_CTRL_REG0,
FORCE_STARTING_PWM_HIGHTIME, ~FORCE_STARTING_PWM_HIGHTIME);
WREG32_P(FVTHROT_PWM_FEEDBACK_DIV_REG1, 0,
~RANGE_PWM_FEEDBACK_DIV_EN);
udelay(1);
WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL);
}
static int rs780_set_engine_clock_scaling(struct radeon_device *rdev,
struct radeon_ps *new_ps,
struct radeon_ps *old_ps)
{
struct atom_clock_dividers min_dividers, max_dividers, current_max_dividers;
struct igp_ps *new_state = rs780_get_ps(new_ps);
struct igp_ps *old_state = rs780_get_ps(old_ps);
int ret;
if ((new_state->sclk_high == old_state->sclk_high) &&
(new_state->sclk_low == old_state->sclk_low))
return 0;
ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
new_state->sclk_low, false, &min_dividers);
if (ret)
return ret;
ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
new_state->sclk_high, false, &max_dividers);
if (ret)
return ret;
ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
old_state->sclk_high, false, &current_max_dividers);
if (ret)
return ret;
WREG32_P(GFX_MACRO_BYPASS_CNTL, SPLL_BYPASS_CNTL, ~SPLL_BYPASS_CNTL);
WREG32_P(FVTHROT_FBDIV_REG2, FORCED_FEEDBACK_DIV(max_dividers.fb_div),
~FORCED_FEEDBACK_DIV_MASK);
WREG32_P(FVTHROT_FBDIV_REG1, STARTING_FEEDBACK_DIV(max_dividers.fb_div),
~STARTING_FEEDBACK_DIV_MASK);
WREG32_P(FVTHROT_FBDIV_REG1, FORCE_FEEDBACK_DIV, ~FORCE_FEEDBACK_DIV);
udelay(100);
WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL);
if (max_dividers.fb_div > min_dividers.fb_div) {
WREG32_P(FVTHROT_FBDIV_REG0,
MIN_FEEDBACK_DIV(min_dividers.fb_div) |
MAX_FEEDBACK_DIV(max_dividers.fb_div),
~(MIN_FEEDBACK_DIV_MASK | MAX_FEEDBACK_DIV_MASK));
WREG32_P(FVTHROT_FBDIV_REG1, 0, ~FORCE_FEEDBACK_DIV);
}
return 0;
}
static void rs780_set_engine_clock_spc(struct radeon_device *rdev,
struct radeon_ps *new_ps,
struct radeon_ps *old_ps)
{
struct igp_ps *new_state = rs780_get_ps(new_ps);
struct igp_ps *old_state = rs780_get_ps(old_ps);
struct igp_power_info *pi = rs780_get_pi(rdev);
if ((new_state->sclk_high == old_state->sclk_high) &&
(new_state->sclk_low == old_state->sclk_low))
return;
if (pi->crtc_id == 0)
WREG32_P(CG_INTGFX_MISC, 0, ~FVTHROT_VBLANK_SEL);
else
WREG32_P(CG_INTGFX_MISC, FVTHROT_VBLANK_SEL, ~FVTHROT_VBLANK_SEL);
}
static void rs780_activate_engine_clk_scaling(struct radeon_device *rdev,
struct radeon_ps *new_ps,
struct radeon_ps *old_ps)
{
struct igp_ps *new_state = rs780_get_ps(new_ps);
struct igp_ps *old_state = rs780_get_ps(old_ps);
if ((new_state->sclk_high == old_state->sclk_high) &&
(new_state->sclk_low == old_state->sclk_low))
return;
rs780_clk_scaling_enable(rdev, true);
}
static u32 rs780_get_voltage_for_vddc_level(struct radeon_device *rdev,
enum rs780_vddc_level vddc)
{
struct igp_power_info *pi = rs780_get_pi(rdev);
if (vddc == RS780_VDDC_LEVEL_HIGH)
return pi->max_voltage;
else if (vddc == RS780_VDDC_LEVEL_LOW)
return pi->min_voltage;
else
return pi->max_voltage;
}
static void rs780_enable_voltage_scaling(struct radeon_device *rdev,
struct radeon_ps *new_ps)
{
struct igp_ps *new_state = rs780_get_ps(new_ps);
struct igp_power_info *pi = rs780_get_pi(rdev);
enum rs780_vddc_level vddc_high, vddc_low;
udelay(100);
if ((new_state->max_voltage == RS780_VDDC_LEVEL_HIGH) &&
(new_state->min_voltage == RS780_VDDC_LEVEL_HIGH))
return;
vddc_high = rs780_get_voltage_for_vddc_level(rdev,
new_state->max_voltage);
vddc_low = rs780_get_voltage_for_vddc_level(rdev,
new_state->min_voltage);
WREG32_P(GFX_MACRO_BYPASS_CNTL, SPLL_BYPASS_CNTL, ~SPLL_BYPASS_CNTL);
udelay(1);
if (vddc_high > vddc_low) {
WREG32_P(FVTHROT_PWM_FEEDBACK_DIV_REG1,
RANGE_PWM_FEEDBACK_DIV_EN, ~RANGE_PWM_FEEDBACK_DIV_EN);
WREG32_P(FVTHROT_PWM_CTRL_REG0, 0, ~FORCE_STARTING_PWM_HIGHTIME);
} else if (vddc_high == vddc_low) {
if (pi->max_voltage != vddc_high) {
WREG32_P(FVTHROT_PWM_CTRL_REG0,
STARTING_PWM_HIGHTIME(vddc_high),
~STARTING_PWM_HIGHTIME_MASK);
WREG32_P(FVTHROT_PWM_CTRL_REG0,
FORCE_STARTING_PWM_HIGHTIME,
~FORCE_STARTING_PWM_HIGHTIME);
}
}
WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL);
}
static void rs780_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
struct radeon_ps *new_ps,
struct radeon_ps *old_ps)
{
struct igp_ps *new_state = rs780_get_ps(new_ps);
struct igp_ps *current_state = rs780_get_ps(old_ps);
if ((new_ps->vclk == old_ps->vclk) &&
(new_ps->dclk == old_ps->dclk))
return;
if (new_state->sclk_high >= current_state->sclk_high)
return;
radeon_set_uvd_clocks(rdev, new_ps->vclk, new_ps->dclk);
}
static void rs780_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
struct radeon_ps *new_ps,
struct radeon_ps *old_ps)
{
struct igp_ps *new_state = rs780_get_ps(new_ps);
struct igp_ps *current_state = rs780_get_ps(old_ps);
if ((new_ps->vclk == old_ps->vclk) &&
(new_ps->dclk == old_ps->dclk))
return;
if (new_state->sclk_high < current_state->sclk_high)
return;
radeon_set_uvd_clocks(rdev, new_ps->vclk, new_ps->dclk);
}
int rs780_dpm_enable(struct radeon_device *rdev)
{
struct igp_power_info *pi = rs780_get_pi(rdev);
struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
int ret;
rs780_get_pm_mode_parameters(rdev);
rs780_disable_vbios_powersaving(rdev);
if (r600_dynamicpm_enabled(rdev))
return -EINVAL;
ret = rs780_initialize_dpm_parameters(rdev, boot_ps);
if (ret)
return ret;
rs780_start_dpm(rdev);
rs780_preset_ranges_slow_clk_fbdiv_en(rdev);
rs780_preset_starting_fbdiv(rdev);
if (pi->voltage_control)
rs780_voltage_scaling_init(rdev);
rs780_clk_scaling_enable(rdev, true);
rs780_set_engine_clock_sc(rdev);
rs780_set_engine_clock_wfc(rdev);
rs780_program_at(rdev);
rs780_set_engine_clock_tdc(rdev);
rs780_set_engine_clock_ssc(rdev);
if (pi->gfx_clock_gating)
r600_gfx_clockgating_enable(rdev, true);
if (rdev->irq.installed && (rdev->pm.int_thermal_type == THERMAL_TYPE_RV6XX)) {
ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
if (ret)
return ret;
rdev->irq.dpm_thermal = true;
radeon_irq_set(rdev);
}
return 0;
}
void rs780_dpm_disable(struct radeon_device *rdev)
{
struct igp_power_info *pi = rs780_get_pi(rdev);
r600_dynamicpm_enable(rdev, false);
rs780_clk_scaling_enable(rdev, false);
rs780_voltage_scaling_enable(rdev, false);
if (pi->gfx_clock_gating)
r600_gfx_clockgating_enable(rdev, false);
if (rdev->irq.installed &&
(rdev->pm.int_thermal_type == THERMAL_TYPE_RV6XX)) {
rdev->irq.dpm_thermal = false;
radeon_irq_set(rdev);
}
}
int rs780_dpm_set_power_state(struct radeon_device *rdev)
{
struct igp_power_info *pi = rs780_get_pi(rdev);
struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
int ret;
rs780_get_pm_mode_parameters(rdev);
rs780_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
if (pi->voltage_control) {
rs780_force_voltage_to_high(rdev);
mdelay(5);
}
ret = rs780_set_engine_clock_scaling(rdev, new_ps, old_ps);
if (ret)
return ret;
rs780_set_engine_clock_spc(rdev, new_ps, old_ps);
rs780_activate_engine_clk_scaling(rdev, new_ps, old_ps);
if (pi->voltage_control)
rs780_enable_voltage_scaling(rdev, new_ps);
rs780_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
return 0;
}
void rs780_dpm_setup_asic(struct radeon_device *rdev)
{
}
void rs780_dpm_display_configuration_changed(struct radeon_device *rdev)
{
rs780_get_pm_mode_parameters(rdev);
rs780_program_at(rdev);
}
union igp_info {
struct _ATOM_INTEGRATED_SYSTEM_INFO info;
struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
};
union power_info {
struct _ATOM_POWERPLAY_INFO info;
struct _ATOM_POWERPLAY_INFO_V2 info_2;
struct _ATOM_POWERPLAY_INFO_V3 info_3;
struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
};
union pplib_clock_info {
struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
};
union pplib_power_state {
struct _ATOM_PPLIB_STATE v1;
struct _ATOM_PPLIB_STATE_V2 v2;
};
static void rs780_parse_pplib_non_clock_info(struct radeon_device *rdev,
struct radeon_ps *rps,
struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
u8 table_rev)
{
rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
rps->class = le16_to_cpu(non_clock_info->usClassification);
rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
} else if (r600_is_uvd_state(rps->class, rps->class2)) {
rps->vclk = RS780_DEFAULT_VCLK_FREQ;
rps->dclk = RS780_DEFAULT_DCLK_FREQ;
} else {
rps->vclk = 0;
rps->dclk = 0;
}
if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT)
rdev->pm.dpm.boot_ps = rps;
if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
rdev->pm.dpm.uvd_ps = rps;
}
static void rs780_parse_pplib_clock_info(struct radeon_device *rdev,
struct radeon_ps *rps,
union pplib_clock_info *clock_info)
{
struct igp_ps *ps = rs780_get_ps(rps);
u32 sclk;
sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow);
sclk |= clock_info->rs780.ucLowEngineClockHigh << 16;
ps->sclk_low = sclk;
sclk = le16_to_cpu(clock_info->rs780.usHighEngineClockLow);
sclk |= clock_info->rs780.ucHighEngineClockHigh << 16;
ps->sclk_high = sclk;
switch (le16_to_cpu(clock_info->rs780.usVDDC)) {
case ATOM_PPLIB_RS780_VOLTAGE_NONE:
default:
ps->min_voltage = RS780_VDDC_LEVEL_UNKNOWN;
ps->max_voltage = RS780_VDDC_LEVEL_UNKNOWN;
break;
case ATOM_PPLIB_RS780_VOLTAGE_LOW:
ps->min_voltage = RS780_VDDC_LEVEL_LOW;
ps->max_voltage = RS780_VDDC_LEVEL_LOW;
break;
case ATOM_PPLIB_RS780_VOLTAGE_HIGH:
ps->min_voltage = RS780_VDDC_LEVEL_HIGH;
ps->max_voltage = RS780_VDDC_LEVEL_HIGH;
break;
case ATOM_PPLIB_RS780_VOLTAGE_VARIABLE:
ps->min_voltage = RS780_VDDC_LEVEL_LOW;
ps->max_voltage = RS780_VDDC_LEVEL_HIGH;
break;
}
ps->flags = le32_to_cpu(clock_info->rs780.ulFlags);
if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
ps->sclk_low = rdev->clock.default_sclk;
ps->sclk_high = rdev->clock.default_sclk;
ps->min_voltage = RS780_VDDC_LEVEL_HIGH;
ps->max_voltage = RS780_VDDC_LEVEL_HIGH;
}
}
static int rs780_parse_power_table(struct radeon_device *rdev)
{
struct radeon_mode_info *mode_info = &rdev->mode_info;
struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
union pplib_power_state *power_state;
int i;
union pplib_clock_info *clock_info;
union power_info *power_info;
int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
u16 data_offset;
u8 frev, crev;
struct igp_ps *ps;
if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset))
return -EINVAL;
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
power_info->pplib.ucNumStates, GFP_KERNEL);
if (!rdev->pm.dpm.ps)
return -ENOMEM;
rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
for (i = 0; i < power_info->pplib.ucNumStates; i++) {
power_state = (union pplib_power_state *)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usStateArrayOffset) +
i * power_info->pplib.ucStateEntrySize);
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
(power_state->v1.ucNonClockStateIndex *
power_info->pplib.ucNonClockSize));
if (power_info->pplib.ucStateEntrySize - 1) {
clock_info = (union pplib_clock_info *)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
(power_state->v1.ucClockStateIndices[0] *
power_info->pplib.ucClockInfoSize));
ps = kzalloc(sizeof(struct igp_ps), GFP_KERNEL);
if (ps == NULL) {
kfree(rdev->pm.dpm.ps);
return -ENOMEM;
}
rdev->pm.dpm.ps[i].ps_priv = ps;
rs780_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
non_clock_info,
power_info->pplib.ucNonClockSize);
rs780_parse_pplib_clock_info(rdev,
&rdev->pm.dpm.ps[i],
clock_info);
}
}
rdev->pm.dpm.num_ps = power_info->pplib.ucNumStates;
return 0;
}
int rs780_dpm_init(struct radeon_device *rdev)
{
struct igp_power_info *pi;
int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
union igp_info *info;
u16 data_offset;
u8 frev, crev;
int ret;
pi = kzalloc(sizeof(struct igp_power_info), GFP_KERNEL);
if (pi == NULL)
return -ENOMEM;
rdev->pm.dpm.priv = pi;
ret = rs780_parse_power_table(rdev);
if (ret)
return ret;
pi->voltage_control = false;
pi->gfx_clock_gating = true;
if (atom_parse_data_header(rdev->mode_info.atom_context, index, NULL,
&frev, &crev, &data_offset)) {
info = (union igp_info *)(rdev->mode_info.atom_context->bios + data_offset);
/* Get various system informations from bios */
switch (crev) {
case 1:
pi->num_of_cycles_in_period =
info->info.ucNumberOfCyclesInPeriod;
pi->num_of_cycles_in_period |=
info->info.ucNumberOfCyclesInPeriodHi << 8;
pi->invert_pwm_required =
(pi->num_of_cycles_in_period & 0x8000) ? true : false;
pi->boot_voltage = info->info.ucStartingPWM_HighTime;
pi->max_voltage = info->info.ucMaxNBVoltage;
pi->max_voltage |= info->info.ucMaxNBVoltageHigh << 8;
pi->min_voltage = info->info.ucMinNBVoltage;
pi->min_voltage |= info->info.ucMinNBVoltageHigh << 8;
pi->inter_voltage_low =
le16_to_cpu(info->info.usInterNBVoltageLow);
pi->inter_voltage_high =
le16_to_cpu(info->info.usInterNBVoltageHigh);
pi->voltage_control = true;
pi->bootup_uma_clk = info->info.usK8MemoryClock * 100;
break;
case 2:
pi->num_of_cycles_in_period =
le16_to_cpu(info->info_2.usNumberOfCyclesInPeriod);
pi->invert_pwm_required =
(pi->num_of_cycles_in_period & 0x8000) ? true : false;
pi->boot_voltage =
le16_to_cpu(info->info_2.usBootUpNBVoltage);
pi->max_voltage =
le16_to_cpu(info->info_2.usMaxNBVoltage);
pi->min_voltage =
le16_to_cpu(info->info_2.usMinNBVoltage);
pi->system_config =
le32_to_cpu(info->info_2.ulSystemConfig);
pi->pwm_voltage_control =
(pi->system_config & 0x4) ? true : false;
pi->voltage_control = true;
pi->bootup_uma_clk = le32_to_cpu(info->info_2.ulBootUpUMAClock);
break;
default:
DRM_ERROR("No integrated system info for your GPU\n");
return -EINVAL;
}
if (pi->min_voltage > pi->max_voltage)
pi->voltage_control = false;
if (pi->pwm_voltage_control) {
if ((pi->num_of_cycles_in_period == 0) ||
(pi->max_voltage == 0) ||
(pi->min_voltage == 0))
pi->voltage_control = false;
} else {
if ((pi->num_of_cycles_in_period == 0) ||
(pi->max_voltage == 0))
pi->voltage_control = false;
}
return 0;
}
radeon_dpm_fini(rdev);
return -EINVAL;
}
void rs780_dpm_print_power_state(struct radeon_device *rdev,
struct radeon_ps *rps)
{
struct igp_ps *ps = rs780_get_ps(rps);
r600_dpm_print_class_info(rps->class, rps->class2);
r600_dpm_print_cap_info(rps->caps);
printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
printk("\t\tpower level 0 sclk: %u vddc_index: %d\n",
ps->sclk_low, ps->min_voltage);
printk("\t\tpower level 1 sclk: %u vddc_index: %d\n",
ps->sclk_high, ps->max_voltage);
r600_dpm_print_ps_status(rdev, rps);
}
void rs780_dpm_fini(struct radeon_device *rdev)
{
int i;
for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
kfree(rdev->pm.dpm.ps[i].ps_priv);
}
kfree(rdev->pm.dpm.ps);
kfree(rdev->pm.dpm.priv);
}
u32 rs780_dpm_get_sclk(struct radeon_device *rdev, bool low)
{
struct igp_ps *requested_state = rs780_get_ps(rdev->pm.dpm.requested_ps);
if (low)
return requested_state->sclk_low;
else
return requested_state->sclk_high;
}
u32 rs780_dpm_get_mclk(struct radeon_device *rdev, bool low)
{
struct igp_power_info *pi = rs780_get_pi(rdev);
return pi->bootup_uma_clk;
}

View File

@ -0,0 +1,109 @@
/*
* Copyright 2011 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.
*
*/
#ifndef __RS780_DPM_H__
#define __RS780_DPM_H__
enum rs780_vddc_level {
RS780_VDDC_LEVEL_UNKNOWN = 0,
RS780_VDDC_LEVEL_LOW = 1,
RS780_VDDC_LEVEL_HIGH = 2,
};
struct igp_power_info {
/* flags */
bool invert_pwm_required;
bool pwm_voltage_control;
bool voltage_control;
bool gfx_clock_gating;
/* stored values */
u32 system_config;
u32 bootup_uma_clk;
u16 max_voltage;
u16 min_voltage;
u16 boot_voltage;
u16 inter_voltage_low;
u16 inter_voltage_high;
u16 num_of_cycles_in_period;
/* variable */
int crtc_id;
int refresh_rate;
};
struct igp_ps {
enum rs780_vddc_level min_voltage;
enum rs780_vddc_level max_voltage;
u32 sclk_low;
u32 sclk_high;
u32 flags;
};
#define RS780_CGFTV_DFLT 0x0303000f
#define RS780_FBDIVTIMERVAL_DFLT 0x2710
#define RS780_FVTHROTUTC0_DFLT 0x04010040
#define RS780_FVTHROTUTC1_DFLT 0x04010040
#define RS780_FVTHROTUTC2_DFLT 0x04010040
#define RS780_FVTHROTUTC3_DFLT 0x04010040
#define RS780_FVTHROTUTC4_DFLT 0x04010040
#define RS780_FVTHROTDTC0_DFLT 0x04010040
#define RS780_FVTHROTDTC1_DFLT 0x04010040
#define RS780_FVTHROTDTC2_DFLT 0x04010040
#define RS780_FVTHROTDTC3_DFLT 0x04010040
#define RS780_FVTHROTDTC4_DFLT 0x04010040
#define RS780_FVTHROTFBUSREG0_DFLT 0x00001001
#define RS780_FVTHROTFBUSREG1_DFLT 0x00002002
#define RS780_FVTHROTFBDSREG0_DFLT 0x00004001
#define RS780_FVTHROTFBDSREG1_DFLT 0x00020010
#define RS780_FVTHROTPWMUSREG0_DFLT 0x00002001
#define RS780_FVTHROTPWMUSREG1_DFLT 0x00004003
#define RS780_FVTHROTPWMDSREG0_DFLT 0x00002001
#define RS780_FVTHROTPWMDSREG1_DFLT 0x00004003
#define RS780_FVTHROTPWMFBDIVRANGEREG0_DFLT 0x37
#define RS780_FVTHROTPWMFBDIVRANGEREG1_DFLT 0x4b
#define RS780_FVTHROTPWMFBDIVRANGEREG2_DFLT 0x8b
#define RS780D_FVTHROTPWMFBDIVRANGEREG0_DFLT 0x8b
#define RS780D_FVTHROTPWMFBDIVRANGEREG1_DFLT 0x8c
#define RS780D_FVTHROTPWMFBDIVRANGEREG2_DFLT 0xb5
#define RS880D_FVTHROTPWMFBDIVRANGEREG0_DFLT 0x8d
#define RS880D_FVTHROTPWMFBDIVRANGEREG1_DFLT 0x8e
#define RS880D_FVTHROTPWMFBDIVRANGEREG2_DFLT 0xBa
#define RS780_FVTHROTPWMRANGE0_GPIO_DFLT 0x1a
#define RS780_FVTHROTPWMRANGE1_GPIO_DFLT 0x1a
#define RS780_FVTHROTPWMRANGE2_GPIO_DFLT 0x0
#define RS780_FVTHROTPWMRANGE3_GPIO_DFLT 0x0
#define RS780_SLOWCLKFEEDBACKDIV_DFLT 110
#define RS780_CGCLKGATING_DFLT 0x0000E204
#define RS780_DEFAULT_VCLK_FREQ 53300 /* 10 khz */
#define RS780_DEFAULT_DCLK_FREQ 40000 /* 10 khz */
#endif

View File

@ -0,0 +1,168 @@
/*
* Copyright 2011 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.
*
*/
#ifndef __RS780D_H__
#define __RS780D_H__
#define CG_SPLL_FUNC_CNTL 0x600
# define SPLL_RESET (1 << 0)
# define SPLL_SLEEP (1 << 1)
# define SPLL_REF_DIV(x) ((x) << 2)
# define SPLL_REF_DIV_MASK (7 << 2)
# define SPLL_FB_DIV(x) ((x) << 5)
# define SPLL_FB_DIV_MASK (0xff << 2)
# define SPLL_FB_DIV_SHIFT 2
# define SPLL_PULSEEN (1 << 13)
# define SPLL_PULSENUM(x) ((x) << 14)
# define SPLL_PULSENUM_MASK (3 << 14)
# define SPLL_SW_HILEN(x) ((x) << 16)
# define SPLL_SW_HILEN_MASK (0xf << 16)
# define SPLL_SW_LOLEN(x) ((x) << 20)
# define SPLL_SW_LOLEN_MASK (0xf << 20)
# define SPLL_DIVEN (1 << 24)
# define SPLL_BYPASS_EN (1 << 25)
# define SPLL_CHG_STATUS (1 << 29)
# define SPLL_CTLREQ (1 << 30)
# define SPLL_CTLACK (1 << 31)
/* RS780/RS880 PM */
#define FVTHROT_CNTRL_REG 0x3000
#define DONT_WAIT_FOR_FBDIV_WRAP (1 << 0)
#define MINIMUM_CIP(x) ((x) << 1)
#define MINIMUM_CIP_SHIFT 1
#define MINIMUM_CIP_MASK 0x1fffffe
#define REFRESH_RATE_DIVISOR(x) ((x) << 25)
#define REFRESH_RATE_DIVISOR_SHIFT 25
#define REFRESH_RATE_DIVISOR_MASK (0x3 << 25)
#define ENABLE_FV_THROT (1 << 27)
#define ENABLE_FV_UPDATE (1 << 28)
#define TREND_SEL_MODE (1 << 29)
#define FORCE_TREND_SEL (1 << 30)
#define ENABLE_FV_THROT_IO (1 << 31)
#define FVTHROT_TARGET_REG 0x3004
#define TARGET_IDLE_COUNT(x) ((x) << 0)
#define TARGET_IDLE_COUNT_MASK 0xffffff
#define TARGET_IDLE_COUNT_SHIFT 0
#define FVTHROT_CB1 0x3008
#define FVTHROT_CB2 0x300c
#define FVTHROT_CB3 0x3010
#define FVTHROT_CB4 0x3014
#define FVTHROT_UTC0 0x3018
#define FVTHROT_UTC1 0x301c
#define FVTHROT_UTC2 0x3020
#define FVTHROT_UTC3 0x3024
#define FVTHROT_UTC4 0x3028
#define FVTHROT_DTC0 0x302c
#define FVTHROT_DTC1 0x3030
#define FVTHROT_DTC2 0x3034
#define FVTHROT_DTC3 0x3038
#define FVTHROT_DTC4 0x303c
#define FVTHROT_FBDIV_REG0 0x3040
#define MIN_FEEDBACK_DIV(x) ((x) << 0)
#define MIN_FEEDBACK_DIV_MASK 0xfff
#define MIN_FEEDBACK_DIV_SHIFT 0
#define MAX_FEEDBACK_DIV(x) ((x) << 12)
#define MAX_FEEDBACK_DIV_MASK (0xfff << 12)
#define MAX_FEEDBACK_DIV_SHIFT 12
#define FVTHROT_FBDIV_REG1 0x3044
#define MAX_FEEDBACK_STEP(x) ((x) << 0)
#define MAX_FEEDBACK_STEP_MASK 0xfff
#define MAX_FEEDBACK_STEP_SHIFT 0
#define STARTING_FEEDBACK_DIV(x) ((x) << 12)
#define STARTING_FEEDBACK_DIV_MASK (0xfff << 12)
#define STARTING_FEEDBACK_DIV_SHIFT 12
#define FORCE_FEEDBACK_DIV (1 << 24)
#define FVTHROT_FBDIV_REG2 0x3048
#define FORCED_FEEDBACK_DIV(x) ((x) << 0)
#define FORCED_FEEDBACK_DIV_MASK 0xfff
#define FORCED_FEEDBACK_DIV_SHIFT 0
#define FB_DIV_TIMER_VAL(x) ((x) << 12)
#define FB_DIV_TIMER_VAL_MASK (0xffff << 12)
#define FB_DIV_TIMER_VAL_SHIFT 12
#define FVTHROT_FB_US_REG0 0x304c
#define FVTHROT_FB_US_REG1 0x3050
#define FVTHROT_FB_DS_REG0 0x3054
#define FVTHROT_FB_DS_REG1 0x3058
#define FVTHROT_PWM_CTRL_REG0 0x305c
#define STARTING_PWM_HIGHTIME(x) ((x) << 0)
#define STARTING_PWM_HIGHTIME_MASK 0xfff
#define STARTING_PWM_HIGHTIME_SHIFT 0
#define NUMBER_OF_CYCLES_IN_PERIOD(x) ((x) << 12)
#define NUMBER_OF_CYCLES_IN_PERIOD_MASK (0xfff << 12)
#define NUMBER_OF_CYCLES_IN_PERIOD_SHIFT 12
#define FORCE_STARTING_PWM_HIGHTIME (1 << 24)
#define INVERT_PWM_WAVEFORM (1 << 25)
#define FVTHROT_PWM_CTRL_REG1 0x3060
#define MIN_PWM_HIGHTIME(x) ((x) << 0)
#define MIN_PWM_HIGHTIME_MASK 0xfff
#define MIN_PWM_HIGHTIME_SHIFT 0
#define MAX_PWM_HIGHTIME(x) ((x) << 12)
#define MAX_PWM_HIGHTIME_MASK (0xfff << 12)
#define MAX_PWM_HIGHTIME_SHIFT 12
#define FVTHROT_PWM_US_REG0 0x3064
#define FVTHROT_PWM_US_REG1 0x3068
#define FVTHROT_PWM_DS_REG0 0x306c
#define FVTHROT_PWM_DS_REG1 0x3070
#define FVTHROT_STATUS_REG0 0x3074
#define CURRENT_FEEDBACK_DIV_MASK 0xfff
#define CURRENT_FEEDBACK_DIV_SHIFT 0
#define FVTHROT_STATUS_REG1 0x3078
#define FVTHROT_STATUS_REG2 0x307c
#define CG_INTGFX_MISC 0x3080
#define FVTHROT_VBLANK_SEL (1 << 9)
#define FVTHROT_PWM_FEEDBACK_DIV_REG1 0x308c
#define RANGE0_PWM_FEEDBACK_DIV(x) ((x) << 0)
#define RANGE0_PWM_FEEDBACK_DIV_MASK 0xfff
#define RANGE0_PWM_FEEDBACK_DIV_SHIFT 0
#define RANGE_PWM_FEEDBACK_DIV_EN (1 << 12)
#define FVTHROT_PWM_FEEDBACK_DIV_REG2 0x3090
#define RANGE1_PWM_FEEDBACK_DIV(x) ((x) << 0)
#define RANGE1_PWM_FEEDBACK_DIV_MASK 0xfff
#define RANGE1_PWM_FEEDBACK_DIV_SHIFT 0
#define RANGE2_PWM_FEEDBACK_DIV(x) ((x) << 12)
#define RANGE2_PWM_FEEDBACK_DIV_MASK (0xfff << 12)
#define RANGE2_PWM_FEEDBACK_DIV_SHIFT 12
#define FVTHROT_PWM_FEEDBACK_DIV_REG3 0x3094
#define RANGE0_PWM(x) ((x) << 0)
#define RANGE0_PWM_MASK 0xfff
#define RANGE0_PWM_SHIFT 0
#define RANGE1_PWM(x) ((x) << 12)
#define RANGE1_PWM_MASK (0xfff << 12)
#define RANGE1_PWM_SHIFT 12
#define FVTHROT_PWM_FEEDBACK_DIV_REG4 0x3098
#define RANGE2_PWM(x) ((x) << 0)
#define RANGE2_PWM_MASK 0xfff
#define RANGE2_PWM_SHIFT 0
#define RANGE3_PWM(x) ((x) << 12)
#define RANGE3_PWM_MASK (0xfff << 12)
#define RANGE3_PWM_SHIFT 12
#define FVTHROT_SLOW_CLK_FEEDBACK_DIV_REG1 0x30ac
#define RANGE0_SLOW_CLK_FEEDBACK_DIV(x) ((x) << 0)
#define RANGE0_SLOW_CLK_FEEDBACK_DIV_MASK 0xfff
#define RANGE0_SLOW_CLK_FEEDBACK_DIV_SHIFT 0
#define RANGE_SLOW_CLK_FEEDBACK_DIV_EN (1 << 12)
#define GFX_MACRO_BYPASS_CNTL 0x30c0
#define SPLL_BYPASS_CNTL (1 << 0)
#define UPLL_BYPASS_CNTL (1 << 1)
#endif

View File

@ -937,13 +937,16 @@ struct rv515_watermark {
};
static void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
struct radeon_crtc *crtc,
struct rv515_watermark *wm)
struct radeon_crtc *crtc,
struct rv515_watermark *wm,
bool low)
{
struct drm_display_mode *mode = &crtc->base.mode;
fixed20_12 a, b, c;
fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
fixed20_12 sclk;
u32 selected_sclk;
if (!crtc->base.enabled) {
/* FIXME: wouldn't it better to set priority mark to maximum */
@ -951,6 +954,18 @@ static void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
return;
}
/* rv6xx, rv7xx */
if ((rdev->family >= CHIP_RV610) &&
(rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled)
selected_sclk = radeon_dpm_get_sclk(rdev, low);
else
selected_sclk = rdev->pm.current_sclk;
/* sclk in Mhz */
a.full = dfixed_const(100);
sclk.full = dfixed_const(selected_sclk);
sclk.full = dfixed_div(sclk, a);
if (crtc->vsc.full > dfixed_const(2))
wm->num_line_pair.full = dfixed_const(2);
else
@ -1016,7 +1031,7 @@ static void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
* sclk = system clock(Mhz)
*/
a.full = dfixed_const(600 * 1000);
chunk_time.full = dfixed_div(a, rdev->pm.sclk);
chunk_time.full = dfixed_div(a, sclk);
read_delay_latency.full = dfixed_const(1000);
/* Determine the worst case latency
@ -1077,17 +1092,147 @@ static void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
}
}
static void rv515_compute_mode_priority(struct radeon_device *rdev,
struct rv515_watermark *wm0,
struct rv515_watermark *wm1,
struct drm_display_mode *mode0,
struct drm_display_mode *mode1,
u32 *d1mode_priority_a_cnt,
u32 *d2mode_priority_a_cnt)
{
fixed20_12 priority_mark02, priority_mark12, fill_rate;
fixed20_12 a, b;
*d1mode_priority_a_cnt = MODE_PRIORITY_OFF;
*d2mode_priority_a_cnt = MODE_PRIORITY_OFF;
if (mode0 && mode1) {
if (dfixed_trunc(wm0->dbpp) > 64)
a.full = dfixed_div(wm0->dbpp, wm0->num_line_pair);
else
a.full = wm0->num_line_pair.full;
if (dfixed_trunc(wm1->dbpp) > 64)
b.full = dfixed_div(wm1->dbpp, wm1->num_line_pair);
else
b.full = wm1->num_line_pair.full;
a.full += b.full;
fill_rate.full = dfixed_div(wm0->sclk, a);
if (wm0->consumption_rate.full > fill_rate.full) {
b.full = wm0->consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm0->active_time);
a.full = dfixed_const(16);
b.full = dfixed_div(b, a);
a.full = dfixed_mul(wm0->worst_case_latency,
wm0->consumption_rate);
priority_mark02.full = a.full + b.full;
} else {
a.full = dfixed_mul(wm0->worst_case_latency,
wm0->consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark02.full = dfixed_div(a, b);
}
if (wm1->consumption_rate.full > fill_rate.full) {
b.full = wm1->consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm1->active_time);
a.full = dfixed_const(16);
b.full = dfixed_div(b, a);
a.full = dfixed_mul(wm1->worst_case_latency,
wm1->consumption_rate);
priority_mark12.full = a.full + b.full;
} else {
a.full = dfixed_mul(wm1->worst_case_latency,
wm1->consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark12.full = dfixed_div(a, b);
}
if (wm0->priority_mark.full > priority_mark02.full)
priority_mark02.full = wm0->priority_mark.full;
if (dfixed_trunc(priority_mark02) < 0)
priority_mark02.full = 0;
if (wm0->priority_mark_max.full > priority_mark02.full)
priority_mark02.full = wm0->priority_mark_max.full;
if (wm1->priority_mark.full > priority_mark12.full)
priority_mark12.full = wm1->priority_mark.full;
if (dfixed_trunc(priority_mark12) < 0)
priority_mark12.full = 0;
if (wm1->priority_mark_max.full > priority_mark12.full)
priority_mark12.full = wm1->priority_mark_max.full;
*d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);
*d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);
if (rdev->disp_priority == 2) {
*d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
*d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
}
} else if (mode0) {
if (dfixed_trunc(wm0->dbpp) > 64)
a.full = dfixed_div(wm0->dbpp, wm0->num_line_pair);
else
a.full = wm0->num_line_pair.full;
fill_rate.full = dfixed_div(wm0->sclk, a);
if (wm0->consumption_rate.full > fill_rate.full) {
b.full = wm0->consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm0->active_time);
a.full = dfixed_const(16);
b.full = dfixed_div(b, a);
a.full = dfixed_mul(wm0->worst_case_latency,
wm0->consumption_rate);
priority_mark02.full = a.full + b.full;
} else {
a.full = dfixed_mul(wm0->worst_case_latency,
wm0->consumption_rate);
b.full = dfixed_const(16);
priority_mark02.full = dfixed_div(a, b);
}
if (wm0->priority_mark.full > priority_mark02.full)
priority_mark02.full = wm0->priority_mark.full;
if (dfixed_trunc(priority_mark02) < 0)
priority_mark02.full = 0;
if (wm0->priority_mark_max.full > priority_mark02.full)
priority_mark02.full = wm0->priority_mark_max.full;
*d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);
if (rdev->disp_priority == 2)
*d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
} else if (mode1) {
if (dfixed_trunc(wm1->dbpp) > 64)
a.full = dfixed_div(wm1->dbpp, wm1->num_line_pair);
else
a.full = wm1->num_line_pair.full;
fill_rate.full = dfixed_div(wm1->sclk, a);
if (wm1->consumption_rate.full > fill_rate.full) {
b.full = wm1->consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm1->active_time);
a.full = dfixed_const(16);
b.full = dfixed_div(b, a);
a.full = dfixed_mul(wm1->worst_case_latency,
wm1->consumption_rate);
priority_mark12.full = a.full + b.full;
} else {
a.full = dfixed_mul(wm1->worst_case_latency,
wm1->consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark12.full = dfixed_div(a, b);
}
if (wm1->priority_mark.full > priority_mark12.full)
priority_mark12.full = wm1->priority_mark.full;
if (dfixed_trunc(priority_mark12) < 0)
priority_mark12.full = 0;
if (wm1->priority_mark_max.full > priority_mark12.full)
priority_mark12.full = wm1->priority_mark_max.full;
*d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);
if (rdev->disp_priority == 2)
*d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
}
}
void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
{
struct drm_display_mode *mode0 = NULL;
struct drm_display_mode *mode1 = NULL;
struct rv515_watermark wm0;
struct rv515_watermark wm1;
struct rv515_watermark wm0_high, wm0_low;
struct rv515_watermark wm1_high, wm1_low;
u32 tmp;
u32 d1mode_priority_a_cnt = MODE_PRIORITY_OFF;
u32 d2mode_priority_a_cnt = MODE_PRIORITY_OFF;
fixed20_12 priority_mark02, priority_mark12, fill_rate;
fixed20_12 a, b;
u32 d1mode_priority_a_cnt, d1mode_priority_b_cnt;
u32 d2mode_priority_a_cnt, d2mode_priority_b_cnt;
if (rdev->mode_info.crtcs[0]->base.enabled)
mode0 = &rdev->mode_info.crtcs[0]->base.mode;
@ -1095,134 +1240,29 @@ void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
mode1 = &rdev->mode_info.crtcs[1]->base.mode;
rs690_line_buffer_adjust(rdev, mode0, mode1);
rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0);
rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1);
rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0_high, false);
rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1_high, false);
tmp = wm0.lb_request_fifo_depth;
tmp |= wm1.lb_request_fifo_depth << 16;
rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0_low, false);
rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1_low, false);
tmp = wm0_high.lb_request_fifo_depth;
tmp |= wm1_high.lb_request_fifo_depth << 16;
WREG32(LB_MAX_REQ_OUTSTANDING, tmp);
if (mode0 && mode1) {
if (dfixed_trunc(wm0.dbpp) > 64)
a.full = dfixed_div(wm0.dbpp, wm0.num_line_pair);
else
a.full = wm0.num_line_pair.full;
if (dfixed_trunc(wm1.dbpp) > 64)
b.full = dfixed_div(wm1.dbpp, wm1.num_line_pair);
else
b.full = wm1.num_line_pair.full;
a.full += b.full;
fill_rate.full = dfixed_div(wm0.sclk, a);
if (wm0.consumption_rate.full > fill_rate.full) {
b.full = wm0.consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm0.active_time);
a.full = dfixed_const(16);
b.full = dfixed_div(b, a);
a.full = dfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
priority_mark02.full = a.full + b.full;
} else {
a.full = dfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark02.full = dfixed_div(a, b);
}
if (wm1.consumption_rate.full > fill_rate.full) {
b.full = wm1.consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm1.active_time);
a.full = dfixed_const(16);
b.full = dfixed_div(b, a);
a.full = dfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
priority_mark12.full = a.full + b.full;
} else {
a.full = dfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark12.full = dfixed_div(a, b);
}
if (wm0.priority_mark.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark.full;
if (dfixed_trunc(priority_mark02) < 0)
priority_mark02.full = 0;
if (wm0.priority_mark_max.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark_max.full;
if (wm1.priority_mark.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark.full;
if (dfixed_trunc(priority_mark12) < 0)
priority_mark12.full = 0;
if (wm1.priority_mark_max.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark_max.full;
d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);
d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);
if (rdev->disp_priority == 2) {
d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
}
} else if (mode0) {
if (dfixed_trunc(wm0.dbpp) > 64)
a.full = dfixed_div(wm0.dbpp, wm0.num_line_pair);
else
a.full = wm0.num_line_pair.full;
fill_rate.full = dfixed_div(wm0.sclk, a);
if (wm0.consumption_rate.full > fill_rate.full) {
b.full = wm0.consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm0.active_time);
a.full = dfixed_const(16);
b.full = dfixed_div(b, a);
a.full = dfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
priority_mark02.full = a.full + b.full;
} else {
a.full = dfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
b.full = dfixed_const(16);
priority_mark02.full = dfixed_div(a, b);
}
if (wm0.priority_mark.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark.full;
if (dfixed_trunc(priority_mark02) < 0)
priority_mark02.full = 0;
if (wm0.priority_mark_max.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark_max.full;
d1mode_priority_a_cnt = dfixed_trunc(priority_mark02);
if (rdev->disp_priority == 2)
d1mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
} else if (mode1) {
if (dfixed_trunc(wm1.dbpp) > 64)
a.full = dfixed_div(wm1.dbpp, wm1.num_line_pair);
else
a.full = wm1.num_line_pair.full;
fill_rate.full = dfixed_div(wm1.sclk, a);
if (wm1.consumption_rate.full > fill_rate.full) {
b.full = wm1.consumption_rate.full - fill_rate.full;
b.full = dfixed_mul(b, wm1.active_time);
a.full = dfixed_const(16);
b.full = dfixed_div(b, a);
a.full = dfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
priority_mark12.full = a.full + b.full;
} else {
a.full = dfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
b.full = dfixed_const(16 * 1000);
priority_mark12.full = dfixed_div(a, b);
}
if (wm1.priority_mark.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark.full;
if (dfixed_trunc(priority_mark12) < 0)
priority_mark12.full = 0;
if (wm1.priority_mark_max.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark_max.full;
d2mode_priority_a_cnt = dfixed_trunc(priority_mark12);
if (rdev->disp_priority == 2)
d2mode_priority_a_cnt |= MODE_PRIORITY_ALWAYS_ON;
}
rv515_compute_mode_priority(rdev,
&wm0_high, &wm1_high,
mode0, mode1,
&d1mode_priority_a_cnt, &d2mode_priority_a_cnt);
rv515_compute_mode_priority(rdev,
&wm0_low, &wm1_low,
mode0, mode1,
&d1mode_priority_b_cnt, &d2mode_priority_b_cnt);
WREG32(D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt);
WREG32(D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt);
WREG32(D1MODE_PRIORITY_B_CNT, d1mode_priority_b_cnt);
WREG32(D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt);
WREG32(D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt);
WREG32(D2MODE_PRIORITY_B_CNT, d2mode_priority_b_cnt);
}
void rv515_bandwidth_update(struct radeon_device *rdev)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,95 @@
/*
* Copyright 2011 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: Alex Deucher
*/
#ifndef __RV6XX_DPM_H__
#define __RV6XX_DPM_H__
#include "r600_dpm.h"
/* Represents a single SCLK step. */
struct rv6xx_sclk_stepping
{
u32 vco_frequency;
u32 post_divider;
};
struct rv6xx_pm_hw_state {
u32 sclks[R600_PM_NUMBER_OF_ACTIVITY_LEVELS];
u32 mclks[R600_PM_NUMBER_OF_MCLKS];
u16 vddc[R600_PM_NUMBER_OF_VOLTAGE_LEVELS];
bool backbias[R600_PM_NUMBER_OF_VOLTAGE_LEVELS];
bool pcie_gen2[R600_PM_NUMBER_OF_ACTIVITY_LEVELS];
u8 high_sclk_index;
u8 medium_sclk_index;
u8 low_sclk_index;
u8 high_mclk_index;
u8 medium_mclk_index;
u8 low_mclk_index;
u8 high_vddc_index;
u8 medium_vddc_index;
u8 low_vddc_index;
u8 rp[R600_PM_NUMBER_OF_ACTIVITY_LEVELS];
u8 lp[R600_PM_NUMBER_OF_ACTIVITY_LEVELS];
};
struct rv6xx_power_info {
/* flags */
bool voltage_control;
bool sclk_ss;
bool mclk_ss;
bool dynamic_ss;
bool dynamic_pcie_gen2;
bool thermal_protection;
bool display_gap;
bool gfx_clock_gating;
/* clk values */
u32 fb_div_scale;
u32 spll_ref_div;
u32 mpll_ref_div;
u32 bsu;
u32 bsp;
/* */
u32 active_auto_throttle_sources;
/* current power state */
u32 restricted_levels;
struct rv6xx_pm_hw_state hw;
};
struct rv6xx_pl {
u32 sclk;
u32 mclk;
u16 vddc;
u32 flags;
};
struct rv6xx_ps {
struct rv6xx_pl high;
struct rv6xx_pl medium;
struct rv6xx_pl low;
};
#define RV6XX_DEFAULT_VCLK_FREQ 40000 /* 10 khz */
#define RV6XX_DEFAULT_DCLK_FREQ 30000 /* 10 khz */
#endif

View File

@ -0,0 +1,246 @@
/*
* Copyright 2011 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.
*
*/
#ifndef RV6XXD_H
#define RV6XXD_H
/* RV6xx power management */
#define SPLL_CNTL_MODE 0x60c
# define SPLL_DIV_SYNC (1 << 5)
#define GENERAL_PWRMGT 0x618
# define GLOBAL_PWRMGT_EN (1 << 0)
# define STATIC_PM_EN (1 << 1)
# define MOBILE_SU (1 << 2)
# define THERMAL_PROTECTION_DIS (1 << 3)
# define THERMAL_PROTECTION_TYPE (1 << 4)
# define ENABLE_GEN2PCIE (1 << 5)
# define SW_GPIO_INDEX(x) ((x) << 6)
# define SW_GPIO_INDEX_MASK (3 << 6)
# define LOW_VOLT_D2_ACPI (1 << 8)
# define LOW_VOLT_D3_ACPI (1 << 9)
# define VOLT_PWRMGT_EN (1 << 10)
# define BACKBIAS_PAD_EN (1 << 16)
# define BACKBIAS_VALUE (1 << 17)
# define BACKBIAS_DPM_CNTL (1 << 18)
# define DYN_SPREAD_SPECTRUM_EN (1 << 21)
#define MCLK_PWRMGT_CNTL 0x624
# define MPLL_PWRMGT_OFF (1 << 0)
# define YCLK_TURNOFF (1 << 1)
# define MPLL_TURNOFF (1 << 2)
# define SU_MCLK_USE_BCLK (1 << 3)
# define DLL_READY (1 << 4)
# define MC_BUSY (1 << 5)
# define MC_INT_CNTL (1 << 7)
# define MRDCKA_SLEEP (1 << 8)
# define MRDCKB_SLEEP (1 << 9)
# define MRDCKC_SLEEP (1 << 10)
# define MRDCKD_SLEEP (1 << 11)
# define MRDCKE_SLEEP (1 << 12)
# define MRDCKF_SLEEP (1 << 13)
# define MRDCKG_SLEEP (1 << 14)
# define MRDCKH_SLEEP (1 << 15)
# define MRDCKA_RESET (1 << 16)
# define MRDCKB_RESET (1 << 17)
# define MRDCKC_RESET (1 << 18)
# define MRDCKD_RESET (1 << 19)
# define MRDCKE_RESET (1 << 20)
# define MRDCKF_RESET (1 << 21)
# define MRDCKG_RESET (1 << 22)
# define MRDCKH_RESET (1 << 23)
# define DLL_READY_READ (1 << 24)
# define USE_DISPLAY_GAP (1 << 25)
# define USE_DISPLAY_URGENT_NORMAL (1 << 26)
# define USE_DISPLAY_GAP_CTXSW (1 << 27)
# define MPLL_TURNOFF_D2 (1 << 28)
# define USE_DISPLAY_URGENT_CTXSW (1 << 29)
#define MPLL_FREQ_LEVEL_0 0x6e8
# define LEVEL0_MPLL_POST_DIV(x) ((x) << 0)
# define LEVEL0_MPLL_POST_DIV_MASK (0xff << 0)
# define LEVEL0_MPLL_FB_DIV(x) ((x) << 8)
# define LEVEL0_MPLL_FB_DIV_MASK (0xfff << 8)
# define LEVEL0_MPLL_REF_DIV(x) ((x) << 20)
# define LEVEL0_MPLL_REF_DIV_MASK (0x3f << 20)
# define LEVEL0_MPLL_DIV_EN (1 << 28)
# define LEVEL0_DLL_BYPASS (1 << 29)
# define LEVEL0_DLL_RESET (1 << 30)
#define VID_RT 0x6f8
# define VID_CRT(x) ((x) << 0)
# define VID_CRT_MASK (0x1fff << 0)
# define VID_CRTU(x) ((x) << 13)
# define VID_CRTU_MASK (7 << 13)
# define SSTU(x) ((x) << 16)
# define SSTU_MASK (7 << 16)
# define VID_SWT(x) ((x) << 19)
# define VID_SWT_MASK (0x1f << 19)
# define BRT(x) ((x) << 24)
# define BRT_MASK (0xff << 24)
#define TARGET_AND_CURRENT_PROFILE_INDEX 0x70c
# define TARGET_PROFILE_INDEX_MASK (3 << 0)
# define TARGET_PROFILE_INDEX_SHIFT 0
# define CURRENT_PROFILE_INDEX_MASK (3 << 2)
# define CURRENT_PROFILE_INDEX_SHIFT 2
# define DYN_PWR_ENTER_INDEX(x) ((x) << 4)
# define DYN_PWR_ENTER_INDEX_MASK (3 << 4)
# define DYN_PWR_ENTER_INDEX_SHIFT 4
# define CURR_MCLK_INDEX_MASK (3 << 6)
# define CURR_MCLK_INDEX_SHIFT 6
# define CURR_SCLK_INDEX_MASK (0x1f << 8)
# define CURR_SCLK_INDEX_SHIFT 8
# define CURR_VID_INDEX_MASK (3 << 13)
# define CURR_VID_INDEX_SHIFT 13
#define VID_UPPER_GPIO_CNTL 0x740
# define CTXSW_UPPER_GPIO_VALUES(x) ((x) << 0)
# define CTXSW_UPPER_GPIO_VALUES_MASK (7 << 0)
# define HIGH_UPPER_GPIO_VALUES(x) ((x) << 3)
# define HIGH_UPPER_GPIO_VALUES_MASK (7 << 3)
# define MEDIUM_UPPER_GPIO_VALUES(x) ((x) << 6)
# define MEDIUM_UPPER_GPIO_VALUES_MASK (7 << 6)
# define LOW_UPPER_GPIO_VALUES(x) ((x) << 9)
# define LOW_UPPER_GPIO_VALUES_MASK (7 << 9)
# define CTXSW_BACKBIAS_VALUE (1 << 12)
# define HIGH_BACKBIAS_VALUE (1 << 13)
# define MEDIUM_BACKBIAS_VALUE (1 << 14)
# define LOW_BACKBIAS_VALUE (1 << 15)
#define CG_DISPLAY_GAP_CNTL 0x7dc
# define DISP1_GAP(x) ((x) << 0)
# define DISP1_GAP_MASK (3 << 0)
# define DISP2_GAP(x) ((x) << 2)
# define DISP2_GAP_MASK (3 << 2)
# define VBI_TIMER_COUNT(x) ((x) << 4)
# define VBI_TIMER_COUNT_MASK (0x3fff << 4)
# define VBI_TIMER_UNIT(x) ((x) << 20)
# define VBI_TIMER_UNIT_MASK (7 << 20)
# define DISP1_GAP_MCHG(x) ((x) << 24)
# define DISP1_GAP_MCHG_MASK (3 << 24)
# define DISP2_GAP_MCHG(x) ((x) << 26)
# define DISP2_GAP_MCHG_MASK (3 << 26)
#define CG_THERMAL_CTRL 0x7f0
# define DPM_EVENT_SRC(x) ((x) << 0)
# define DPM_EVENT_SRC_MASK (7 << 0)
# define THERM_INC_CLK (1 << 3)
# define TOFFSET(x) ((x) << 4)
# define TOFFSET_MASK (0xff << 4)
# define DIG_THERM_DPM(x) ((x) << 12)
# define DIG_THERM_DPM_MASK (0xff << 12)
# define CTF_SEL(x) ((x) << 20)
# define CTF_SEL_MASK (7 << 20)
# define CTF_PAD_POLARITY (1 << 23)
# define CTF_PAD_EN (1 << 24)
#define CG_SPLL_SPREAD_SPECTRUM_LOW 0x820
# define SSEN (1 << 0)
# define CLKS(x) ((x) << 3)
# define CLKS_MASK (0xff << 3)
# define CLKS_SHIFT 3
# define CLKV(x) ((x) << 11)
# define CLKV_MASK (0x7ff << 11)
# define CLKV_SHIFT 11
#define CG_MPLL_SPREAD_SPECTRUM 0x830
#define CITF_CNTL 0x200c
# define BLACKOUT_RD (1 << 0)
# define BLACKOUT_WR (1 << 1)
#define RAMCFG 0x2408
#define NOOFBANK_SHIFT 0
#define NOOFBANK_MASK 0x00000001
#define NOOFRANK_SHIFT 1
#define NOOFRANK_MASK 0x00000002
#define NOOFROWS_SHIFT 2
#define NOOFROWS_MASK 0x0000001C
#define NOOFCOLS_SHIFT 5
#define NOOFCOLS_MASK 0x00000060
#define CHANSIZE_SHIFT 7
#define CHANSIZE_MASK 0x00000080
#define BURSTLENGTH_SHIFT 8
#define BURSTLENGTH_MASK 0x00000100
#define CHANSIZE_OVERRIDE (1 << 10)
#define SQM_RATIO 0x2424
# define STATE0(x) ((x) << 0)
# define STATE0_MASK (0xff << 0)
# define STATE1(x) ((x) << 8)
# define STATE1_MASK (0xff << 8)
# define STATE2(x) ((x) << 16)
# define STATE2_MASK (0xff << 16)
# define STATE3(x) ((x) << 24)
# define STATE3_MASK (0xff << 24)
#define ARB_RFSH_CNTL 0x2460
# define ENABLE (1 << 0)
#define ARB_RFSH_RATE 0x2464
# define POWERMODE0(x) ((x) << 0)
# define POWERMODE0_MASK (0xff << 0)
# define POWERMODE1(x) ((x) << 8)
# define POWERMODE1_MASK (0xff << 8)
# define POWERMODE2(x) ((x) << 16)
# define POWERMODE2_MASK (0xff << 16)
# define POWERMODE3(x) ((x) << 24)
# define POWERMODE3_MASK (0xff << 24)
#define MC_SEQ_DRAM 0x2608
# define CKE_DYN (1 << 12)
#define MC_SEQ_CMD 0x26c4
#define MC_SEQ_RESERVE_S 0x2890
#define MC_SEQ_RESERVE_M 0x2894
#define LVTMA_DATA_SYNCHRONIZATION 0x7adc
# define LVTMA_PFREQCHG (1 << 8)
#define DCE3_LVTMA_DATA_SYNCHRONIZATION 0x7f98
/* PCIE indirect regs */
#define PCIE_P_CNTL 0x40
# define P_PLL_PWRDN_IN_L1L23 (1 << 3)
# define P_PLL_BUF_PDNB (1 << 4)
# define P_PLL_PDNB (1 << 9)
# define P_ALLOW_PRX_FRONTEND_SHUTOFF (1 << 12)
/* PCIE PORT indirect regs */
#define PCIE_LC_CNTL 0xa0
# define LC_L0S_INACTIVITY(x) ((x) << 8)
# define LC_L0S_INACTIVITY_MASK (0xf << 8)
# define LC_L0S_INACTIVITY_SHIFT 8
# define LC_L1_INACTIVITY(x) ((x) << 12)
# define LC_L1_INACTIVITY_MASK (0xf << 12)
# define LC_L1_INACTIVITY_SHIFT 12
# define LC_PMI_TO_L1_DIS (1 << 16)
# define LC_ASPM_TO_L1_DIS (1 << 24)
#define PCIE_LC_SPEED_CNTL 0xa4
# define LC_GEN2_EN (1 << 0)
# define LC_INITIATE_LINK_SPEED_CHANGE (1 << 7)
# define LC_CURRENT_DATA_RATE (1 << 11)
# define LC_HW_VOLTAGE_IF_CONTROL(x) ((x) << 12)
# define LC_HW_VOLTAGE_IF_CONTROL_MASK (3 << 12)
# define LC_HW_VOLTAGE_IF_CONTROL_SHIFT 12
# define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 23)
# define LC_OTHER_SIDE_SUPPORTS_GEN2 (1 << 24)
#endif

View File

@ -0,0 +1,508 @@
/*
* Copyright 2011 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: Alex Deucher
*/
#include "drmP.h"
#include "radeon.h"
#include "rv730d.h"
#include "r600_dpm.h"
#include "rv770_dpm.h"
#include "atom.h"
#define MC_CG_ARB_FREQ_F0 0x0a
#define MC_CG_ARB_FREQ_F1 0x0b
#define MC_CG_ARB_FREQ_F2 0x0c
#define MC_CG_ARB_FREQ_F3 0x0d
struct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps);
struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev);
int rv730_populate_sclk_value(struct radeon_device *rdev,
u32 engine_clock,
RV770_SMC_SCLK_VALUE *sclk)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
struct atom_clock_dividers dividers;
u32 spll_func_cntl = pi->clk_regs.rv730.cg_spll_func_cntl;
u32 spll_func_cntl_2 = pi->clk_regs.rv730.cg_spll_func_cntl_2;
u32 spll_func_cntl_3 = pi->clk_regs.rv730.cg_spll_func_cntl_3;
u32 cg_spll_spread_spectrum = pi->clk_regs.rv730.cg_spll_spread_spectrum;
u32 cg_spll_spread_spectrum_2 = pi->clk_regs.rv730.cg_spll_spread_spectrum_2;
u64 tmp;
u32 reference_clock = rdev->clock.spll.reference_freq;
u32 reference_divider, post_divider;
u32 fbdiv;
int ret;
ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
engine_clock, false, &dividers);
if (ret)
return ret;
reference_divider = 1 + dividers.ref_div;
if (dividers.enable_post_div)
post_divider = ((dividers.post_div >> 4) & 0xf) +
(dividers.post_div & 0xf) + 2;
else
post_divider = 1;
tmp = (u64) engine_clock * reference_divider * post_divider * 16384;
do_div(tmp, reference_clock);
fbdiv = (u32) tmp;
/* set up registers */
if (dividers.enable_post_div)
spll_func_cntl |= SPLL_DIVEN;
else
spll_func_cntl &= ~SPLL_DIVEN;
spll_func_cntl &= ~(SPLL_HILEN_MASK | SPLL_LOLEN_MASK | SPLL_REF_DIV_MASK);
spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div);
spll_func_cntl |= SPLL_HILEN((dividers.post_div >> 4) & 0xf);
spll_func_cntl |= SPLL_LOLEN(dividers.post_div & 0xf);
spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
spll_func_cntl_2 |= SCLK_MUX_SEL(2);
spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK;
spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv);
spll_func_cntl_3 |= SPLL_DITHEN;
if (pi->sclk_ss) {
struct radeon_atom_ss ss;
u32 vco_freq = engine_clock * post_divider;
if (radeon_atombios_get_asic_ss_info(rdev, &ss,
ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
u32 clk_v = ss.percentage * fbdiv / (clk_s * 10000);
cg_spll_spread_spectrum &= ~CLK_S_MASK;
cg_spll_spread_spectrum |= CLK_S(clk_s);
cg_spll_spread_spectrum |= SSEN;
cg_spll_spread_spectrum_2 &= ~CLK_V_MASK;
cg_spll_spread_spectrum_2 |= CLK_V(clk_v);
}
}
sclk->sclk_value = cpu_to_be32(engine_clock);
sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(cg_spll_spread_spectrum);
sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(cg_spll_spread_spectrum_2);
return 0;
}
int rv730_populate_mclk_value(struct radeon_device *rdev,
u32 engine_clock, u32 memory_clock,
LPRV7XX_SMC_MCLK_VALUE mclk)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
u32 mclk_pwrmgt_cntl = pi->clk_regs.rv730.mclk_pwrmgt_cntl;
u32 dll_cntl = pi->clk_regs.rv730.dll_cntl;
u32 mpll_func_cntl = pi->clk_regs.rv730.mpll_func_cntl;
u32 mpll_func_cntl_2 = pi->clk_regs.rv730.mpll_func_cntl2;
u32 mpll_func_cntl_3 = pi->clk_regs.rv730.mpll_func_cntl3;
u32 mpll_ss = pi->clk_regs.rv730.mpll_ss;
u32 mpll_ss2 = pi->clk_regs.rv730.mpll_ss2;
struct atom_clock_dividers dividers;
u32 post_divider, reference_divider;
int ret;
ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM,
memory_clock, false, &dividers);
if (ret)
return ret;
reference_divider = dividers.ref_div + 1;
if (dividers.enable_post_div)
post_divider = ((dividers.post_div >> 4) & 0xf) +
(dividers.post_div & 0xf) + 2;
else
post_divider = 1;
/* setup the registers */
if (dividers.enable_post_div)
mpll_func_cntl |= MPLL_DIVEN;
else
mpll_func_cntl &= ~MPLL_DIVEN;
mpll_func_cntl &= ~(MPLL_REF_DIV_MASK | MPLL_HILEN_MASK | MPLL_LOLEN_MASK);
mpll_func_cntl |= MPLL_REF_DIV(dividers.ref_div);
mpll_func_cntl |= MPLL_HILEN((dividers.post_div >> 4) & 0xf);
mpll_func_cntl |= MPLL_LOLEN(dividers.post_div & 0xf);
mpll_func_cntl_3 &= ~MPLL_FB_DIV_MASK;
mpll_func_cntl_3 |= MPLL_FB_DIV(dividers.fb_div);
if (dividers.enable_dithen)
mpll_func_cntl_3 |= MPLL_DITHEN;
else
mpll_func_cntl_3 &= ~MPLL_DITHEN;
if (pi->mclk_ss) {
struct radeon_atom_ss ss;
u32 vco_freq = memory_clock * post_divider;
if (radeon_atombios_get_asic_ss_info(rdev, &ss,
ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
u32 reference_clock = rdev->clock.mpll.reference_freq;
u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
u32 clk_v = ss.percentage * dividers.fb_div / (clk_s * 10000);
mpll_ss &= ~CLK_S_MASK;
mpll_ss |= CLK_S(clk_s);
mpll_ss |= SSEN;
mpll_ss2 &= ~CLK_V_MASK;
mpll_ss |= CLK_V(clk_v);
}
}
mclk->mclk730.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
mclk->mclk730.vDLL_CNTL = cpu_to_be32(dll_cntl);
mclk->mclk730.mclk_value = cpu_to_be32(memory_clock);
mclk->mclk730.vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl);
mclk->mclk730.vMPLL_FUNC_CNTL2 = cpu_to_be32(mpll_func_cntl_2);
mclk->mclk730.vMPLL_FUNC_CNTL3 = cpu_to_be32(mpll_func_cntl_3);
mclk->mclk730.vMPLL_SS = cpu_to_be32(mpll_ss);
mclk->mclk730.vMPLL_SS2 = cpu_to_be32(mpll_ss2);
return 0;
}
void rv730_read_clock_registers(struct radeon_device *rdev)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
pi->clk_regs.rv730.cg_spll_func_cntl =
RREG32(CG_SPLL_FUNC_CNTL);
pi->clk_regs.rv730.cg_spll_func_cntl_2 =
RREG32(CG_SPLL_FUNC_CNTL_2);
pi->clk_regs.rv730.cg_spll_func_cntl_3 =
RREG32(CG_SPLL_FUNC_CNTL_3);
pi->clk_regs.rv730.cg_spll_spread_spectrum =
RREG32(CG_SPLL_SPREAD_SPECTRUM);
pi->clk_regs.rv730.cg_spll_spread_spectrum_2 =
RREG32(CG_SPLL_SPREAD_SPECTRUM_2);
pi->clk_regs.rv730.mclk_pwrmgt_cntl =
RREG32(TCI_MCLK_PWRMGT_CNTL);
pi->clk_regs.rv730.dll_cntl =
RREG32(TCI_DLL_CNTL);
pi->clk_regs.rv730.mpll_func_cntl =
RREG32(CG_MPLL_FUNC_CNTL);
pi->clk_regs.rv730.mpll_func_cntl2 =
RREG32(CG_MPLL_FUNC_CNTL_2);
pi->clk_regs.rv730.mpll_func_cntl3 =
RREG32(CG_MPLL_FUNC_CNTL_3);
pi->clk_regs.rv730.mpll_ss =
RREG32(CG_TCI_MPLL_SPREAD_SPECTRUM);
pi->clk_regs.rv730.mpll_ss2 =
RREG32(CG_TCI_MPLL_SPREAD_SPECTRUM_2);
}
int rv730_populate_smc_acpi_state(struct radeon_device *rdev,
RV770_SMC_STATETABLE *table)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
u32 mpll_func_cntl = 0;
u32 mpll_func_cntl_2 = 0 ;
u32 mpll_func_cntl_3 = 0;
u32 mclk_pwrmgt_cntl;
u32 dll_cntl;
u32 spll_func_cntl;
u32 spll_func_cntl_2;
u32 spll_func_cntl_3;
table->ACPIState = table->initialState;
table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;
if (pi->acpi_vddc) {
rv770_populate_vddc_value(rdev, pi->acpi_vddc,
&table->ACPIState.levels[0].vddc);
table->ACPIState.levels[0].gen2PCIE = pi->pcie_gen2 ?
pi->acpi_pcie_gen2 : 0;
table->ACPIState.levels[0].gen2XSP =
pi->acpi_pcie_gen2;
} else {
rv770_populate_vddc_value(rdev, pi->min_vddc_in_table,
&table->ACPIState.levels[0].vddc);
table->ACPIState.levels[0].gen2PCIE = 0;
}
mpll_func_cntl = pi->clk_regs.rv730.mpll_func_cntl;
mpll_func_cntl_2 = pi->clk_regs.rv730.mpll_func_cntl2;
mpll_func_cntl_3 = pi->clk_regs.rv730.mpll_func_cntl3;
mpll_func_cntl |= MPLL_RESET | MPLL_BYPASS_EN;
mpll_func_cntl &= ~MPLL_SLEEP;
mpll_func_cntl_2 &= ~MCLK_MUX_SEL_MASK;
mpll_func_cntl_2 |= MCLK_MUX_SEL(1);
mclk_pwrmgt_cntl = (MRDCKA_RESET |
MRDCKB_RESET |
MRDCKC_RESET |
MRDCKD_RESET |
MRDCKE_RESET |
MRDCKF_RESET |
MRDCKG_RESET |
MRDCKH_RESET |
MRDCKA_SLEEP |
MRDCKB_SLEEP |
MRDCKC_SLEEP |
MRDCKD_SLEEP |
MRDCKE_SLEEP |
MRDCKF_SLEEP |
MRDCKG_SLEEP |
MRDCKH_SLEEP);
dll_cntl = 0xff000000;
spll_func_cntl = pi->clk_regs.rv730.cg_spll_func_cntl;
spll_func_cntl_2 = pi->clk_regs.rv730.cg_spll_func_cntl_2;
spll_func_cntl_3 = pi->clk_regs.rv730.cg_spll_func_cntl_3;
spll_func_cntl |= SPLL_RESET | SPLL_BYPASS_EN;
spll_func_cntl &= ~SPLL_SLEEP;
spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
spll_func_cntl_2 |= SCLK_MUX_SEL(4);
table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl);
table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL2 = cpu_to_be32(mpll_func_cntl_2);
table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL3 = cpu_to_be32(mpll_func_cntl_3);
table->ACPIState.levels[0].mclk.mclk730.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
table->ACPIState.levels[0].mclk.mclk730.vDLL_CNTL = cpu_to_be32(dll_cntl);
table->ACPIState.levels[0].mclk.mclk730.mclk_value = 0;
table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
table->ACPIState.levels[0].sclk.sclk_value = 0;
rv770_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd);
table->ACPIState.levels[1] = table->ACPIState.levels[0];
table->ACPIState.levels[2] = table->ACPIState.levels[0];
return 0;
}
int rv730_populate_smc_initial_state(struct radeon_device *rdev,
struct radeon_ps *radeon_state,
RV770_SMC_STATETABLE *table)
{
struct rv7xx_ps *initial_state = rv770_get_ps(radeon_state);
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
u32 a_t;
table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL =
cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl);
table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL2 =
cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl2);
table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL3 =
cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl3);
table->initialState.levels[0].mclk.mclk730.vMCLK_PWRMGT_CNTL =
cpu_to_be32(pi->clk_regs.rv730.mclk_pwrmgt_cntl);
table->initialState.levels[0].mclk.mclk730.vDLL_CNTL =
cpu_to_be32(pi->clk_regs.rv730.dll_cntl);
table->initialState.levels[0].mclk.mclk730.vMPLL_SS =
cpu_to_be32(pi->clk_regs.rv730.mpll_ss);
table->initialState.levels[0].mclk.mclk730.vMPLL_SS2 =
cpu_to_be32(pi->clk_regs.rv730.mpll_ss2);
table->initialState.levels[0].mclk.mclk730.mclk_value =
cpu_to_be32(initial_state->low.mclk);
table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL =
cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl);
table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 =
cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl_2);
table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 =
cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl_3);
table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM =
cpu_to_be32(pi->clk_regs.rv730.cg_spll_spread_spectrum);
table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 =
cpu_to_be32(pi->clk_regs.rv730.cg_spll_spread_spectrum_2);
table->initialState.levels[0].sclk.sclk_value =
cpu_to_be32(initial_state->low.sclk);
table->initialState.levels[0].arbValue = MC_CG_ARB_FREQ_F0;
table->initialState.levels[0].seqValue =
rv770_get_seq_value(rdev, &initial_state->low);
rv770_populate_vddc_value(rdev,
initial_state->low.vddc,
&table->initialState.levels[0].vddc);
rv770_populate_initial_mvdd_value(rdev,
&table->initialState.levels[0].mvdd);
a_t = CG_R(0xffff) | CG_L(0);
table->initialState.levels[0].aT = cpu_to_be32(a_t);
table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp);
if (pi->boot_in_gen2)
table->initialState.levels[0].gen2PCIE = 1;
else
table->initialState.levels[0].gen2PCIE = 0;
if (initial_state->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2)
table->initialState.levels[0].gen2XSP = 1;
else
table->initialState.levels[0].gen2XSP = 0;
table->initialState.levels[1] = table->initialState.levels[0];
table->initialState.levels[2] = table->initialState.levels[0];
table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC;
return 0;
}
void rv730_program_memory_timing_parameters(struct radeon_device *rdev,
struct radeon_ps *radeon_state)
{
struct rv7xx_ps *state = rv770_get_ps(radeon_state);
u32 arb_refresh_rate = 0;
u32 dram_timing = 0;
u32 dram_timing2 = 0;
u32 old_dram_timing = 0;
u32 old_dram_timing2 = 0;
arb_refresh_rate = RREG32(MC_ARB_RFSH_RATE) &
~(POWERMODE1_MASK | POWERMODE2_MASK | POWERMODE3_MASK);
arb_refresh_rate |=
(POWERMODE1(rv770_calculate_memory_refresh_rate(rdev, state->low.sclk)) |
POWERMODE2(rv770_calculate_memory_refresh_rate(rdev, state->medium.sclk)) |
POWERMODE3(rv770_calculate_memory_refresh_rate(rdev, state->high.sclk)));
WREG32(MC_ARB_RFSH_RATE, arb_refresh_rate);
/* save the boot dram timings */
old_dram_timing = RREG32(MC_ARB_DRAM_TIMING);
old_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
radeon_atom_set_engine_dram_timings(rdev,
state->high.sclk,
state->high.mclk);
dram_timing = RREG32(MC_ARB_DRAM_TIMING);
dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
WREG32(MC_ARB_DRAM_TIMING_3, dram_timing);
WREG32(MC_ARB_DRAM_TIMING2_3, dram_timing2);
radeon_atom_set_engine_dram_timings(rdev,
state->medium.sclk,
state->medium.mclk);
dram_timing = RREG32(MC_ARB_DRAM_TIMING);
dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
WREG32(MC_ARB_DRAM_TIMING_2, dram_timing);
WREG32(MC_ARB_DRAM_TIMING2_2, dram_timing2);
radeon_atom_set_engine_dram_timings(rdev,
state->low.sclk,
state->low.mclk);
dram_timing = RREG32(MC_ARB_DRAM_TIMING);
dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
WREG32(MC_ARB_DRAM_TIMING_1, dram_timing);
WREG32(MC_ARB_DRAM_TIMING2_1, dram_timing2);
/* restore the boot dram timings */
WREG32(MC_ARB_DRAM_TIMING, old_dram_timing);
WREG32(MC_ARB_DRAM_TIMING2, old_dram_timing2);
}
void rv730_start_dpm(struct radeon_device *rdev)
{
WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF);
WREG32_P(TCI_MCLK_PWRMGT_CNTL, 0, ~MPLL_PWRMGT_OFF);
WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
}
void rv730_stop_dpm(struct radeon_device *rdev)
{
PPSMC_Result result;
result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_TwoLevelsDisabled);
if (result != PPSMC_Result_OK)
DRM_ERROR("Could not force DPM to low\n");
WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN);
WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF);
WREG32_P(TCI_MCLK_PWRMGT_CNTL, MPLL_PWRMGT_OFF, ~MPLL_PWRMGT_OFF);
}
void rv730_program_dcodt(struct radeon_device *rdev, bool use_dcodt)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
u32 i = use_dcodt ? 0 : 1;
u32 mc4_io_pad_cntl;
mc4_io_pad_cntl = RREG32(MC4_IO_DQ_PAD_CNTL_D0_I0);
mc4_io_pad_cntl &= 0xFFFFFF00;
mc4_io_pad_cntl |= pi->odt_value_0[i];
WREG32(MC4_IO_DQ_PAD_CNTL_D0_I0, mc4_io_pad_cntl);
WREG32(MC4_IO_DQ_PAD_CNTL_D0_I1, mc4_io_pad_cntl);
mc4_io_pad_cntl = RREG32(MC4_IO_QS_PAD_CNTL_D0_I0);
mc4_io_pad_cntl &= 0xFFFFFF00;
mc4_io_pad_cntl |= pi->odt_value_1[i];
WREG32(MC4_IO_QS_PAD_CNTL_D0_I0, mc4_io_pad_cntl);
WREG32(MC4_IO_QS_PAD_CNTL_D0_I1, mc4_io_pad_cntl);
}
void rv730_get_odt_values(struct radeon_device *rdev)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
u32 mc4_io_pad_cntl;
pi->odt_value_0[0] = (u8)0;
pi->odt_value_1[0] = (u8)0x80;
mc4_io_pad_cntl = RREG32(MC4_IO_DQ_PAD_CNTL_D0_I0);
pi->odt_value_0[1] = (u8)(mc4_io_pad_cntl & 0xff);
mc4_io_pad_cntl = RREG32(MC4_IO_QS_PAD_CNTL_D0_I0);
pi->odt_value_1[1] = (u8)(mc4_io_pad_cntl & 0xff);
}

View File

@ -0,0 +1,165 @@
/*
* Copyright 2011 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.
*
*/
#ifndef RV730_H
#define RV730_H
#define CG_SPLL_FUNC_CNTL 0x600
#define SPLL_RESET (1 << 0)
#define SPLL_SLEEP (1 << 1)
#define SPLL_DIVEN (1 << 2)
#define SPLL_BYPASS_EN (1 << 3)
#define SPLL_REF_DIV(x) ((x) << 4)
#define SPLL_REF_DIV_MASK (0x3f << 4)
#define SPLL_HILEN(x) ((x) << 12)
#define SPLL_HILEN_MASK (0xf << 12)
#define SPLL_LOLEN(x) ((x) << 16)
#define SPLL_LOLEN_MASK (0xf << 16)
#define CG_SPLL_FUNC_CNTL_2 0x604
#define SCLK_MUX_SEL(x) ((x) << 0)
#define SCLK_MUX_SEL_MASK (0x1ff << 0)
#define CG_SPLL_FUNC_CNTL_3 0x608
#define SPLL_FB_DIV(x) ((x) << 0)
#define SPLL_FB_DIV_MASK (0x3ffffff << 0)
#define SPLL_DITHEN (1 << 28)
#define CG_MPLL_FUNC_CNTL 0x624
#define MPLL_RESET (1 << 0)
#define MPLL_SLEEP (1 << 1)
#define MPLL_DIVEN (1 << 2)
#define MPLL_BYPASS_EN (1 << 3)
#define MPLL_REF_DIV(x) ((x) << 4)
#define MPLL_REF_DIV_MASK (0x3f << 4)
#define MPLL_HILEN(x) ((x) << 12)
#define MPLL_HILEN_MASK (0xf << 12)
#define MPLL_LOLEN(x) ((x) << 16)
#define MPLL_LOLEN_MASK (0xf << 16)
#define CG_MPLL_FUNC_CNTL_2 0x628
#define MCLK_MUX_SEL(x) ((x) << 0)
#define MCLK_MUX_SEL_MASK (0x1ff << 0)
#define CG_MPLL_FUNC_CNTL_3 0x62c
#define MPLL_FB_DIV(x) ((x) << 0)
#define MPLL_FB_DIV_MASK (0x3ffffff << 0)
#define MPLL_DITHEN (1 << 28)
#define CG_TCI_MPLL_SPREAD_SPECTRUM 0x634
#define CG_TCI_MPLL_SPREAD_SPECTRUM_2 0x638
#define GENERAL_PWRMGT 0x63c
# define GLOBAL_PWRMGT_EN (1 << 0)
# define STATIC_PM_EN (1 << 1)
# define THERMAL_PROTECTION_DIS (1 << 2)
# define THERMAL_PROTECTION_TYPE (1 << 3)
# define ENABLE_GEN2PCIE (1 << 4)
# define ENABLE_GEN2XSP (1 << 5)
# define SW_SMIO_INDEX(x) ((x) << 6)
# define SW_SMIO_INDEX_MASK (3 << 6)
# define LOW_VOLT_D2_ACPI (1 << 8)
# define LOW_VOLT_D3_ACPI (1 << 9)
# define VOLT_PWRMGT_EN (1 << 10)
# define BACKBIAS_PAD_EN (1 << 18)
# define BACKBIAS_VALUE (1 << 19)
# define DYN_SPREAD_SPECTRUM_EN (1 << 23)
# define AC_DC_SW (1 << 24)
#define SCLK_PWRMGT_CNTL 0x644
# define SCLK_PWRMGT_OFF (1 << 0)
# define SCLK_LOW_D1 (1 << 1)
# define FIR_RESET (1 << 4)
# define FIR_FORCE_TREND_SEL (1 << 5)
# define FIR_TREND_MODE (1 << 6)
# define DYN_GFX_CLK_OFF_EN (1 << 7)
# define GFX_CLK_FORCE_ON (1 << 8)
# define GFX_CLK_REQUEST_OFF (1 << 9)
# define GFX_CLK_FORCE_OFF (1 << 10)
# define GFX_CLK_OFF_ACPI_D1 (1 << 11)
# define GFX_CLK_OFF_ACPI_D2 (1 << 12)
# define GFX_CLK_OFF_ACPI_D3 (1 << 13)
#define TCI_MCLK_PWRMGT_CNTL 0x648
# define MPLL_PWRMGT_OFF (1 << 5)
# define DLL_READY (1 << 6)
# define MC_INT_CNTL (1 << 7)
# define MRDCKA_SLEEP (1 << 8)
# define MRDCKB_SLEEP (1 << 9)
# define MRDCKC_SLEEP (1 << 10)
# define MRDCKD_SLEEP (1 << 11)
# define MRDCKE_SLEEP (1 << 12)
# define MRDCKF_SLEEP (1 << 13)
# define MRDCKG_SLEEP (1 << 14)
# define MRDCKH_SLEEP (1 << 15)
# define MRDCKA_RESET (1 << 16)
# define MRDCKB_RESET (1 << 17)
# define MRDCKC_RESET (1 << 18)
# define MRDCKD_RESET (1 << 19)
# define MRDCKE_RESET (1 << 20)
# define MRDCKF_RESET (1 << 21)
# define MRDCKG_RESET (1 << 22)
# define MRDCKH_RESET (1 << 23)
# define DLL_READY_READ (1 << 24)
# define USE_DISPLAY_GAP (1 << 25)
# define USE_DISPLAY_URGENT_NORMAL (1 << 26)
# define MPLL_TURNOFF_D2 (1 << 28)
#define TCI_DLL_CNTL 0x64c
#define CG_PG_CNTL 0x858
# define PWRGATE_ENABLE (1 << 0)
#define CG_AT 0x6d4
#define CG_R(x) ((x) << 0)
#define CG_R_MASK (0xffff << 0)
#define CG_L(x) ((x) << 16)
#define CG_L_MASK (0xffff << 16)
#define CG_SPLL_SPREAD_SPECTRUM 0x790
#define SSEN (1 << 0)
#define CLK_S(x) ((x) << 4)
#define CLK_S_MASK (0xfff << 4)
#define CG_SPLL_SPREAD_SPECTRUM_2 0x794
#define CLK_V(x) ((x) << 0)
#define CLK_V_MASK (0x3ffffff << 0)
#define MC_ARB_DRAM_TIMING 0x2774
#define MC_ARB_DRAM_TIMING2 0x2778
#define MC_ARB_RFSH_RATE 0x27b0
#define POWERMODE0(x) ((x) << 0)
#define POWERMODE0_MASK (0xff << 0)
#define POWERMODE1(x) ((x) << 8)
#define POWERMODE1_MASK (0xff << 8)
#define POWERMODE2(x) ((x) << 16)
#define POWERMODE2_MASK (0xff << 16)
#define POWERMODE3(x) ((x) << 24)
#define POWERMODE3_MASK (0xff << 24)
#define MC_ARB_DRAM_TIMING_1 0x27f0
#define MC_ARB_DRAM_TIMING_2 0x27f4
#define MC_ARB_DRAM_TIMING_3 0x27f8
#define MC_ARB_DRAM_TIMING2_1 0x27fc
#define MC_ARB_DRAM_TIMING2_2 0x2800
#define MC_ARB_DRAM_TIMING2_3 0x2804
#define MC4_IO_DQ_PAD_CNTL_D0_I0 0x2978
#define MC4_IO_DQ_PAD_CNTL_D0_I1 0x297c
#define MC4_IO_QS_PAD_CNTL_D0_I0 0x2980
#define MC4_IO_QS_PAD_CNTL_D0_I1 0x2984
#endif

View File

@ -0,0 +1,416 @@
/*
* Copyright 2011 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: Alex Deucher
*/
#include "drmP.h"
#include "radeon.h"
#include "rv740d.h"
#include "r600_dpm.h"
#include "rv770_dpm.h"
#include "atom.h"
struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev);
u32 rv740_get_decoded_reference_divider(u32 encoded_ref)
{
u32 ref = 0;
switch (encoded_ref) {
case 0:
ref = 1;
break;
case 16:
ref = 2;
break;
case 17:
ref = 3;
break;
case 18:
ref = 2;
break;
case 19:
ref = 3;
break;
case 20:
ref = 4;
break;
case 21:
ref = 5;
break;
default:
DRM_ERROR("Invalid encoded Reference Divider\n");
ref = 0;
break;
}
return ref;
}
struct dll_speed_setting {
u16 min;
u16 max;
u32 dll_speed;
};
static struct dll_speed_setting dll_speed_table[16] =
{
{ 270, 320, 0x0f },
{ 240, 270, 0x0e },
{ 200, 240, 0x0d },
{ 180, 200, 0x0c },
{ 160, 180, 0x0b },
{ 140, 160, 0x0a },
{ 120, 140, 0x09 },
{ 110, 120, 0x08 },
{ 95, 110, 0x07 },
{ 85, 95, 0x06 },
{ 78, 85, 0x05 },
{ 70, 78, 0x04 },
{ 65, 70, 0x03 },
{ 60, 65, 0x02 },
{ 42, 60, 0x01 },
{ 00, 42, 0x00 }
};
u32 rv740_get_dll_speed(bool is_gddr5, u32 memory_clock)
{
int i;
u32 factor;
u16 data_rate;
if (is_gddr5)
factor = 4;
else
factor = 2;
data_rate = (u16)(memory_clock * factor / 1000);
if (data_rate < dll_speed_table[0].max) {
for (i = 0; i < 16; i++) {
if (data_rate > dll_speed_table[i].min &&
data_rate <= dll_speed_table[i].max)
return dll_speed_table[i].dll_speed;
}
}
DRM_DEBUG_KMS("Target MCLK greater than largest MCLK in DLL speed table\n");
return 0x0f;
}
int rv740_populate_sclk_value(struct radeon_device *rdev, u32 engine_clock,
RV770_SMC_SCLK_VALUE *sclk)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
struct atom_clock_dividers dividers;
u32 spll_func_cntl = pi->clk_regs.rv770.cg_spll_func_cntl;
u32 spll_func_cntl_2 = pi->clk_regs.rv770.cg_spll_func_cntl_2;
u32 spll_func_cntl_3 = pi->clk_regs.rv770.cg_spll_func_cntl_3;
u32 cg_spll_spread_spectrum = pi->clk_regs.rv770.cg_spll_spread_spectrum;
u32 cg_spll_spread_spectrum_2 = pi->clk_regs.rv770.cg_spll_spread_spectrum_2;
u64 tmp;
u32 reference_clock = rdev->clock.spll.reference_freq;
u32 reference_divider;
u32 fbdiv;
int ret;
ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
engine_clock, false, &dividers);
if (ret)
return ret;
reference_divider = 1 + dividers.ref_div;
tmp = (u64) engine_clock * reference_divider * dividers.post_div * 16384;
do_div(tmp, reference_clock);
fbdiv = (u32) tmp;
spll_func_cntl &= ~(SPLL_PDIV_A_MASK | SPLL_REF_DIV_MASK);
spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div);
spll_func_cntl |= SPLL_PDIV_A(dividers.post_div);
spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
spll_func_cntl_2 |= SCLK_MUX_SEL(2);
spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK;
spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv);
spll_func_cntl_3 |= SPLL_DITHEN;
if (pi->sclk_ss) {
struct radeon_atom_ss ss;
u32 vco_freq = engine_clock * dividers.post_div;
if (radeon_atombios_get_asic_ss_info(rdev, &ss,
ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000);
cg_spll_spread_spectrum &= ~CLK_S_MASK;
cg_spll_spread_spectrum |= CLK_S(clk_s);
cg_spll_spread_spectrum |= SSEN;
cg_spll_spread_spectrum_2 &= ~CLK_V_MASK;
cg_spll_spread_spectrum_2 |= CLK_V(clk_v);
}
}
sclk->sclk_value = cpu_to_be32(engine_clock);
sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(cg_spll_spread_spectrum);
sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(cg_spll_spread_spectrum_2);
return 0;
}
int rv740_populate_mclk_value(struct radeon_device *rdev,
u32 engine_clock, u32 memory_clock,
RV7XX_SMC_MCLK_VALUE *mclk)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
u32 mpll_ad_func_cntl = pi->clk_regs.rv770.mpll_ad_func_cntl;
u32 mpll_ad_func_cntl_2 = pi->clk_regs.rv770.mpll_ad_func_cntl_2;
u32 mpll_dq_func_cntl = pi->clk_regs.rv770.mpll_dq_func_cntl;
u32 mpll_dq_func_cntl_2 = pi->clk_regs.rv770.mpll_dq_func_cntl_2;
u32 mclk_pwrmgt_cntl = pi->clk_regs.rv770.mclk_pwrmgt_cntl;
u32 dll_cntl = pi->clk_regs.rv770.dll_cntl;
u32 mpll_ss1 = pi->clk_regs.rv770.mpll_ss1;
u32 mpll_ss2 = pi->clk_regs.rv770.mpll_ss2;
struct atom_clock_dividers dividers;
u32 ibias;
u32 dll_speed;
int ret;
ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM,
memory_clock, false, &dividers);
if (ret)
return ret;
ibias = rv770_map_clkf_to_ibias(rdev, dividers.whole_fb_div);
mpll_ad_func_cntl &= ~(CLKR_MASK |
YCLK_POST_DIV_MASK |
CLKF_MASK |
CLKFRAC_MASK |
IBIAS_MASK);
mpll_ad_func_cntl |= CLKR(dividers.ref_div);
mpll_ad_func_cntl |= YCLK_POST_DIV(dividers.post_div);
mpll_ad_func_cntl |= CLKF(dividers.whole_fb_div);
mpll_ad_func_cntl |= CLKFRAC(dividers.frac_fb_div);
mpll_ad_func_cntl |= IBIAS(ibias);
if (dividers.vco_mode)
mpll_ad_func_cntl_2 |= VCO_MODE;
else
mpll_ad_func_cntl_2 &= ~VCO_MODE;
if (pi->mem_gddr5) {
mpll_dq_func_cntl &= ~(CLKR_MASK |
YCLK_POST_DIV_MASK |
CLKF_MASK |
CLKFRAC_MASK |
IBIAS_MASK);
mpll_dq_func_cntl |= CLKR(dividers.ref_div);
mpll_dq_func_cntl |= YCLK_POST_DIV(dividers.post_div);
mpll_dq_func_cntl |= CLKF(dividers.whole_fb_div);
mpll_dq_func_cntl |= CLKFRAC(dividers.frac_fb_div);
mpll_dq_func_cntl |= IBIAS(ibias);
if (dividers.vco_mode)
mpll_dq_func_cntl_2 |= VCO_MODE;
else
mpll_dq_func_cntl_2 &= ~VCO_MODE;
}
if (pi->mclk_ss) {
struct radeon_atom_ss ss;
u32 vco_freq = memory_clock * dividers.post_div;
if (radeon_atombios_get_asic_ss_info(rdev, &ss,
ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
u32 reference_clock = rdev->clock.mpll.reference_freq;
u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div);
u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
u32 clk_v = 0x40000 * ss.percentage *
(dividers.whole_fb_div + (dividers.frac_fb_div / 8)) / (clk_s * 10000);
mpll_ss1 &= ~CLKV_MASK;
mpll_ss1 |= CLKV(clk_v);
mpll_ss2 &= ~CLKS_MASK;
mpll_ss2 |= CLKS(clk_s);
}
}
dll_speed = rv740_get_dll_speed(pi->mem_gddr5,
memory_clock);
mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK;
mclk_pwrmgt_cntl |= DLL_SPEED(dll_speed);
mclk->mclk770.mclk_value = cpu_to_be32(memory_clock);
mclk->mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
mclk->mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
mclk->mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
mclk->mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
mclk->mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
mclk->mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl);
mclk->mclk770.vMPLL_SS = cpu_to_be32(mpll_ss1);
mclk->mclk770.vMPLL_SS2 = cpu_to_be32(mpll_ss2);
return 0;
}
void rv740_read_clock_registers(struct radeon_device *rdev)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
pi->clk_regs.rv770.cg_spll_func_cntl =
RREG32(CG_SPLL_FUNC_CNTL);
pi->clk_regs.rv770.cg_spll_func_cntl_2 =
RREG32(CG_SPLL_FUNC_CNTL_2);
pi->clk_regs.rv770.cg_spll_func_cntl_3 =
RREG32(CG_SPLL_FUNC_CNTL_3);
pi->clk_regs.rv770.cg_spll_spread_spectrum =
RREG32(CG_SPLL_SPREAD_SPECTRUM);
pi->clk_regs.rv770.cg_spll_spread_spectrum_2 =
RREG32(CG_SPLL_SPREAD_SPECTRUM_2);
pi->clk_regs.rv770.mpll_ad_func_cntl =
RREG32(MPLL_AD_FUNC_CNTL);
pi->clk_regs.rv770.mpll_ad_func_cntl_2 =
RREG32(MPLL_AD_FUNC_CNTL_2);
pi->clk_regs.rv770.mpll_dq_func_cntl =
RREG32(MPLL_DQ_FUNC_CNTL);
pi->clk_regs.rv770.mpll_dq_func_cntl_2 =
RREG32(MPLL_DQ_FUNC_CNTL_2);
pi->clk_regs.rv770.mclk_pwrmgt_cntl =
RREG32(MCLK_PWRMGT_CNTL);
pi->clk_regs.rv770.dll_cntl = RREG32(DLL_CNTL);
pi->clk_regs.rv770.mpll_ss1 = RREG32(MPLL_SS1);
pi->clk_regs.rv770.mpll_ss2 = RREG32(MPLL_SS2);
}
int rv740_populate_smc_acpi_state(struct radeon_device *rdev,
RV770_SMC_STATETABLE *table)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
u32 mpll_ad_func_cntl = pi->clk_regs.rv770.mpll_ad_func_cntl;
u32 mpll_ad_func_cntl_2 = pi->clk_regs.rv770.mpll_ad_func_cntl_2;
u32 mpll_dq_func_cntl = pi->clk_regs.rv770.mpll_dq_func_cntl;
u32 mpll_dq_func_cntl_2 = pi->clk_regs.rv770.mpll_dq_func_cntl_2;
u32 spll_func_cntl = pi->clk_regs.rv770.cg_spll_func_cntl;
u32 spll_func_cntl_2 = pi->clk_regs.rv770.cg_spll_func_cntl_2;
u32 spll_func_cntl_3 = pi->clk_regs.rv770.cg_spll_func_cntl_3;
u32 mclk_pwrmgt_cntl = pi->clk_regs.rv770.mclk_pwrmgt_cntl;
u32 dll_cntl = pi->clk_regs.rv770.dll_cntl;
table->ACPIState = table->initialState;
table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;
if (pi->acpi_vddc) {
rv770_populate_vddc_value(rdev, pi->acpi_vddc,
&table->ACPIState.levels[0].vddc);
table->ACPIState.levels[0].gen2PCIE =
pi->pcie_gen2 ?
pi->acpi_pcie_gen2 : 0;
table->ACPIState.levels[0].gen2XSP =
pi->acpi_pcie_gen2;
} else {
rv770_populate_vddc_value(rdev, pi->min_vddc_in_table,
&table->ACPIState.levels[0].vddc);
table->ACPIState.levels[0].gen2PCIE = 0;
}
mpll_ad_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN;
mpll_dq_func_cntl_2 |= BYPASS | BIAS_GEN_PDNB | RESET_EN;
mclk_pwrmgt_cntl |= (MRDCKA0_RESET |
MRDCKA1_RESET |
MRDCKB0_RESET |
MRDCKB1_RESET |
MRDCKC0_RESET |
MRDCKC1_RESET |
MRDCKD0_RESET |
MRDCKD1_RESET);
dll_cntl |= (MRDCKA0_BYPASS |
MRDCKA1_BYPASS |
MRDCKB0_BYPASS |
MRDCKB1_BYPASS |
MRDCKC0_BYPASS |
MRDCKC1_BYPASS |
MRDCKD0_BYPASS |
MRDCKD1_BYPASS);
spll_func_cntl |= SPLL_RESET | SPLL_SLEEP | SPLL_BYPASS_EN;
spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
spll_func_cntl_2 |= SCLK_MUX_SEL(4);
table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
table->ACPIState.levels[0].mclk.mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
table->ACPIState.levels[0].mclk.mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl);
table->ACPIState.levels[0].mclk.mclk770.mclk_value = 0;
table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
table->ACPIState.levels[0].sclk.sclk_value = 0;
table->ACPIState.levels[1] = table->ACPIState.levels[0];
table->ACPIState.levels[2] = table->ACPIState.levels[0];
rv770_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd);
return 0;
}
void rv740_enable_mclk_spread_spectrum(struct radeon_device *rdev,
bool enable)
{
if (enable)
WREG32_P(MPLL_CNTL_MODE, SS_SSEN, ~SS_SSEN);
else
WREG32_P(MPLL_CNTL_MODE, 0, ~SS_SSEN);
}
u8 rv740_get_mclk_frequency_ratio(u32 memory_clock)
{
u8 mc_para_index;
if ((memory_clock < 10000) || (memory_clock > 47500))
mc_para_index = 0x00;
else
mc_para_index = (u8)((memory_clock - 10000) / 2500);
return mc_para_index;
}

View File

@ -0,0 +1,117 @@
/*
* Copyright 2011 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.
*
*/
#ifndef RV740_H
#define RV740_H
#define CG_SPLL_FUNC_CNTL 0x600
#define SPLL_RESET (1 << 0)
#define SPLL_SLEEP (1 << 1)
#define SPLL_BYPASS_EN (1 << 3)
#define SPLL_REF_DIV(x) ((x) << 4)
#define SPLL_REF_DIV_MASK (0x3f << 4)
#define SPLL_PDIV_A(x) ((x) << 20)
#define SPLL_PDIV_A_MASK (0x7f << 20)
#define CG_SPLL_FUNC_CNTL_2 0x604
#define SCLK_MUX_SEL(x) ((x) << 0)
#define SCLK_MUX_SEL_MASK (0x1ff << 0)
#define CG_SPLL_FUNC_CNTL_3 0x608
#define SPLL_FB_DIV(x) ((x) << 0)
#define SPLL_FB_DIV_MASK (0x3ffffff << 0)
#define SPLL_DITHEN (1 << 28)
#define MPLL_CNTL_MODE 0x61c
#define SS_SSEN (1 << 24)
#define MPLL_AD_FUNC_CNTL 0x624
#define CLKF(x) ((x) << 0)
#define CLKF_MASK (0x7f << 0)
#define CLKR(x) ((x) << 7)
#define CLKR_MASK (0x1f << 7)
#define CLKFRAC(x) ((x) << 12)
#define CLKFRAC_MASK (0x1f << 12)
#define YCLK_POST_DIV(x) ((x) << 17)
#define YCLK_POST_DIV_MASK (3 << 17)
#define IBIAS(x) ((x) << 20)
#define IBIAS_MASK (0x3ff << 20)
#define RESET (1 << 30)
#define PDNB (1 << 31)
#define MPLL_AD_FUNC_CNTL_2 0x628
#define BYPASS (1 << 19)
#define BIAS_GEN_PDNB (1 << 24)
#define RESET_EN (1 << 25)
#define VCO_MODE (1 << 29)
#define MPLL_DQ_FUNC_CNTL 0x62c
#define MPLL_DQ_FUNC_CNTL_2 0x630
#define MCLK_PWRMGT_CNTL 0x648
#define DLL_SPEED(x) ((x) << 0)
#define DLL_SPEED_MASK (0x1f << 0)
# define MPLL_PWRMGT_OFF (1 << 5)
# define DLL_READY (1 << 6)
# define MC_INT_CNTL (1 << 7)
# define MRDCKA0_SLEEP (1 << 8)
# define MRDCKA1_SLEEP (1 << 9)
# define MRDCKB0_SLEEP (1 << 10)
# define MRDCKB1_SLEEP (1 << 11)
# define MRDCKC0_SLEEP (1 << 12)
# define MRDCKC1_SLEEP (1 << 13)
# define MRDCKD0_SLEEP (1 << 14)
# define MRDCKD1_SLEEP (1 << 15)
# define MRDCKA0_RESET (1 << 16)
# define MRDCKA1_RESET (1 << 17)
# define MRDCKB0_RESET (1 << 18)
# define MRDCKB1_RESET (1 << 19)
# define MRDCKC0_RESET (1 << 20)
# define MRDCKC1_RESET (1 << 21)
# define MRDCKD0_RESET (1 << 22)
# define MRDCKD1_RESET (1 << 23)
# define DLL_READY_READ (1 << 24)
# define USE_DISPLAY_GAP (1 << 25)
# define USE_DISPLAY_URGENT_NORMAL (1 << 26)
# define MPLL_TURNOFF_D2 (1 << 28)
#define DLL_CNTL 0x64c
# define MRDCKA0_BYPASS (1 << 24)
# define MRDCKA1_BYPASS (1 << 25)
# define MRDCKB0_BYPASS (1 << 26)
# define MRDCKB1_BYPASS (1 << 27)
# define MRDCKC0_BYPASS (1 << 28)
# define MRDCKC1_BYPASS (1 << 29)
# define MRDCKD0_BYPASS (1 << 30)
# define MRDCKD1_BYPASS (1 << 31)
#define CG_SPLL_SPREAD_SPECTRUM 0x790
#define SSEN (1 << 0)
#define CLK_S(x) ((x) << 4)
#define CLK_S_MASK (0xfff << 4)
#define CG_SPLL_SPREAD_SPECTRUM_2 0x794
#define CLK_V(x) ((x) << 0)
#define CLK_V_MASK (0x3ffffff << 0)
#define MPLL_SS1 0x85c
#define CLKV(x) ((x) << 0)
#define CLKV_MASK (0x3ffffff << 0)
#define MPLL_SS2 0x860
#define CLKS(x) ((x) << 0)
#define CLKS_MASK (0xfff << 0)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,288 @@
/*
* Copyright 2011 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.
*
*/
#ifndef __RV770_DPM_H__
#define __RV770_DPM_H__
#include "rv770_smc.h"
struct rv770_clock_registers {
u32 cg_spll_func_cntl;
u32 cg_spll_func_cntl_2;
u32 cg_spll_func_cntl_3;
u32 cg_spll_spread_spectrum;
u32 cg_spll_spread_spectrum_2;
u32 mpll_ad_func_cntl;
u32 mpll_ad_func_cntl_2;
u32 mpll_dq_func_cntl;
u32 mpll_dq_func_cntl_2;
u32 mclk_pwrmgt_cntl;
u32 dll_cntl;
u32 mpll_ss1;
u32 mpll_ss2;
};
struct rv730_clock_registers {
u32 cg_spll_func_cntl;
u32 cg_spll_func_cntl_2;
u32 cg_spll_func_cntl_3;
u32 cg_spll_spread_spectrum;
u32 cg_spll_spread_spectrum_2;
u32 mclk_pwrmgt_cntl;
u32 dll_cntl;
u32 mpll_func_cntl;
u32 mpll_func_cntl2;
u32 mpll_func_cntl3;
u32 mpll_ss;
u32 mpll_ss2;
};
union r7xx_clock_registers {
struct rv770_clock_registers rv770;
struct rv730_clock_registers rv730;
};
struct vddc_table_entry {
u16 vddc;
u8 vddc_index;
u8 high_smio;
u32 low_smio;
};
#define MAX_NO_OF_MVDD_VALUES 2
#define MAX_NO_VREG_STEPS 32
struct rv7xx_power_info {
/* flags */
bool mem_gddr5;
bool pcie_gen2;
bool dynamic_pcie_gen2;
bool acpi_pcie_gen2;
bool boot_in_gen2;
bool voltage_control; /* vddc */
bool mvdd_control;
bool sclk_ss;
bool mclk_ss;
bool dynamic_ss;
bool gfx_clock_gating;
bool mg_clock_gating;
bool mgcgtssm;
bool power_gating;
bool thermal_protection;
bool display_gap;
bool dcodt;
bool ulps;
/* registers */
union r7xx_clock_registers clk_regs;
u32 s0_vid_lower_smio_cntl;
/* voltage */
u32 vddc_mask_low;
u32 mvdd_mask_low;
u32 mvdd_split_frequency;
u32 mvdd_low_smio[MAX_NO_OF_MVDD_VALUES];
u16 max_vddc;
u16 max_vddc_in_table;
u16 min_vddc_in_table;
struct vddc_table_entry vddc_table[MAX_NO_VREG_STEPS];
u8 valid_vddc_entries;
/* dc odt */
u32 mclk_odt_threshold;
u8 odt_value_0[2];
u8 odt_value_1[2];
/* stored values */
u32 boot_sclk;
u16 acpi_vddc;
u32 ref_div;
u32 active_auto_throttle_sources;
u32 mclk_stutter_mode_threshold;
u32 mclk_strobe_mode_threshold;
u32 mclk_edc_enable_threshold;
u32 bsp;
u32 bsu;
u32 pbsp;
u32 pbsu;
u32 dsp;
u32 psp;
u32 asi;
u32 pasi;
u32 vrc;
u32 restricted_levels;
u32 rlp;
u32 rmp;
u32 lhp;
u32 lmp;
/* smc offsets */
u16 state_table_start;
u16 soft_regs_start;
u16 sram_end;
/* scratch structs */
RV770_SMC_STATETABLE smc_statetable;
};
struct rv7xx_pl {
u32 sclk;
u32 mclk;
u16 vddc;
u16 vddci; /* eg+ only */
u32 flags;
enum radeon_pcie_gen pcie_gen; /* si+ only */
};
struct rv7xx_ps {
struct rv7xx_pl high;
struct rv7xx_pl medium;
struct rv7xx_pl low;
bool dc_compatible;
};
#define RV770_RLP_DFLT 10
#define RV770_RMP_DFLT 25
#define RV770_LHP_DFLT 25
#define RV770_LMP_DFLT 10
#define RV770_VRC_DFLT 0x003f
#define RV770_ASI_DFLT 1000
#define RV770_HASI_DFLT 200000
#define RV770_MGCGTTLOCAL0_DFLT 0x00100000
#define RV7XX_MGCGTTLOCAL0_DFLT 0
#define RV770_MGCGTTLOCAL1_DFLT 0xFFFF0000
#define RV770_MGCGCGTSSMCTRL_DFLT 0x55940000
#define MVDD_LOW_INDEX 0
#define MVDD_HIGH_INDEX 1
#define MVDD_LOW_VALUE 0
#define MVDD_HIGH_VALUE 0xffff
#define RV770_DEFAULT_VCLK_FREQ 53300 /* 10 khz */
#define RV770_DEFAULT_DCLK_FREQ 40000 /* 10 khz */
/* rv730/rv710 */
int rv730_populate_sclk_value(struct radeon_device *rdev,
u32 engine_clock,
RV770_SMC_SCLK_VALUE *sclk);
int rv730_populate_mclk_value(struct radeon_device *rdev,
u32 engine_clock, u32 memory_clock,
LPRV7XX_SMC_MCLK_VALUE mclk);
void rv730_read_clock_registers(struct radeon_device *rdev);
int rv730_populate_smc_acpi_state(struct radeon_device *rdev,
RV770_SMC_STATETABLE *table);
int rv730_populate_smc_initial_state(struct radeon_device *rdev,
struct radeon_ps *radeon_initial_state,
RV770_SMC_STATETABLE *table);
void rv730_program_memory_timing_parameters(struct radeon_device *rdev,
struct radeon_ps *radeon_state);
void rv730_power_gating_enable(struct radeon_device *rdev,
bool enable);
void rv730_start_dpm(struct radeon_device *rdev);
void rv730_stop_dpm(struct radeon_device *rdev);
void rv730_program_dcodt(struct radeon_device *rdev, bool use_dcodt);
void rv730_get_odt_values(struct radeon_device *rdev);
/* rv740 */
int rv740_populate_sclk_value(struct radeon_device *rdev, u32 engine_clock,
RV770_SMC_SCLK_VALUE *sclk);
int rv740_populate_mclk_value(struct radeon_device *rdev,
u32 engine_clock, u32 memory_clock,
RV7XX_SMC_MCLK_VALUE *mclk);
void rv740_read_clock_registers(struct radeon_device *rdev);
int rv740_populate_smc_acpi_state(struct radeon_device *rdev,
RV770_SMC_STATETABLE *table);
void rv740_enable_mclk_spread_spectrum(struct radeon_device *rdev,
bool enable);
u8 rv740_get_mclk_frequency_ratio(u32 memory_clock);
u32 rv740_get_dll_speed(bool is_gddr5, u32 memory_clock);
u32 rv740_get_decoded_reference_divider(u32 encoded_ref);
/* rv770 */
u32 rv770_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf);
int rv770_populate_vddc_value(struct radeon_device *rdev, u16 vddc,
RV770_SMC_VOLTAGE_VALUE *voltage);
int rv770_populate_mvdd_value(struct radeon_device *rdev, u32 mclk,
RV770_SMC_VOLTAGE_VALUE *voltage);
u8 rv770_get_seq_value(struct radeon_device *rdev,
struct rv7xx_pl *pl);
int rv770_populate_initial_mvdd_value(struct radeon_device *rdev,
RV770_SMC_VOLTAGE_VALUE *voltage);
u32 rv770_calculate_memory_refresh_rate(struct radeon_device *rdev,
u32 engine_clock);
void rv770_program_response_times(struct radeon_device *rdev);
int rv770_populate_smc_sp(struct radeon_device *rdev,
struct radeon_ps *radeon_state,
RV770_SMC_SWSTATE *smc_state);
int rv770_populate_smc_t(struct radeon_device *rdev,
struct radeon_ps *radeon_state,
RV770_SMC_SWSTATE *smc_state);
void rv770_read_voltage_smio_registers(struct radeon_device *rdev);
void rv770_get_memory_type(struct radeon_device *rdev);
void r7xx_start_smc(struct radeon_device *rdev);
u8 rv770_get_memory_module_index(struct radeon_device *rdev);
void rv770_get_max_vddc(struct radeon_device *rdev);
void rv770_get_pcie_gen2_status(struct radeon_device *rdev);
void rv770_enable_acpi_pm(struct radeon_device *rdev);
void rv770_restore_cgcg(struct radeon_device *rdev);
bool rv770_dpm_enabled(struct radeon_device *rdev);
void rv770_enable_voltage_control(struct radeon_device *rdev,
bool enable);
void rv770_enable_backbias(struct radeon_device *rdev,
bool enable);
void rv770_enable_thermal_protection(struct radeon_device *rdev,
bool enable);
void rv770_enable_auto_throttle_source(struct radeon_device *rdev,
enum radeon_dpm_auto_throttle_src source,
bool enable);
void rv770_setup_bsp(struct radeon_device *rdev);
void rv770_program_git(struct radeon_device *rdev);
void rv770_program_tp(struct radeon_device *rdev);
void rv770_program_tpp(struct radeon_device *rdev);
void rv770_program_sstp(struct radeon_device *rdev);
void rv770_program_engine_speed_parameters(struct radeon_device *rdev);
void rv770_program_vc(struct radeon_device *rdev);
void rv770_clear_vc(struct radeon_device *rdev);
int rv770_upload_firmware(struct radeon_device *rdev);
void rv770_stop_dpm(struct radeon_device *rdev);
void r7xx_stop_smc(struct radeon_device *rdev);
void rv770_reset_smio_status(struct radeon_device *rdev);
int rv770_restrict_performance_levels_before_switch(struct radeon_device *rdev);
int rv770_unrestrict_performance_levels_after_switch(struct radeon_device *rdev);
int rv770_halt_smc(struct radeon_device *rdev);
int rv770_resume_smc(struct radeon_device *rdev);
int rv770_set_sw_state(struct radeon_device *rdev);
int rv770_set_boot_state(struct radeon_device *rdev);
int rv7xx_parse_power_table(struct radeon_device *rdev);
void rv770_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
struct radeon_ps *new_ps,
struct radeon_ps *old_ps);
void rv770_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
struct radeon_ps *new_ps,
struct radeon_ps *old_ps);
/* smc */
int rv770_read_smc_soft_register(struct radeon_device *rdev,
u16 reg_offset, u32 *value);
int rv770_write_smc_soft_register(struct radeon_device *rdev,
u16 reg_offset, u32 value);
/* thermal */
int rv770_set_thermal_temperature_range(struct radeon_device *rdev,
int min_temp, int max_temp);
#endif

View File

@ -0,0 +1,621 @@
/*
* Copyright 2011 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: Alex Deucher
*/
#include <linux/firmware.h>
#include "drmP.h"
#include "radeon.h"
#include "rv770d.h"
#include "rv770_dpm.h"
#include "rv770_smc.h"
#include "atom.h"
#include "radeon_ucode.h"
#define FIRST_SMC_INT_VECT_REG 0xFFD8
#define FIRST_INT_VECT_S19 0xFFC0
static const u8 rv770_smc_int_vectors[] =
{
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x0C, 0xD7,
0x08, 0x2B, 0x08, 0x10,
0x03, 0x51, 0x03, 0x51,
0x03, 0x51, 0x03, 0x51
};
static const u8 rv730_smc_int_vectors[] =
{
0x08, 0x15, 0x08, 0x15,
0x08, 0x15, 0x08, 0x15,
0x08, 0x15, 0x08, 0x15,
0x08, 0x15, 0x08, 0x15,
0x08, 0x15, 0x08, 0x15,
0x08, 0x15, 0x08, 0x15,
0x08, 0x15, 0x08, 0x15,
0x08, 0x15, 0x08, 0x15,
0x08, 0x15, 0x08, 0x15,
0x08, 0x15, 0x08, 0x15,
0x08, 0x15, 0x08, 0x15,
0x08, 0x15, 0x08, 0x15,
0x08, 0x15, 0x0C, 0xBB,
0x08, 0x30, 0x08, 0x15,
0x03, 0x56, 0x03, 0x56,
0x03, 0x56, 0x03, 0x56
};
static const u8 rv710_smc_int_vectors[] =
{
0x08, 0x04, 0x08, 0x04,
0x08, 0x04, 0x08, 0x04,
0x08, 0x04, 0x08, 0x04,
0x08, 0x04, 0x08, 0x04,
0x08, 0x04, 0x08, 0x04,
0x08, 0x04, 0x08, 0x04,
0x08, 0x04, 0x08, 0x04,
0x08, 0x04, 0x08, 0x04,
0x08, 0x04, 0x08, 0x04,
0x08, 0x04, 0x08, 0x04,
0x08, 0x04, 0x08, 0x04,
0x08, 0x04, 0x08, 0x04,
0x08, 0x04, 0x0C, 0xCB,
0x08, 0x1F, 0x08, 0x04,
0x03, 0x51, 0x03, 0x51,
0x03, 0x51, 0x03, 0x51
};
static const u8 rv740_smc_int_vectors[] =
{
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x08, 0x10,
0x08, 0x10, 0x0C, 0xD7,
0x08, 0x2B, 0x08, 0x10,
0x03, 0x51, 0x03, 0x51,
0x03, 0x51, 0x03, 0x51
};
static const u8 cedar_smc_int_vectors[] =
{
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x11, 0x8B,
0x0B, 0x20, 0x0B, 0x05,
0x04, 0xF6, 0x04, 0xF6,
0x04, 0xF6, 0x04, 0xF6
};
static const u8 redwood_smc_int_vectors[] =
{
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x11, 0x8B,
0x0B, 0x20, 0x0B, 0x05,
0x04, 0xF6, 0x04, 0xF6,
0x04, 0xF6, 0x04, 0xF6
};
static const u8 juniper_smc_int_vectors[] =
{
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x11, 0x8B,
0x0B, 0x20, 0x0B, 0x05,
0x04, 0xF6, 0x04, 0xF6,
0x04, 0xF6, 0x04, 0xF6
};
static const u8 cypress_smc_int_vectors[] =
{
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x0B, 0x05,
0x0B, 0x05, 0x11, 0x8B,
0x0B, 0x20, 0x0B, 0x05,
0x04, 0xF6, 0x04, 0xF6,
0x04, 0xF6, 0x04, 0xF6
};
static const u8 barts_smc_int_vectors[] =
{
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x12, 0xAA,
0x0C, 0x2F, 0x15, 0xF6,
0x15, 0xF6, 0x05, 0x0A,
0x05, 0x0A, 0x05, 0x0A
};
static const u8 turks_smc_int_vectors[] =
{
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x12, 0xAA,
0x0C, 0x2F, 0x15, 0xF6,
0x15, 0xF6, 0x05, 0x0A,
0x05, 0x0A, 0x05, 0x0A
};
static const u8 caicos_smc_int_vectors[] =
{
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x0C, 0x14,
0x0C, 0x14, 0x12, 0xAA,
0x0C, 0x2F, 0x15, 0xF6,
0x15, 0xF6, 0x05, 0x0A,
0x05, 0x0A, 0x05, 0x0A
};
static const u8 cayman_smc_int_vectors[] =
{
0x12, 0x05, 0x12, 0x05,
0x12, 0x05, 0x12, 0x05,
0x12, 0x05, 0x12, 0x05,
0x12, 0x05, 0x12, 0x05,
0x12, 0x05, 0x12, 0x05,
0x12, 0x05, 0x12, 0x05,
0x12, 0x05, 0x12, 0x05,
0x12, 0x05, 0x12, 0x05,
0x12, 0x05, 0x12, 0x05,
0x12, 0x05, 0x12, 0x05,
0x12, 0x05, 0x12, 0x05,
0x12, 0x05, 0x12, 0x05,
0x12, 0x05, 0x18, 0xEA,
0x12, 0x20, 0x1C, 0x34,
0x1C, 0x34, 0x08, 0x72,
0x08, 0x72, 0x08, 0x72
};
int rv770_set_smc_sram_address(struct radeon_device *rdev,
u16 smc_address, u16 limit)
{
u32 addr;
if (smc_address & 3)
return -EINVAL;
if ((smc_address + 3) > limit)
return -EINVAL;
addr = smc_address;
addr |= SMC_SRAM_AUTO_INC_DIS;
WREG32(SMC_SRAM_ADDR, addr);
return 0;
}
int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
u16 smc_start_address, const u8 *src,
u16 byte_count, u16 limit)
{
u32 data, original_data, extra_shift;
u16 addr;
int ret;
if (smc_start_address & 3)
return -EINVAL;
if ((smc_start_address + byte_count) > limit)
return -EINVAL;
addr = smc_start_address;
while (byte_count >= 4) {
/* SMC address space is BE */
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
ret = rv770_set_smc_sram_address(rdev, addr, limit);
if (ret)
return ret;
WREG32(SMC_SRAM_DATA, data);
src += 4;
byte_count -= 4;
addr += 4;
}
/* RMW for final bytes */
if (byte_count > 0) {
data = 0;
ret = rv770_set_smc_sram_address(rdev, addr, limit);
if (ret)
return ret;
original_data = RREG32(SMC_SRAM_DATA);
extra_shift = 8 * (4 - byte_count);
while (byte_count > 0) {
/* SMC address space is BE */
data = (data << 8) + *src++;
byte_count--;
}
data <<= extra_shift;
data |= (original_data & ~((~0UL) << extra_shift));
ret = rv770_set_smc_sram_address(rdev, addr, limit);
if (ret)
return ret;
WREG32(SMC_SRAM_DATA, data);
}
return 0;
}
static int rv770_program_interrupt_vectors(struct radeon_device *rdev,
u32 smc_first_vector, const u8 *src,
u32 byte_count)
{
u32 tmp, i;
if (byte_count % 4)
return -EINVAL;
if (smc_first_vector < FIRST_SMC_INT_VECT_REG) {
tmp = FIRST_SMC_INT_VECT_REG - smc_first_vector;
if (tmp > byte_count)
return 0;
byte_count -= tmp;
src += tmp;
smc_first_vector = FIRST_SMC_INT_VECT_REG;
}
for (i = 0; i < byte_count; i += 4) {
/* SMC address space is BE */
tmp = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3];
WREG32(SMC_ISR_FFD8_FFDB + i, tmp);
}
return 0;
}
void rv770_start_smc(struct radeon_device *rdev)
{
WREG32_P(SMC_IO, SMC_RST_N, ~SMC_RST_N);
}
void rv770_reset_smc(struct radeon_device *rdev)
{
WREG32_P(SMC_IO, 0, ~SMC_RST_N);
}
void rv770_stop_smc_clock(struct radeon_device *rdev)
{
WREG32_P(SMC_IO, 0, ~SMC_CLK_EN);
}
void rv770_start_smc_clock(struct radeon_device *rdev)
{
WREG32_P(SMC_IO, SMC_CLK_EN, ~SMC_CLK_EN);
}
bool rv770_is_smc_running(struct radeon_device *rdev)
{
u32 tmp;
tmp = RREG32(SMC_IO);
if ((tmp & SMC_RST_N) && (tmp & SMC_CLK_EN))
return true;
else
return false;
}
PPSMC_Result rv770_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg)
{
u32 tmp;
int i;
PPSMC_Result result;
if (!rv770_is_smc_running(rdev))
return PPSMC_Result_Failed;
WREG32_P(SMC_MSG, HOST_SMC_MSG(msg), ~HOST_SMC_MSG_MASK);
for (i = 0; i < rdev->usec_timeout; i++) {
tmp = RREG32(SMC_MSG) & HOST_SMC_RESP_MASK;
tmp >>= HOST_SMC_RESP_SHIFT;
if (tmp != 0)
break;
udelay(1);
}
tmp = RREG32(SMC_MSG) & HOST_SMC_RESP_MASK;
tmp >>= HOST_SMC_RESP_SHIFT;
result = (PPSMC_Result)tmp;
return result;
}
PPSMC_Result rv770_wait_for_smc_inactive(struct radeon_device *rdev)
{
int i;
PPSMC_Result result = PPSMC_Result_OK;
if (!rv770_is_smc_running(rdev))
return result;
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(SMC_IO) & SMC_STOP_MODE)
break;
udelay(1);
}
return result;
}
static void rv770_clear_smc_sram(struct radeon_device *rdev, u16 limit)
{
u16 i;
for (i = 0; i < limit; i += 4) {
rv770_set_smc_sram_address(rdev, i, limit);
WREG32(SMC_SRAM_DATA, 0);
}
}
int rv770_load_smc_ucode(struct radeon_device *rdev,
u16 limit)
{
int ret;
const u8 *int_vect;
u16 int_vect_start_address;
u16 int_vect_size;
const u8 *ucode_data;
u16 ucode_start_address;
u16 ucode_size;
if (!rdev->smc_fw)
return -EINVAL;
rv770_clear_smc_sram(rdev, limit);
switch (rdev->family) {
case CHIP_RV770:
ucode_start_address = RV770_SMC_UCODE_START;
ucode_size = RV770_SMC_UCODE_SIZE;
int_vect = (const u8 *)&rv770_smc_int_vectors;
int_vect_start_address = RV770_SMC_INT_VECTOR_START;
int_vect_size = RV770_SMC_INT_VECTOR_SIZE;
break;
case CHIP_RV730:
ucode_start_address = RV730_SMC_UCODE_START;
ucode_size = RV730_SMC_UCODE_SIZE;
int_vect = (const u8 *)&rv730_smc_int_vectors;
int_vect_start_address = RV730_SMC_INT_VECTOR_START;
int_vect_size = RV730_SMC_INT_VECTOR_SIZE;
break;
case CHIP_RV710:
ucode_start_address = RV710_SMC_UCODE_START;
ucode_size = RV710_SMC_UCODE_SIZE;
int_vect = (const u8 *)&rv710_smc_int_vectors;
int_vect_start_address = RV710_SMC_INT_VECTOR_START;
int_vect_size = RV710_SMC_INT_VECTOR_SIZE;
break;
case CHIP_RV740:
ucode_start_address = RV740_SMC_UCODE_START;
ucode_size = RV740_SMC_UCODE_SIZE;
int_vect = (const u8 *)&rv740_smc_int_vectors;
int_vect_start_address = RV740_SMC_INT_VECTOR_START;
int_vect_size = RV740_SMC_INT_VECTOR_SIZE;
break;
case CHIP_CEDAR:
ucode_start_address = CEDAR_SMC_UCODE_START;
ucode_size = CEDAR_SMC_UCODE_SIZE;
int_vect = (const u8 *)&cedar_smc_int_vectors;
int_vect_start_address = CEDAR_SMC_INT_VECTOR_START;
int_vect_size = CEDAR_SMC_INT_VECTOR_SIZE;
break;
case CHIP_REDWOOD:
ucode_start_address = REDWOOD_SMC_UCODE_START;
ucode_size = REDWOOD_SMC_UCODE_SIZE;
int_vect = (const u8 *)&redwood_smc_int_vectors;
int_vect_start_address = REDWOOD_SMC_INT_VECTOR_START;
int_vect_size = REDWOOD_SMC_INT_VECTOR_SIZE;
break;
case CHIP_JUNIPER:
ucode_start_address = JUNIPER_SMC_UCODE_START;
ucode_size = JUNIPER_SMC_UCODE_SIZE;
int_vect = (const u8 *)&juniper_smc_int_vectors;
int_vect_start_address = JUNIPER_SMC_INT_VECTOR_START;
int_vect_size = JUNIPER_SMC_INT_VECTOR_SIZE;
break;
case CHIP_CYPRESS:
case CHIP_HEMLOCK:
ucode_start_address = CYPRESS_SMC_UCODE_START;
ucode_size = CYPRESS_SMC_UCODE_SIZE;
int_vect = (const u8 *)&cypress_smc_int_vectors;
int_vect_start_address = CYPRESS_SMC_INT_VECTOR_START;
int_vect_size = CYPRESS_SMC_INT_VECTOR_SIZE;
break;
case CHIP_BARTS:
ucode_start_address = BARTS_SMC_UCODE_START;
ucode_size = BARTS_SMC_UCODE_SIZE;
int_vect = (const u8 *)&barts_smc_int_vectors;
int_vect_start_address = BARTS_SMC_INT_VECTOR_START;
int_vect_size = BARTS_SMC_INT_VECTOR_SIZE;
break;
case CHIP_TURKS:
ucode_start_address = TURKS_SMC_UCODE_START;
ucode_size = TURKS_SMC_UCODE_SIZE;
int_vect = (const u8 *)&turks_smc_int_vectors;
int_vect_start_address = TURKS_SMC_INT_VECTOR_START;
int_vect_size = TURKS_SMC_INT_VECTOR_SIZE;
break;
case CHIP_CAICOS:
ucode_start_address = CAICOS_SMC_UCODE_START;
ucode_size = CAICOS_SMC_UCODE_SIZE;
int_vect = (const u8 *)&caicos_smc_int_vectors;
int_vect_start_address = CAICOS_SMC_INT_VECTOR_START;
int_vect_size = CAICOS_SMC_INT_VECTOR_SIZE;
break;
case CHIP_CAYMAN:
ucode_start_address = CAYMAN_SMC_UCODE_START;
ucode_size = CAYMAN_SMC_UCODE_SIZE;
int_vect = (const u8 *)&cayman_smc_int_vectors;
int_vect_start_address = CAYMAN_SMC_INT_VECTOR_START;
int_vect_size = CAYMAN_SMC_INT_VECTOR_SIZE;
break;
default:
DRM_ERROR("unknown asic in smc ucode loader\n");
BUG();
}
/* load the ucode */
ucode_data = (const u8 *)rdev->smc_fw->data;
ret = rv770_copy_bytes_to_smc(rdev, ucode_start_address,
ucode_data, ucode_size, limit);
if (ret)
return ret;
/* set up the int vectors */
ret = rv770_program_interrupt_vectors(rdev, int_vect_start_address,
int_vect, int_vect_size);
if (ret)
return ret;
return 0;
}
int rv770_read_smc_sram_dword(struct radeon_device *rdev,
u16 smc_address, u32 *value, u16 limit)
{
int ret;
ret = rv770_set_smc_sram_address(rdev, smc_address, limit);
if (ret)
return ret;
*value = RREG32(SMC_SRAM_DATA);
return 0;
}
int rv770_write_smc_sram_dword(struct radeon_device *rdev,
u16 smc_address, u32 value, u16 limit)
{
int ret;
ret = rv770_set_smc_sram_address(rdev, smc_address, limit);
if (ret)
return ret;
WREG32(SMC_SRAM_DATA, value);
return 0;
}

View File

@ -0,0 +1,209 @@
/*
* Copyright 2011 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.
*
*/
#ifndef __RV770_SMC_H__
#define __RV770_SMC_H__
#include "ppsmc.h"
#pragma pack(push, 1)
#define RV770_SMC_TABLE_ADDRESS 0xB000
#define RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 3
struct RV770_SMC_SCLK_VALUE
{
uint32_t vCG_SPLL_FUNC_CNTL;
uint32_t vCG_SPLL_FUNC_CNTL_2;
uint32_t vCG_SPLL_FUNC_CNTL_3;
uint32_t vCG_SPLL_SPREAD_SPECTRUM;
uint32_t vCG_SPLL_SPREAD_SPECTRUM_2;
uint32_t sclk_value;
};
typedef struct RV770_SMC_SCLK_VALUE RV770_SMC_SCLK_VALUE;
struct RV770_SMC_MCLK_VALUE
{
uint32_t vMPLL_AD_FUNC_CNTL;
uint32_t vMPLL_AD_FUNC_CNTL_2;
uint32_t vMPLL_DQ_FUNC_CNTL;
uint32_t vMPLL_DQ_FUNC_CNTL_2;
uint32_t vMCLK_PWRMGT_CNTL;
uint32_t vDLL_CNTL;
uint32_t vMPLL_SS;
uint32_t vMPLL_SS2;
uint32_t mclk_value;
};
typedef struct RV770_SMC_MCLK_VALUE RV770_SMC_MCLK_VALUE;
struct RV730_SMC_MCLK_VALUE
{
uint32_t vMCLK_PWRMGT_CNTL;
uint32_t vDLL_CNTL;
uint32_t vMPLL_FUNC_CNTL;
uint32_t vMPLL_FUNC_CNTL2;
uint32_t vMPLL_FUNC_CNTL3;
uint32_t vMPLL_SS;
uint32_t vMPLL_SS2;
uint32_t mclk_value;
};
typedef struct RV730_SMC_MCLK_VALUE RV730_SMC_MCLK_VALUE;
struct RV770_SMC_VOLTAGE_VALUE
{
uint16_t value;
uint8_t index;
uint8_t padding;
};
typedef struct RV770_SMC_VOLTAGE_VALUE RV770_SMC_VOLTAGE_VALUE;
union RV7XX_SMC_MCLK_VALUE
{
RV770_SMC_MCLK_VALUE mclk770;
RV730_SMC_MCLK_VALUE mclk730;
};
typedef union RV7XX_SMC_MCLK_VALUE RV7XX_SMC_MCLK_VALUE, *LPRV7XX_SMC_MCLK_VALUE;
struct RV770_SMC_HW_PERFORMANCE_LEVEL
{
uint8_t arbValue;
union{
uint8_t seqValue;
uint8_t ACIndex;
};
uint8_t displayWatermark;
uint8_t gen2PCIE;
uint8_t gen2XSP;
uint8_t backbias;
uint8_t strobeMode;
uint8_t mcFlags;
uint32_t aT;
uint32_t bSP;
RV770_SMC_SCLK_VALUE sclk;
RV7XX_SMC_MCLK_VALUE mclk;
RV770_SMC_VOLTAGE_VALUE vddc;
RV770_SMC_VOLTAGE_VALUE mvdd;
RV770_SMC_VOLTAGE_VALUE vddci;
uint8_t reserved1;
uint8_t reserved2;
uint8_t stateFlags;
uint8_t padding;
};
#define SMC_STROBE_RATIO 0x0F
#define SMC_STROBE_ENABLE 0x10
#define SMC_MC_EDC_RD_FLAG 0x01
#define SMC_MC_EDC_WR_FLAG 0x02
#define SMC_MC_RTT_ENABLE 0x04
#define SMC_MC_STUTTER_EN 0x08
typedef struct RV770_SMC_HW_PERFORMANCE_LEVEL RV770_SMC_HW_PERFORMANCE_LEVEL;
struct RV770_SMC_SWSTATE
{
uint8_t flags;
uint8_t padding1;
uint8_t padding2;
uint8_t padding3;
RV770_SMC_HW_PERFORMANCE_LEVEL levels[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE];
};
typedef struct RV770_SMC_SWSTATE RV770_SMC_SWSTATE;
#define RV770_SMC_VOLTAGEMASK_VDDC 0
#define RV770_SMC_VOLTAGEMASK_MVDD 1
#define RV770_SMC_VOLTAGEMASK_VDDCI 2
#define RV770_SMC_VOLTAGEMASK_MAX 4
struct RV770_SMC_VOLTAGEMASKTABLE
{
uint8_t highMask[RV770_SMC_VOLTAGEMASK_MAX];
uint32_t lowMask[RV770_SMC_VOLTAGEMASK_MAX];
};
typedef struct RV770_SMC_VOLTAGEMASKTABLE RV770_SMC_VOLTAGEMASKTABLE;
#define MAX_NO_VREG_STEPS 32
struct RV770_SMC_STATETABLE
{
uint8_t thermalProtectType;
uint8_t systemFlags;
uint8_t maxVDDCIndexInPPTable;
uint8_t extraFlags;
uint8_t highSMIO[MAX_NO_VREG_STEPS];
uint32_t lowSMIO[MAX_NO_VREG_STEPS];
RV770_SMC_VOLTAGEMASKTABLE voltageMaskTable;
RV770_SMC_SWSTATE initialState;
RV770_SMC_SWSTATE ACPIState;
RV770_SMC_SWSTATE driverState;
RV770_SMC_SWSTATE ULVState;
};
typedef struct RV770_SMC_STATETABLE RV770_SMC_STATETABLE;
#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01
#pragma pack(pop)
#define RV770_SMC_SOFT_REGISTERS_START 0x104
#define RV770_SMC_SOFT_REGISTER_mclk_chg_timeout 0x0
#define RV770_SMC_SOFT_REGISTER_baby_step_timer 0x8
#define RV770_SMC_SOFT_REGISTER_delay_bbias 0xC
#define RV770_SMC_SOFT_REGISTER_delay_vreg 0x10
#define RV770_SMC_SOFT_REGISTER_delay_acpi 0x2C
#define RV770_SMC_SOFT_REGISTER_seq_index 0x64
#define RV770_SMC_SOFT_REGISTER_mvdd_chg_time 0x68
#define RV770_SMC_SOFT_REGISTER_mclk_switch_lim 0x78
#define RV770_SMC_SOFT_REGISTER_mc_block_delay 0x90
#define RV770_SMC_SOFT_REGISTER_uvd_enabled 0x9C
#define RV770_SMC_SOFT_REGISTER_is_asic_lombok 0xA0
int rv770_set_smc_sram_address(struct radeon_device *rdev,
u16 smc_address, u16 limit);
int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
u16 smc_start_address, const u8 *src,
u16 byte_count, u16 limit);
void rv770_start_smc(struct radeon_device *rdev);
void rv770_reset_smc(struct radeon_device *rdev);
void rv770_stop_smc_clock(struct radeon_device *rdev);
void rv770_start_smc_clock(struct radeon_device *rdev);
bool rv770_is_smc_running(struct radeon_device *rdev);
PPSMC_Result rv770_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg);
PPSMC_Result rv770_wait_for_smc_inactive(struct radeon_device *rdev);
int rv770_read_smc_sram_dword(struct radeon_device *rdev,
u16 smc_address, u32 *value, u16 limit);
int rv770_write_smc_sram_dword(struct radeon_device *rdev,
u16 smc_address, u32 value, u16 limit);
int rv770_load_smc_ucode(struct radeon_device *rdev,
u16 limit);
#endif

View File

@ -62,6 +62,242 @@
# define UPLL_FB_DIV(x) ((x) << 0)
# define UPLL_FB_DIV_MASK 0x01FFFFFF
/* pm registers */
#define SMC_SRAM_ADDR 0x200
#define SMC_SRAM_AUTO_INC_DIS (1 << 16)
#define SMC_SRAM_DATA 0x204
#define SMC_IO 0x208
#define SMC_RST_N (1 << 0)
#define SMC_STOP_MODE (1 << 2)
#define SMC_CLK_EN (1 << 11)
#define SMC_MSG 0x20c
#define HOST_SMC_MSG(x) ((x) << 0)
#define HOST_SMC_MSG_MASK (0xff << 0)
#define HOST_SMC_MSG_SHIFT 0
#define HOST_SMC_RESP(x) ((x) << 8)
#define HOST_SMC_RESP_MASK (0xff << 8)
#define HOST_SMC_RESP_SHIFT 8
#define SMC_HOST_MSG(x) ((x) << 16)
#define SMC_HOST_MSG_MASK (0xff << 16)
#define SMC_HOST_MSG_SHIFT 16
#define SMC_HOST_RESP(x) ((x) << 24)
#define SMC_HOST_RESP_MASK (0xff << 24)
#define SMC_HOST_RESP_SHIFT 24
#define SMC_ISR_FFD8_FFDB 0x218
#define CG_SPLL_FUNC_CNTL 0x600
#define SPLL_RESET (1 << 0)
#define SPLL_SLEEP (1 << 1)
#define SPLL_DIVEN (1 << 2)
#define SPLL_BYPASS_EN (1 << 3)
#define SPLL_REF_DIV(x) ((x) << 4)
#define SPLL_REF_DIV_MASK (0x3f << 4)
#define SPLL_HILEN(x) ((x) << 12)
#define SPLL_HILEN_MASK (0xf << 12)
#define SPLL_LOLEN(x) ((x) << 16)
#define SPLL_LOLEN_MASK (0xf << 16)
#define CG_SPLL_FUNC_CNTL_2 0x604
#define SCLK_MUX_SEL(x) ((x) << 0)
#define SCLK_MUX_SEL_MASK (0x1ff << 0)
#define CG_SPLL_FUNC_CNTL_3 0x608
#define SPLL_FB_DIV(x) ((x) << 0)
#define SPLL_FB_DIV_MASK (0x3ffffff << 0)
#define SPLL_DITHEN (1 << 28)
#define SPLL_CNTL_MODE 0x610
#define SPLL_DIV_SYNC (1 << 5)
#define MPLL_AD_FUNC_CNTL 0x624
#define CLKF(x) ((x) << 0)
#define CLKF_MASK (0x7f << 0)
#define CLKR(x) ((x) << 7)
#define CLKR_MASK (0x1f << 7)
#define CLKFRAC(x) ((x) << 12)
#define CLKFRAC_MASK (0x1f << 12)
#define YCLK_POST_DIV(x) ((x) << 17)
#define YCLK_POST_DIV_MASK (3 << 17)
#define IBIAS(x) ((x) << 20)
#define IBIAS_MASK (0x3ff << 20)
#define RESET (1 << 30)
#define PDNB (1 << 31)
#define MPLL_AD_FUNC_CNTL_2 0x628
#define BYPASS (1 << 19)
#define BIAS_GEN_PDNB (1 << 24)
#define RESET_EN (1 << 25)
#define VCO_MODE (1 << 29)
#define MPLL_DQ_FUNC_CNTL 0x62c
#define MPLL_DQ_FUNC_CNTL_2 0x630
#define GENERAL_PWRMGT 0x63c
# define GLOBAL_PWRMGT_EN (1 << 0)
# define STATIC_PM_EN (1 << 1)
# define THERMAL_PROTECTION_DIS (1 << 2)
# define THERMAL_PROTECTION_TYPE (1 << 3)
# define ENABLE_GEN2PCIE (1 << 4)
# define ENABLE_GEN2XSP (1 << 5)
# define SW_SMIO_INDEX(x) ((x) << 6)
# define SW_SMIO_INDEX_MASK (3 << 6)
# define SW_SMIO_INDEX_SHIFT 6
# define LOW_VOLT_D2_ACPI (1 << 8)
# define LOW_VOLT_D3_ACPI (1 << 9)
# define VOLT_PWRMGT_EN (1 << 10)
# define BACKBIAS_PAD_EN (1 << 18)
# define BACKBIAS_VALUE (1 << 19)
# define DYN_SPREAD_SPECTRUM_EN (1 << 23)
# define AC_DC_SW (1 << 24)
#define CG_TPC 0x640
#define SCLK_PWRMGT_CNTL 0x644
# define SCLK_PWRMGT_OFF (1 << 0)
# define SCLK_LOW_D1 (1 << 1)
# define FIR_RESET (1 << 4)
# define FIR_FORCE_TREND_SEL (1 << 5)
# define FIR_TREND_MODE (1 << 6)
# define DYN_GFX_CLK_OFF_EN (1 << 7)
# define GFX_CLK_FORCE_ON (1 << 8)
# define GFX_CLK_REQUEST_OFF (1 << 9)
# define GFX_CLK_FORCE_OFF (1 << 10)
# define GFX_CLK_OFF_ACPI_D1 (1 << 11)
# define GFX_CLK_OFF_ACPI_D2 (1 << 12)
# define GFX_CLK_OFF_ACPI_D3 (1 << 13)
#define MCLK_PWRMGT_CNTL 0x648
# define DLL_SPEED(x) ((x) << 0)
# define DLL_SPEED_MASK (0x1f << 0)
# define MPLL_PWRMGT_OFF (1 << 5)
# define DLL_READY (1 << 6)
# define MC_INT_CNTL (1 << 7)
# define MRDCKA0_SLEEP (1 << 8)
# define MRDCKA1_SLEEP (1 << 9)
# define MRDCKB0_SLEEP (1 << 10)
# define MRDCKB1_SLEEP (1 << 11)
# define MRDCKC0_SLEEP (1 << 12)
# define MRDCKC1_SLEEP (1 << 13)
# define MRDCKD0_SLEEP (1 << 14)
# define MRDCKD1_SLEEP (1 << 15)
# define MRDCKA0_RESET (1 << 16)
# define MRDCKA1_RESET (1 << 17)
# define MRDCKB0_RESET (1 << 18)
# define MRDCKB1_RESET (1 << 19)
# define MRDCKC0_RESET (1 << 20)
# define MRDCKC1_RESET (1 << 21)
# define MRDCKD0_RESET (1 << 22)
# define MRDCKD1_RESET (1 << 23)
# define DLL_READY_READ (1 << 24)
# define USE_DISPLAY_GAP (1 << 25)
# define USE_DISPLAY_URGENT_NORMAL (1 << 26)
# define MPLL_TURNOFF_D2 (1 << 28)
#define DLL_CNTL 0x64c
# define MRDCKA0_BYPASS (1 << 24)
# define MRDCKA1_BYPASS (1 << 25)
# define MRDCKB0_BYPASS (1 << 26)
# define MRDCKB1_BYPASS (1 << 27)
# define MRDCKC0_BYPASS (1 << 28)
# define MRDCKC1_BYPASS (1 << 29)
# define MRDCKD0_BYPASS (1 << 30)
# define MRDCKD1_BYPASS (1 << 31)
#define MPLL_TIME 0x654
# define MPLL_LOCK_TIME(x) ((x) << 0)
# define MPLL_LOCK_TIME_MASK (0xffff << 0)
# define MPLL_RESET_TIME(x) ((x) << 16)
# define MPLL_RESET_TIME_MASK (0xffff << 16)
#define CG_CLKPIN_CNTL 0x660
# define MUX_TCLK_TO_XCLK (1 << 8)
# define XTALIN_DIVIDE (1 << 9)
#define S0_VID_LOWER_SMIO_CNTL 0x678
#define S1_VID_LOWER_SMIO_CNTL 0x67c
#define S2_VID_LOWER_SMIO_CNTL 0x680
#define S3_VID_LOWER_SMIO_CNTL 0x684
#define CG_FTV 0x690
#define CG_FFCT_0 0x694
# define UTC_0(x) ((x) << 0)
# define UTC_0_MASK (0x3ff << 0)
# define DTC_0(x) ((x) << 10)
# define DTC_0_MASK (0x3ff << 10)
#define CG_BSP 0x6d0
# define BSP(x) ((x) << 0)
# define BSP_MASK (0xffff << 0)
# define BSU(x) ((x) << 16)
# define BSU_MASK (0xf << 16)
#define CG_AT 0x6d4
# define CG_R(x) ((x) << 0)
# define CG_R_MASK (0xffff << 0)
# define CG_L(x) ((x) << 16)
# define CG_L_MASK (0xffff << 16)
#define CG_GIT 0x6d8
# define CG_GICST(x) ((x) << 0)
# define CG_GICST_MASK (0xffff << 0)
# define CG_GIPOT(x) ((x) << 16)
# define CG_GIPOT_MASK (0xffff << 16)
#define CG_SSP 0x6e8
# define SST(x) ((x) << 0)
# define SST_MASK (0xffff << 0)
# define SSTU(x) ((x) << 16)
# define SSTU_MASK (0xf << 16)
#define CG_DISPLAY_GAP_CNTL 0x714
# define DISP1_GAP(x) ((x) << 0)
# define DISP1_GAP_MASK (3 << 0)
# define DISP2_GAP(x) ((x) << 2)
# define DISP2_GAP_MASK (3 << 2)
# define VBI_TIMER_COUNT(x) ((x) << 4)
# define VBI_TIMER_COUNT_MASK (0x3fff << 4)
# define VBI_TIMER_UNIT(x) ((x) << 20)
# define VBI_TIMER_UNIT_MASK (7 << 20)
# define DISP1_GAP_MCHG(x) ((x) << 24)
# define DISP1_GAP_MCHG_MASK (3 << 24)
# define DISP2_GAP_MCHG(x) ((x) << 26)
# define DISP2_GAP_MCHG_MASK (3 << 26)
#define CG_SPLL_SPREAD_SPECTRUM 0x790
#define SSEN (1 << 0)
#define CLKS(x) ((x) << 4)
#define CLKS_MASK (0xfff << 4)
#define CG_SPLL_SPREAD_SPECTRUM_2 0x794
#define CLKV(x) ((x) << 0)
#define CLKV_MASK (0x3ffffff << 0)
#define CG_MPLL_SPREAD_SPECTRUM 0x798
#define CG_UPLL_SPREAD_SPECTRUM 0x79c
# define SSEN_MASK 0x00000001
#define CG_CGTT_LOCAL_0 0x7d0
#define CG_CGTT_LOCAL_1 0x7d4
#define BIOS_SCRATCH_4 0x1734
#define MC_SEQ_MISC0 0x2a00
#define MC_SEQ_MISC0_GDDR5_SHIFT 28
#define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000
#define MC_SEQ_MISC0_GDDR5_VALUE 5
#define MC_ARB_SQM_RATIO 0x2770
#define STATE0(x) ((x) << 0)
#define STATE0_MASK (0xff << 0)
#define STATE1(x) ((x) << 8)
#define STATE1_MASK (0xff << 8)
#define STATE2(x) ((x) << 16)
#define STATE2_MASK (0xff << 16)
#define STATE3(x) ((x) << 24)
#define STATE3_MASK (0xff << 24)
#define MC_ARB_RFSH_RATE 0x27b0
#define POWERMODE0(x) ((x) << 0)
#define POWERMODE0_MASK (0xff << 0)
#define POWERMODE1(x) ((x) << 8)
#define POWERMODE1_MASK (0xff << 8)
#define POWERMODE2(x) ((x) << 16)
#define POWERMODE2_MASK (0xff << 16)
#define POWERMODE3(x) ((x) << 24)
#define POWERMODE3_MASK (0xff << 24)
#define CGTS_SM_CTRL_REG 0x9150
/* Registers */
#define CB_COLOR0_BASE 0x28040
#define CB_COLOR1_BASE 0x28044
@ -86,8 +322,8 @@
#define CONFIG_MEMSIZE 0x5428
#define CP_ME_CNTL 0x86D8
#define CP_ME_HALT (1<<28)
#define CP_PFP_HALT (1<<26)
#define CP_ME_HALT (1 << 28)
#define CP_PFP_HALT (1 << 26)
#define CP_ME_RAM_DATA 0xC160
#define CP_ME_RAM_RADDR 0xC158
#define CP_ME_RAM_WADDR 0xC15C
@ -157,9 +393,22 @@
#define GUI_ACTIVE (1<<31)
#define GRBM_STATUS2 0x8014
#define CG_CLKPIN_CNTL 0x660
# define MUX_TCLK_TO_XCLK (1 << 8)
# define XTALIN_DIVIDE (1 << 9)
#define CG_THERMAL_CTRL 0x72C
#define DPM_EVENT_SRC(x) ((x) << 0)
#define DPM_EVENT_SRC_MASK (7 << 0)
#define DIG_THERM_DPM(x) ((x) << 14)
#define DIG_THERM_DPM_MASK 0x003FC000
#define DIG_THERM_DPM_SHIFT 14
#define CG_THERMAL_INT 0x734
#define DIG_THERM_INTH(x) ((x) << 8)
#define DIG_THERM_INTH_MASK 0x0000FF00
#define DIG_THERM_INTH_SHIFT 8
#define DIG_THERM_INTL(x) ((x) << 16)
#define DIG_THERM_INTL_MASK 0x00FF0000
#define DIG_THERM_INTL_SHIFT 16
#define THERM_INT_MASK_HIGH (1 << 24)
#define THERM_INT_MASK_LOW (1 << 25)
#define CG_MULT_THERMAL_STATUS 0x740
#define ASIC_T(x) ((x) << 16)
@ -662,7 +911,22 @@
#define D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x691c
#define D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x611c
/* PCIE link stuff */
/* PCIE indirect regs */
#define PCIE_P_CNTL 0x40
# define P_PLL_PWRDN_IN_L1L23 (1 << 3)
# define P_PLL_BUF_PDNB (1 << 4)
# define P_PLL_PDNB (1 << 9)
# define P_ALLOW_PRX_FRONTEND_SHUTOFF (1 << 12)
/* PCIE PORT regs */
#define PCIE_LC_CNTL 0xa0
# define LC_L0S_INACTIVITY(x) ((x) << 8)
# define LC_L0S_INACTIVITY_MASK (0xf << 8)
# define LC_L0S_INACTIVITY_SHIFT 8
# define LC_L1_INACTIVITY(x) ((x) << 12)
# define LC_L1_INACTIVITY_MASK (0xf << 12)
# define LC_L1_INACTIVITY_SHIFT 12
# define LC_PMI_TO_L1_DIS (1 << 16)
# define LC_ASPM_TO_L1_DIS (1 << 24)
#define PCIE_LC_TRAINING_CNTL 0xa1 /* PCIE_P */
#define PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE_P */
# define LC_LINK_WIDTH_SHIFT 0
@ -690,6 +954,9 @@
# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK (0x3 << 8)
# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT 3
# define LC_CURRENT_DATA_RATE (1 << 11)
# define LC_HW_VOLTAGE_IF_CONTROL(x) ((x) << 12)
# define LC_HW_VOLTAGE_IF_CONTROL_MASK (3 << 12)
# define LC_HW_VOLTAGE_IF_CONTROL_SHIFT 12
# define LC_VOLTAGE_TIMER_SEL_MASK (0xf << 14)
# define LC_CLR_FAILED_SPD_CHANGE_CNT (1 << 21)
# define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 23)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,227 @@
/*
* Copyright 2012 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.
*
*/
#ifndef __SI_DPM_H__
#define __SI_DPM_H__
#include "ni_dpm.h"
#include "sislands_smc.h"
enum si_cac_config_reg_type
{
SISLANDS_CACCONFIG_MMR = 0,
SISLANDS_CACCONFIG_CGIND,
SISLANDS_CACCONFIG_MAX
};
struct si_cac_config_reg
{
u32 offset;
u32 mask;
u32 shift;
u32 value;
enum si_cac_config_reg_type type;
};
struct si_powertune_data
{
u32 cac_window;
u32 l2_lta_window_size_default;
u8 lts_truncate_default;
u8 shift_n_default;
u8 operating_temp;
struct ni_leakage_coeffients leakage_coefficients;
u32 fixed_kt;
u32 lkge_lut_v0_percent;
u8 dc_cac[NISLANDS_DCCAC_MAX_LEVELS];
bool enable_powertune_by_default;
};
struct si_dyn_powertune_data
{
u32 cac_leakage;
s32 leakage_minimum_temperature;
u32 wintime;
u32 l2_lta_window_size;
u8 lts_truncate;
u8 shift_n;
u8 dc_pwr_value;
bool disable_uvd_powertune;
};
struct si_dte_data
{
u32 tau[SMC_SISLANDS_DTE_MAX_FILTER_STAGES];
u32 r[SMC_SISLANDS_DTE_MAX_FILTER_STAGES];
u32 k;
u32 t0;
u32 max_t;
u8 window_size;
u8 temp_select;
u8 dte_mode;
u8 tdep_count;
u8 t_limits[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE];
u32 tdep_tau[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE];
u32 tdep_r[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE];
u32 t_threshold;
bool enable_dte_by_default;
};
struct si_clock_registers {
u32 cg_spll_func_cntl;
u32 cg_spll_func_cntl_2;
u32 cg_spll_func_cntl_3;
u32 cg_spll_func_cntl_4;
u32 cg_spll_spread_spectrum;
u32 cg_spll_spread_spectrum_2;
u32 dll_cntl;
u32 mclk_pwrmgt_cntl;
u32 mpll_ad_func_cntl;
u32 mpll_dq_func_cntl;
u32 mpll_func_cntl;
u32 mpll_func_cntl_1;
u32 mpll_func_cntl_2;
u32 mpll_ss1;
u32 mpll_ss2;
};
struct si_mc_reg_entry {
u32 mclk_max;
u32 mc_data[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE];
};
struct si_mc_reg_table {
u8 last;
u8 num_entries;
u16 valid_flag;
struct si_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES];
SMC_NIslands_MCRegisterAddress mc_reg_address[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE];
};
#define SISLANDS_MCREGISTERTABLE_INITIAL_SLOT 0
#define SISLANDS_MCREGISTERTABLE_ACPI_SLOT 1
#define SISLANDS_MCREGISTERTABLE_ULV_SLOT 2
#define SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT 3
struct si_leakage_voltage_entry
{
u16 voltage;
u16 leakage_index;
};
#define SISLANDS_LEAKAGE_INDEX0 0xff01
#define SISLANDS_MAX_LEAKAGE_COUNT 4
struct si_leakage_voltage
{
u16 count;
struct si_leakage_voltage_entry entries[SISLANDS_MAX_LEAKAGE_COUNT];
};
#define SISLANDS_MAX_HARDWARE_POWERLEVELS 5
struct si_ulv_param {
bool supported;
u32 cg_ulv_control;
u32 cg_ulv_parameter;
u32 volt_change_delay;
struct rv7xx_pl pl;
bool one_pcie_lane_in_ulv;
};
struct si_power_info {
/* must be first! */
struct ni_power_info ni;
struct si_clock_registers clock_registers;
struct si_mc_reg_table mc_reg_table;
struct atom_voltage_table mvdd_voltage_table;
struct atom_voltage_table vddc_phase_shed_table;
struct si_leakage_voltage leakage_voltage;
u16 mvdd_bootup_value;
struct si_ulv_param ulv;
u32 max_cu;
/* pcie gen */
enum radeon_pcie_gen force_pcie_gen;
enum radeon_pcie_gen boot_pcie_gen;
enum radeon_pcie_gen acpi_pcie_gen;
u32 sys_pcie_mask;
/* flags */
bool enable_dte;
bool enable_ppm;
bool vddc_phase_shed_control;
bool pspp_notify_required;
bool sclk_deep_sleep_above_low;
/* smc offsets */
u32 sram_end;
u32 state_table_start;
u32 soft_regs_start;
u32 mc_reg_table_start;
u32 arb_table_start;
u32 cac_table_start;
u32 dte_table_start;
u32 spll_table_start;
u32 papm_cfg_table_start;
/* CAC stuff */
const struct si_cac_config_reg *cac_weights;
const struct si_cac_config_reg *lcac_config;
const struct si_cac_config_reg *cac_override;
const struct si_powertune_data *powertune_data;
struct si_dyn_powertune_data dyn_powertune_data;
/* DTE stuff */
struct si_dte_data dte_data;
/* scratch structs */
SMC_SIslands_MCRegisters smc_mc_reg_table;
SISLANDS_SMC_STATETABLE smc_statetable;
PP_SIslands_PAPMParameters papm_parm;
};
#define SISLANDS_INITIAL_STATE_ARB_INDEX 0
#define SISLANDS_ACPI_STATE_ARB_INDEX 1
#define SISLANDS_ULV_STATE_ARB_INDEX 2
#define SISLANDS_DRIVER_STATE_ARB_INDEX 3
#define SISLANDS_DPM2_MAX_PULSE_SKIP 256
#define SISLANDS_DPM2_NEAR_TDP_DEC 10
#define SISLANDS_DPM2_ABOVE_SAFE_INC 5
#define SISLANDS_DPM2_BELOW_SAFE_INC 20
#define SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT 80
#define SISLANDS_DPM2_MAXPS_PERCENT_H 99
#define SISLANDS_DPM2_MAXPS_PERCENT_M 99
#define SISLANDS_DPM2_SQ_RAMP_MAX_POWER 0x3FFF
#define SISLANDS_DPM2_SQ_RAMP_MIN_POWER 0x12
#define SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15
#define SISLANDS_DPM2_SQ_RAMP_STI_SIZE 0x1E
#define SISLANDS_DPM2_SQ_RAMP_LTI_RATIO 0xF
#define SISLANDS_DPM2_PWREFFICIENCYRATIO_MARGIN 10
#define SISLANDS_VRC_DFLT 0xC000B3
#define SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT 1687
#define SISLANDS_CGULVPARAMETER_DFLT 0x00040035
#define SISLANDS_CGULVCONTROL_DFLT 0x1f007550
#endif

View File

@ -0,0 +1,284 @@
/*
* Copyright 2011 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: Alex Deucher
*/
#include <linux/firmware.h>
#include "drmP.h"
#include "radeon.h"
#include "sid.h"
#include "ppsmc.h"
#include "radeon_ucode.h"
int si_set_smc_sram_address(struct radeon_device *rdev,
u32 smc_address, u32 limit)
{
if (smc_address & 3)
return -EINVAL;
if ((smc_address + 3) > limit)
return -EINVAL;
WREG32(SMC_IND_INDEX_0, smc_address);
WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
return 0;
}
int si_copy_bytes_to_smc(struct radeon_device *rdev,
u32 smc_start_address,
const u8 *src, u32 byte_count, u32 limit)
{
int ret;
u32 data, original_data, addr, extra_shift;
if (smc_start_address & 3)
return -EINVAL;
if ((smc_start_address + byte_count) > limit)
return -EINVAL;
addr = smc_start_address;
while (byte_count >= 4) {
/* SMC address space is BE */
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
ret = si_set_smc_sram_address(rdev, addr, limit);
if (ret)
return ret;
WREG32(SMC_IND_DATA_0, data);
src += 4;
byte_count -= 4;
addr += 4;
}
/* RMW for the final bytes */
if (byte_count > 0) {
data = 0;
ret = si_set_smc_sram_address(rdev, addr, limit);
if (ret)
return ret;
original_data = RREG32(SMC_IND_DATA_0);
extra_shift = 8 * (4 - byte_count);
while (byte_count > 0) {
/* SMC address space is BE */
data = (data << 8) + *src++;
byte_count--;
}
data <<= extra_shift;
data |= (original_data & ~((~0UL) << extra_shift));
ret = si_set_smc_sram_address(rdev, addr, limit);
if (ret)
return ret;
WREG32(SMC_IND_DATA_0, data);
}
return 0;
}
void si_start_smc(struct radeon_device *rdev)
{
u32 tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL);
tmp &= ~RST_REG;
WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp);
}
void si_reset_smc(struct radeon_device *rdev)
{
u32 tmp;
RREG32(CB_CGTT_SCLK_CTRL);
RREG32(CB_CGTT_SCLK_CTRL);
RREG32(CB_CGTT_SCLK_CTRL);
RREG32(CB_CGTT_SCLK_CTRL);
tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL);
tmp |= RST_REG;
WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp);
}
int si_program_jump_on_start(struct radeon_device *rdev)
{
static u8 data[] = { 0x0E, 0x00, 0x40, 0x40 };
return si_copy_bytes_to_smc(rdev, 0x0, data, 4, sizeof(data)+1);
}
void si_stop_smc_clock(struct radeon_device *rdev)
{
u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
tmp |= CK_DISABLE;
WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp);
}
void si_start_smc_clock(struct radeon_device *rdev)
{
u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
tmp &= ~CK_DISABLE;
WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp);
}
bool si_is_smc_running(struct radeon_device *rdev)
{
u32 rst = RREG32_SMC(SMC_SYSCON_RESET_CNTL);
u32 clk = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
if (!(rst & RST_REG) && !(clk & CK_DISABLE))
return true;
return false;
}
PPSMC_Result si_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg)
{
u32 tmp;
int i;
if (!si_is_smc_running(rdev))
return PPSMC_Result_Failed;
WREG32(SMC_MESSAGE_0, msg);
for (i = 0; i < rdev->usec_timeout; i++) {
tmp = RREG32(SMC_RESP_0);
if (tmp != 0)
break;
udelay(1);
}
tmp = RREG32(SMC_RESP_0);
return (PPSMC_Result)tmp;
}
PPSMC_Result si_wait_for_smc_inactive(struct radeon_device *rdev)
{
u32 tmp;
int i;
if (!si_is_smc_running(rdev))
return PPSMC_Result_OK;
for (i = 0; i < rdev->usec_timeout; i++) {
tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
if ((tmp & CKEN) == 0)
break;
udelay(1);
}
return PPSMC_Result_OK;
}
int si_load_smc_ucode(struct radeon_device *rdev, u32 limit)
{
u32 ucode_start_address;
u32 ucode_size;
const u8 *src;
u32 data;
if (!rdev->smc_fw)
return -EINVAL;
switch (rdev->family) {
case CHIP_TAHITI:
ucode_start_address = TAHITI_SMC_UCODE_START;
ucode_size = TAHITI_SMC_UCODE_SIZE;
break;
case CHIP_PITCAIRN:
ucode_start_address = PITCAIRN_SMC_UCODE_START;
ucode_size = PITCAIRN_SMC_UCODE_SIZE;
break;
case CHIP_VERDE:
ucode_start_address = VERDE_SMC_UCODE_START;
ucode_size = VERDE_SMC_UCODE_SIZE;
break;
case CHIP_OLAND:
ucode_start_address = OLAND_SMC_UCODE_START;
ucode_size = OLAND_SMC_UCODE_SIZE;
break;
case CHIP_HAINAN:
ucode_start_address = HAINAN_SMC_UCODE_START;
ucode_size = HAINAN_SMC_UCODE_SIZE;
break;
default:
DRM_ERROR("unknown asic in smc ucode loader\n");
BUG();
}
if (ucode_size & 3)
return -EINVAL;
src = (const u8 *)rdev->smc_fw->data;
WREG32(SMC_IND_INDEX_0, ucode_start_address);
WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
while (ucode_size >= 4) {
/* SMC address space is BE */
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
WREG32(SMC_IND_DATA_0, data);
src += 4;
ucode_size -= 4;
}
WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
return 0;
}
int si_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
u32 *value, u32 limit)
{
int ret;
ret = si_set_smc_sram_address(rdev, smc_address, limit);
if (ret)
return ret;
*value = RREG32(SMC_IND_DATA_0);
return 0;
}
int si_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
u32 value, u32 limit)
{
int ret;
ret = si_set_smc_sram_address(rdev, smc_address, limit);
if (ret)
return ret;
WREG32(SMC_IND_DATA_0, value);
return 0;
}

View File

@ -30,6 +30,94 @@
#define VERDE_GB_ADDR_CONFIG_GOLDEN 0x12010002
#define HAINAN_GB_ADDR_CONFIG_GOLDEN 0x02010001
#define SI_MAX_SH_GPRS 256
#define SI_MAX_TEMP_GPRS 16
#define SI_MAX_SH_THREADS 256
#define SI_MAX_SH_STACK_ENTRIES 4096
#define SI_MAX_FRC_EOV_CNT 16384
#define SI_MAX_BACKENDS 8
#define SI_MAX_BACKENDS_MASK 0xFF
#define SI_MAX_BACKENDS_PER_SE_MASK 0x0F
#define SI_MAX_SIMDS 12
#define SI_MAX_SIMDS_MASK 0x0FFF
#define SI_MAX_SIMDS_PER_SE_MASK 0x00FF
#define SI_MAX_PIPES 8
#define SI_MAX_PIPES_MASK 0xFF
#define SI_MAX_PIPES_PER_SIMD_MASK 0x3F
#define SI_MAX_LDS_NUM 0xFFFF
#define SI_MAX_TCC 16
#define SI_MAX_TCC_MASK 0xFFFF
/* SMC IND accessor regs */
#define SMC_IND_INDEX_0 0x200
#define SMC_IND_DATA_0 0x204
#define SMC_IND_ACCESS_CNTL 0x228
# define AUTO_INCREMENT_IND_0 (1 << 0)
#define SMC_MESSAGE_0 0x22c
#define SMC_RESP_0 0x230
/* CG IND registers are accessed via SMC indirect space + SMC_CG_IND_START */
#define SMC_CG_IND_START 0xc0030000
#define SMC_CG_IND_END 0xc0040000
#define CG_CGTT_LOCAL_0 0x400
#define CG_CGTT_LOCAL_1 0x401
/* SMC IND registers */
#define SMC_SYSCON_RESET_CNTL 0x80000000
# define RST_REG (1 << 0)
#define SMC_SYSCON_CLOCK_CNTL_0 0x80000004
# define CK_DISABLE (1 << 0)
# define CKEN (1 << 24)
#define VGA_HDP_CONTROL 0x328
#define VGA_MEMORY_DISABLE (1 << 4)
#define DCCG_DISP_SLOW_SELECT_REG 0x4fc
#define DCCG_DISP1_SLOW_SELECT(x) ((x) << 0)
#define DCCG_DISP1_SLOW_SELECT_MASK (7 << 0)
#define DCCG_DISP1_SLOW_SELECT_SHIFT 0
#define DCCG_DISP2_SLOW_SELECT(x) ((x) << 4)
#define DCCG_DISP2_SLOW_SELECT_MASK (7 << 4)
#define DCCG_DISP2_SLOW_SELECT_SHIFT 4
#define CG_SPLL_FUNC_CNTL 0x600
#define SPLL_RESET (1 << 0)
#define SPLL_SLEEP (1 << 1)
#define SPLL_BYPASS_EN (1 << 3)
#define SPLL_REF_DIV(x) ((x) << 4)
#define SPLL_REF_DIV_MASK (0x3f << 4)
#define SPLL_PDIV_A(x) ((x) << 20)
#define SPLL_PDIV_A_MASK (0x7f << 20)
#define SPLL_PDIV_A_SHIFT 20
#define CG_SPLL_FUNC_CNTL_2 0x604
#define SCLK_MUX_SEL(x) ((x) << 0)
#define SCLK_MUX_SEL_MASK (0x1ff << 0)
#define CG_SPLL_FUNC_CNTL_3 0x608
#define SPLL_FB_DIV(x) ((x) << 0)
#define SPLL_FB_DIV_MASK (0x3ffffff << 0)
#define SPLL_FB_DIV_SHIFT 0
#define SPLL_DITHEN (1 << 28)
#define CG_SPLL_FUNC_CNTL_4 0x60c
#define SPLL_CNTL_MODE 0x618
# define SPLL_REFCLK_SEL(x) ((x) << 8)
# define SPLL_REFCLK_SEL_MASK 0xFF00
#define CG_SPLL_SPREAD_SPECTRUM 0x620
#define SSEN (1 << 0)
#define CLK_S(x) ((x) << 4)
#define CLK_S_MASK (0xfff << 4)
#define CLK_S_SHIFT 4
#define CG_SPLL_SPREAD_SPECTRUM_2 0x624
#define CLK_V(x) ((x) << 0)
#define CLK_V_MASK (0x3ffffff << 0)
#define CLK_V_SHIFT 0
#define CG_SPLL_AUTOSCALE_CNTL 0x62c
# define AUTOSCALE_ON_SS_CLEAR (1 << 9)
/* discrete uvd clocks */
#define CG_UPLL_FUNC_CNTL 0x634
# define UPLL_RESET_MASK 0x00000001
@ -59,6 +147,45 @@
#define CG_UPLL_SPREAD_SPECTRUM 0x650
# define SSEN_MASK 0x00000001
#define MPLL_BYPASSCLK_SEL 0x65c
# define MPLL_CLKOUT_SEL(x) ((x) << 8)
# define MPLL_CLKOUT_SEL_MASK 0xFF00
#define CG_CLKPIN_CNTL 0x660
# define XTALIN_DIVIDE (1 << 1)
# define BCLK_AS_XCLK (1 << 2)
#define CG_CLKPIN_CNTL_2 0x664
# define FORCE_BIF_REFCLK_EN (1 << 3)
# define MUX_TCLK_TO_XCLK (1 << 8)
#define THM_CLK_CNTL 0x66c
# define CMON_CLK_SEL(x) ((x) << 0)
# define CMON_CLK_SEL_MASK 0xFF
# define TMON_CLK_SEL(x) ((x) << 8)
# define TMON_CLK_SEL_MASK 0xFF00
#define MISC_CLK_CNTL 0x670
# define DEEP_SLEEP_CLK_SEL(x) ((x) << 0)
# define DEEP_SLEEP_CLK_SEL_MASK 0xFF
# define ZCLK_SEL(x) ((x) << 8)
# define ZCLK_SEL_MASK 0xFF00
#define CG_THERMAL_CTRL 0x700
#define DPM_EVENT_SRC(x) ((x) << 0)
#define DPM_EVENT_SRC_MASK (7 << 0)
#define DIG_THERM_DPM(x) ((x) << 14)
#define DIG_THERM_DPM_MASK 0x003FC000
#define DIG_THERM_DPM_SHIFT 14
#define CG_THERMAL_INT 0x708
#define DIG_THERM_INTH(x) ((x) << 8)
#define DIG_THERM_INTH_MASK 0x0000FF00
#define DIG_THERM_INTH_SHIFT 8
#define DIG_THERM_INTL(x) ((x) << 16)
#define DIG_THERM_INTL_MASK 0x00FF0000
#define DIG_THERM_INTL_SHIFT 16
#define THERM_INT_MASK_HIGH (1 << 24)
#define THERM_INT_MASK_LOW (1 << 25)
#define CG_MULT_THERMAL_STATUS 0x714
#define ASIC_MAX_TEMP(x) ((x) << 0)
#define ASIC_MAX_TEMP_MASK 0x000001ff
@ -67,31 +194,85 @@
#define CTF_TEMP_MASK 0x0003fe00
#define CTF_TEMP_SHIFT 9
#define SI_MAX_SH_GPRS 256
#define SI_MAX_TEMP_GPRS 16
#define SI_MAX_SH_THREADS 256
#define SI_MAX_SH_STACK_ENTRIES 4096
#define SI_MAX_FRC_EOV_CNT 16384
#define SI_MAX_BACKENDS 8
#define SI_MAX_BACKENDS_MASK 0xFF
#define SI_MAX_BACKENDS_PER_SE_MASK 0x0F
#define SI_MAX_SIMDS 12
#define SI_MAX_SIMDS_MASK 0x0FFF
#define SI_MAX_SIMDS_PER_SE_MASK 0x00FF
#define SI_MAX_PIPES 8
#define SI_MAX_PIPES_MASK 0xFF
#define SI_MAX_PIPES_PER_SIMD_MASK 0x3F
#define SI_MAX_LDS_NUM 0xFFFF
#define SI_MAX_TCC 16
#define SI_MAX_TCC_MASK 0xFFFF
#define GENERAL_PWRMGT 0x780
# define GLOBAL_PWRMGT_EN (1 << 0)
# define STATIC_PM_EN (1 << 1)
# define THERMAL_PROTECTION_DIS (1 << 2)
# define THERMAL_PROTECTION_TYPE (1 << 3)
# define SW_SMIO_INDEX(x) ((x) << 6)
# define SW_SMIO_INDEX_MASK (1 << 6)
# define SW_SMIO_INDEX_SHIFT 6
# define VOLT_PWRMGT_EN (1 << 10)
# define DYN_SPREAD_SPECTRUM_EN (1 << 23)
#define CG_TPC 0x784
#define SCLK_PWRMGT_CNTL 0x788
# define SCLK_PWRMGT_OFF (1 << 0)
# define SCLK_LOW_D1 (1 << 1)
# define FIR_RESET (1 << 4)
# define FIR_FORCE_TREND_SEL (1 << 5)
# define FIR_TREND_MODE (1 << 6)
# define DYN_GFX_CLK_OFF_EN (1 << 7)
# define GFX_CLK_FORCE_ON (1 << 8)
# define GFX_CLK_REQUEST_OFF (1 << 9)
# define GFX_CLK_FORCE_OFF (1 << 10)
# define GFX_CLK_OFF_ACPI_D1 (1 << 11)
# define GFX_CLK_OFF_ACPI_D2 (1 << 12)
# define GFX_CLK_OFF_ACPI_D3 (1 << 13)
# define DYN_LIGHT_SLEEP_EN (1 << 14)
#define VGA_HDP_CONTROL 0x328
#define VGA_MEMORY_DISABLE (1 << 4)
#define CG_FTV 0x7bc
#define CG_CLKPIN_CNTL 0x660
# define XTALIN_DIVIDE (1 << 1)
#define CG_CLKPIN_CNTL_2 0x664
# define MUX_TCLK_TO_XCLK (1 << 8)
#define CG_FFCT_0 0x7c0
# define UTC_0(x) ((x) << 0)
# define UTC_0_MASK (0x3ff << 0)
# define DTC_0(x) ((x) << 10)
# define DTC_0_MASK (0x3ff << 10)
#define CG_BSP 0x7fc
# define BSP(x) ((x) << 0)
# define BSP_MASK (0xffff << 0)
# define BSU(x) ((x) << 16)
# define BSU_MASK (0xf << 16)
#define CG_AT 0x800
# define CG_R(x) ((x) << 0)
# define CG_R_MASK (0xffff << 0)
# define CG_L(x) ((x) << 16)
# define CG_L_MASK (0xffff << 16)
#define CG_GIT 0x804
# define CG_GICST(x) ((x) << 0)
# define CG_GICST_MASK (0xffff << 0)
# define CG_GIPOT(x) ((x) << 16)
# define CG_GIPOT_MASK (0xffff << 16)
#define CG_SSP 0x80c
# define SST(x) ((x) << 0)
# define SST_MASK (0xffff << 0)
# define SSTU(x) ((x) << 16)
# define SSTU_MASK (0xf << 16)
#define CG_DISPLAY_GAP_CNTL 0x828
# define DISP1_GAP(x) ((x) << 0)
# define DISP1_GAP_MASK (3 << 0)
# define DISP2_GAP(x) ((x) << 2)
# define DISP2_GAP_MASK (3 << 2)
# define VBI_TIMER_COUNT(x) ((x) << 4)
# define VBI_TIMER_COUNT_MASK (0x3fff << 4)
# define VBI_TIMER_UNIT(x) ((x) << 20)
# define VBI_TIMER_UNIT_MASK (7 << 20)
# define DISP1_GAP_MCHG(x) ((x) << 24)
# define DISP1_GAP_MCHG_MASK (3 << 24)
# define DISP2_GAP_MCHG(x) ((x) << 26)
# define DISP2_GAP_MCHG_MASK (3 << 26)
#define CG_ULV_CONTROL 0x878
#define CG_ULV_PARAMETER 0x87c
#define SMC_SCRATCH0 0x884
#define CG_CAC_CTRL 0x8b8
# define CAC_WINDOW(x) ((x) << 0)
# define CAC_WINDOW_MASK 0x00ffffff
#define DMIF_ADDR_CONFIG 0xBD4
@ -203,6 +384,10 @@
#define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157C
#define VM_CONTEXT1_PAGE_TABLE_END_ADDR 0x1580
#define VM_L2_CG 0x15c0
#define MC_CG_ENABLE (1 << 18)
#define MC_LS_ENABLE (1 << 19)
#define MC_SHARED_CHMAP 0x2004
#define NOOFCHAN_SHIFT 12
#define NOOFCHAN_MASK 0x0000f000
@ -228,6 +413,17 @@
#define MC_SHARED_BLACKOUT_CNTL 0x20ac
#define MC_HUB_MISC_HUB_CG 0x20b8
#define MC_HUB_MISC_VM_CG 0x20bc
#define MC_HUB_MISC_SIP_CG 0x20c0
#define MC_XPB_CLK_GAT 0x2478
#define MC_CITF_MISC_RD_CG 0x2648
#define MC_CITF_MISC_WR_CG 0x264c
#define MC_CITF_MISC_VM_CG 0x2650
#define MC_ARB_RAMCFG 0x2760
#define NOOFBANK_SHIFT 0
#define NOOFBANK_MASK 0x00000003
@ -243,6 +439,23 @@
#define NOOFGROUPS_SHIFT 12
#define NOOFGROUPS_MASK 0x00001000
#define MC_ARB_DRAM_TIMING 0x2774
#define MC_ARB_DRAM_TIMING2 0x2778
#define MC_ARB_BURST_TIME 0x2808
#define STATE0(x) ((x) << 0)
#define STATE0_MASK (0x1f << 0)
#define STATE0_SHIFT 0
#define STATE1(x) ((x) << 5)
#define STATE1_MASK (0x1f << 5)
#define STATE1_SHIFT 5
#define STATE2(x) ((x) << 10)
#define STATE2_MASK (0x1f << 10)
#define STATE2_SHIFT 10
#define STATE3(x) ((x) << 15)
#define STATE3_MASK (0x1f << 15)
#define STATE3_SHIFT 15
#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x2808
#define TRAIN_DONE_D0 (1 << 30)
#define TRAIN_DONE_D1 (1 << 31)
@ -250,13 +463,105 @@
#define MC_SEQ_SUP_CNTL 0x28c8
#define RUN_MASK (1 << 0)
#define MC_SEQ_SUP_PGM 0x28cc
#define MC_PMG_AUTO_CMD 0x28d0
#define MC_IO_PAD_CNTL_D0 0x29d0
#define MEM_FALL_OUT_CMD (1 << 8)
#define MC_SEQ_RAS_TIMING 0x28a0
#define MC_SEQ_CAS_TIMING 0x28a4
#define MC_SEQ_MISC_TIMING 0x28a8
#define MC_SEQ_MISC_TIMING2 0x28ac
#define MC_SEQ_PMG_TIMING 0x28b0
#define MC_SEQ_RD_CTL_D0 0x28b4
#define MC_SEQ_RD_CTL_D1 0x28b8
#define MC_SEQ_WR_CTL_D0 0x28bc
#define MC_SEQ_WR_CTL_D1 0x28c0
#define MC_SEQ_MISC0 0x2a00
#define MC_SEQ_MISC0_VEN_ID_SHIFT 8
#define MC_SEQ_MISC0_VEN_ID_MASK 0x00000f00
#define MC_SEQ_MISC0_VEN_ID_VALUE 3
#define MC_SEQ_MISC0_REV_ID_SHIFT 12
#define MC_SEQ_MISC0_REV_ID_MASK 0x0000f000
#define MC_SEQ_MISC0_REV_ID_VALUE 1
#define MC_SEQ_MISC0_GDDR5_SHIFT 28
#define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000
#define MC_SEQ_MISC0_GDDR5_VALUE 5
#define MC_SEQ_MISC1 0x2a04
#define MC_SEQ_RESERVE_M 0x2a08
#define MC_PMG_CMD_EMRS 0x2a0c
#define MC_SEQ_IO_DEBUG_INDEX 0x2a44
#define MC_SEQ_IO_DEBUG_DATA 0x2a48
#define MC_SEQ_MISC5 0x2a54
#define MC_SEQ_MISC6 0x2a58
#define MC_SEQ_MISC7 0x2a64
#define MC_SEQ_RAS_TIMING_LP 0x2a6c
#define MC_SEQ_CAS_TIMING_LP 0x2a70
#define MC_SEQ_MISC_TIMING_LP 0x2a74
#define MC_SEQ_MISC_TIMING2_LP 0x2a78
#define MC_SEQ_WR_CTL_D0_LP 0x2a7c
#define MC_SEQ_WR_CTL_D1_LP 0x2a80
#define MC_SEQ_PMG_CMD_EMRS_LP 0x2a84
#define MC_SEQ_PMG_CMD_MRS_LP 0x2a88
#define MC_PMG_CMD_MRS 0x2aac
#define MC_SEQ_RD_CTL_D0_LP 0x2b1c
#define MC_SEQ_RD_CTL_D1_LP 0x2b20
#define MC_PMG_CMD_MRS1 0x2b44
#define MC_SEQ_PMG_CMD_MRS1_LP 0x2b48
#define MC_SEQ_PMG_TIMING_LP 0x2b4c
#define MC_SEQ_WR_CTL_2 0x2b54
#define MC_SEQ_WR_CTL_2_LP 0x2b58
#define MC_PMG_CMD_MRS2 0x2b5c
#define MC_SEQ_PMG_CMD_MRS2_LP 0x2b60
#define MCLK_PWRMGT_CNTL 0x2ba0
# define DLL_SPEED(x) ((x) << 0)
# define DLL_SPEED_MASK (0x1f << 0)
# define DLL_READY (1 << 6)
# define MC_INT_CNTL (1 << 7)
# define MRDCK0_PDNB (1 << 8)
# define MRDCK1_PDNB (1 << 9)
# define MRDCK0_RESET (1 << 16)
# define MRDCK1_RESET (1 << 17)
# define DLL_READY_READ (1 << 24)
#define DLL_CNTL 0x2ba4
# define MRDCK0_BYPASS (1 << 24)
# define MRDCK1_BYPASS (1 << 25)
#define MPLL_FUNC_CNTL 0x2bb4
#define BWCTRL(x) ((x) << 20)
#define BWCTRL_MASK (0xff << 20)
#define MPLL_FUNC_CNTL_1 0x2bb8
#define VCO_MODE(x) ((x) << 0)
#define VCO_MODE_MASK (3 << 0)
#define CLKFRAC(x) ((x) << 4)
#define CLKFRAC_MASK (0xfff << 4)
#define CLKF(x) ((x) << 16)
#define CLKF_MASK (0xfff << 16)
#define MPLL_FUNC_CNTL_2 0x2bbc
#define MPLL_AD_FUNC_CNTL 0x2bc0
#define YCLK_POST_DIV(x) ((x) << 0)
#define YCLK_POST_DIV_MASK (7 << 0)
#define MPLL_DQ_FUNC_CNTL 0x2bc4
#define YCLK_SEL(x) ((x) << 4)
#define YCLK_SEL_MASK (1 << 4)
#define MPLL_SS1 0x2bcc
#define CLKV(x) ((x) << 0)
#define CLKV_MASK (0x3ffffff << 0)
#define MPLL_SS2 0x2bd0
#define CLKS(x) ((x) << 0)
#define CLKS_MASK (0xfff << 0)
#define HDP_HOST_PATH_CNTL 0x2C00
#define HDP_NONSURFACE_BASE 0x2C04
#define HDP_NONSURFACE_INFO 0x2C08
@ -266,6 +571,8 @@
#define HDP_MISC_CNTL 0x2F4C
#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0)
#define ATC_MISC_CG 0x3350
#define IH_RB_CNTL 0x3e00
# define IH_RB_ENABLE (1 << 0)
# define IH_IB_SIZE(x) ((x) << 1) /* log2 */
@ -424,6 +731,9 @@
# define DC_HPDx_RX_INT_TIMER(x) ((x) << 16)
# define DC_HPDx_EN (1 << 28)
#define DPG_PIPE_STUTTER_CONTROL 0x6cd4
# define STUTTER_ENABLE (1 << 0)
/* 0x6e98, 0x7a98, 0x10698, 0x11298, 0x11e98, 0x12a98 */
#define CRTC_STATUS_FRAME_COUNT 0x6e98
@ -599,6 +909,24 @@
#define SQC_CACHES 0x8C08
#define SQ_POWER_THROTTLE 0x8e58
#define MIN_POWER(x) ((x) << 0)
#define MIN_POWER_MASK (0x3fff << 0)
#define MIN_POWER_SHIFT 0
#define MAX_POWER(x) ((x) << 16)
#define MAX_POWER_MASK (0x3fff << 16)
#define MAX_POWER_SHIFT 0
#define SQ_POWER_THROTTLE2 0x8e5c
#define MAX_POWER_DELTA(x) ((x) << 0)
#define MAX_POWER_DELTA_MASK (0x3fff << 0)
#define MAX_POWER_DELTA_SHIFT 0
#define STI_SIZE(x) ((x) << 16)
#define STI_SIZE_MASK (0x3ff << 16)
#define STI_SIZE_SHIFT 16
#define LTI_RATIO(x) ((x) << 27)
#define LTI_RATIO_MASK (0xf << 27)
#define LTI_RATIO_SHIFT 27
#define SX_DEBUG_1 0x9060
#define SPI_STATIC_THREAD_MGMT_1 0x90E0
@ -616,6 +944,11 @@
#define CGTS_USER_TCC_DISABLE 0x914C
#define TCC_DISABLE_MASK 0xFFFF0000
#define TCC_DISABLE_SHIFT 16
#define CGTS_SM_CTRL_REG 0x9150
#define OVERRIDE (1 << 21)
#define LS_OVERRIDE (1 << 22)
#define SPI_LB_CU_MASK 0x9354
#define TA_CNTL_AUX 0x9508
@ -705,6 +1038,8 @@
#define CB_PERFCOUNTER3_SELECT0 0x9a38
#define CB_PERFCOUNTER3_SELECT1 0x9a3c
#define CB_CGTT_SCLK_CTRL 0x9a60
#define GC_USER_RB_BACKEND_DISABLE 0x9B7C
#define BACKEND_DISABLE_MASK 0x00FF0000
#define BACKEND_DISABLE_SHIFT 16
@ -762,6 +1097,9 @@
# define CP_RINGID1_INT_STAT (1 << 30)
# define CP_RINGID0_INT_STAT (1 << 31)
#define CP_MEM_SLP_CNTL 0xC1E4
# define CP_MEM_LS_EN (1 << 0)
#define CP_DEBUG 0xC1FC
#define RLC_CNTL 0xC300
@ -769,6 +1107,7 @@
#define RLC_RL_BASE 0xC304
#define RLC_RL_SIZE 0xC308
#define RLC_LB_CNTL 0xC30C
# define LOAD_BALANCE_ENABLE (1 << 0)
#define RLC_SAVE_AND_RESTORE_BASE 0xC310
#define RLC_LB_CNTR_MAX 0xC314
#define RLC_LB_CNTR_INIT 0xC318
@ -783,6 +1122,56 @@
#define RLC_CAPTURE_GPU_CLOCK_COUNT 0xC340
#define RLC_MC_CNTL 0xC344
#define RLC_UCODE_CNTL 0xC348
#define RLC_STAT 0xC34C
# define RLC_BUSY_STATUS (1 << 0)
# define GFX_POWER_STATUS (1 << 1)
# define GFX_CLOCK_STATUS (1 << 2)
# define GFX_LS_STATUS (1 << 3)
#define RLC_PG_CNTL 0xC35C
# define GFX_PG_ENABLE (1 << 0)
# define GFX_PG_SRC (1 << 1)
#define RLC_CGTT_MGCG_OVERRIDE 0xC400
#define RLC_CGCG_CGLS_CTRL 0xC404
# define CGCG_EN (1 << 0)
# define CGLS_EN (1 << 1)
#define RLC_TTOP_D 0xC414
# define RLC_PUD(x) ((x) << 0)
# define RLC_PUD_MASK (0xff << 0)
# define RLC_PDD(x) ((x) << 8)
# define RLC_PDD_MASK (0xff << 8)
# define RLC_TTPD(x) ((x) << 16)
# define RLC_TTPD_MASK (0xff << 16)
# define RLC_MSD(x) ((x) << 24)
# define RLC_MSD_MASK (0xff << 24)
#define RLC_LB_INIT_CU_MASK 0xC41C
#define RLC_PG_AO_CU_MASK 0xC42C
#define RLC_MAX_PG_CU 0xC430
# define MAX_PU_CU(x) ((x) << 0)
# define MAX_PU_CU_MASK (0xff << 0)
#define RLC_AUTO_PG_CTRL 0xC434
# define AUTO_PG_EN (1 << 0)
# define GRBM_REG_SGIT(x) ((x) << 3)
# define GRBM_REG_SGIT_MASK (0xffff << 3)
# define PG_AFTER_GRBM_REG_ST(x) ((x) << 19)
# define PG_AFTER_GRBM_REG_ST_MASK (0x1fff << 19)
#define RLC_SERDES_WR_MASTER_MASK_0 0xC454
#define RLC_SERDES_WR_MASTER_MASK_1 0xC458
#define RLC_SERDES_WR_CTRL 0xC45C
#define RLC_SERDES_MASTER_BUSY_0 0xC464
#define RLC_SERDES_MASTER_BUSY_1 0xC468
#define RLC_GCPM_GENERAL_3 0xC478
#define DB_RENDER_CONTROL 0x28000
#define DB_DEPTH_INFO 0x2803c
#define PA_SC_RASTER_CONFIG 0x28350
# define RASTER_CONFIG_RB_MAP_0 0
@ -829,6 +1218,146 @@
# define THREAD_TRACE_FLUSH (54 << 0)
# define THREAD_TRACE_FINISH (55 << 0)
/* PIF PHY0 registers idx/data 0x8/0xc */
#define PB0_PIF_CNTL 0x10
# define LS2_EXIT_TIME(x) ((x) << 17)
# define LS2_EXIT_TIME_MASK (0x7 << 17)
# define LS2_EXIT_TIME_SHIFT 17
#define PB0_PIF_PAIRING 0x11
# define MULTI_PIF (1 << 25)
#define PB0_PIF_PWRDOWN_0 0x12
# define PLL_POWER_STATE_IN_TXS2_0(x) ((x) << 7)
# define PLL_POWER_STATE_IN_TXS2_0_MASK (0x7 << 7)
# define PLL_POWER_STATE_IN_TXS2_0_SHIFT 7
# define PLL_POWER_STATE_IN_OFF_0(x) ((x) << 10)
# define PLL_POWER_STATE_IN_OFF_0_MASK (0x7 << 10)
# define PLL_POWER_STATE_IN_OFF_0_SHIFT 10
# define PLL_RAMP_UP_TIME_0(x) ((x) << 24)
# define PLL_RAMP_UP_TIME_0_MASK (0x7 << 24)
# define PLL_RAMP_UP_TIME_0_SHIFT 24
#define PB0_PIF_PWRDOWN_1 0x13
# define PLL_POWER_STATE_IN_TXS2_1(x) ((x) << 7)
# define PLL_POWER_STATE_IN_TXS2_1_MASK (0x7 << 7)
# define PLL_POWER_STATE_IN_TXS2_1_SHIFT 7
# define PLL_POWER_STATE_IN_OFF_1(x) ((x) << 10)
# define PLL_POWER_STATE_IN_OFF_1_MASK (0x7 << 10)
# define PLL_POWER_STATE_IN_OFF_1_SHIFT 10
# define PLL_RAMP_UP_TIME_1(x) ((x) << 24)
# define PLL_RAMP_UP_TIME_1_MASK (0x7 << 24)
# define PLL_RAMP_UP_TIME_1_SHIFT 24
#define PB0_PIF_PWRDOWN_2 0x17
# define PLL_POWER_STATE_IN_TXS2_2(x) ((x) << 7)
# define PLL_POWER_STATE_IN_TXS2_2_MASK (0x7 << 7)
# define PLL_POWER_STATE_IN_TXS2_2_SHIFT 7
# define PLL_POWER_STATE_IN_OFF_2(x) ((x) << 10)
# define PLL_POWER_STATE_IN_OFF_2_MASK (0x7 << 10)
# define PLL_POWER_STATE_IN_OFF_2_SHIFT 10
# define PLL_RAMP_UP_TIME_2(x) ((x) << 24)
# define PLL_RAMP_UP_TIME_2_MASK (0x7 << 24)
# define PLL_RAMP_UP_TIME_2_SHIFT 24
#define PB0_PIF_PWRDOWN_3 0x18
# define PLL_POWER_STATE_IN_TXS2_3(x) ((x) << 7)
# define PLL_POWER_STATE_IN_TXS2_3_MASK (0x7 << 7)
# define PLL_POWER_STATE_IN_TXS2_3_SHIFT 7
# define PLL_POWER_STATE_IN_OFF_3(x) ((x) << 10)
# define PLL_POWER_STATE_IN_OFF_3_MASK (0x7 << 10)
# define PLL_POWER_STATE_IN_OFF_3_SHIFT 10
# define PLL_RAMP_UP_TIME_3(x) ((x) << 24)
# define PLL_RAMP_UP_TIME_3_MASK (0x7 << 24)
# define PLL_RAMP_UP_TIME_3_SHIFT 24
/* PIF PHY1 registers idx/data 0x10/0x14 */
#define PB1_PIF_CNTL 0x10
#define PB1_PIF_PAIRING 0x11
#define PB1_PIF_PWRDOWN_0 0x12
#define PB1_PIF_PWRDOWN_1 0x13
#define PB1_PIF_PWRDOWN_2 0x17
#define PB1_PIF_PWRDOWN_3 0x18
/* PCIE registers idx/data 0x30/0x34 */
#define PCIE_CNTL2 0x1c /* PCIE */
# define SLV_MEM_LS_EN (1 << 16)
# define MST_MEM_LS_EN (1 << 18)
# define REPLAY_MEM_LS_EN (1 << 19)
#define PCIE_LC_STATUS1 0x28 /* PCIE */
# define LC_REVERSE_RCVR (1 << 0)
# define LC_REVERSE_XMIT (1 << 1)
# define LC_OPERATING_LINK_WIDTH_MASK (0x7 << 2)
# define LC_OPERATING_LINK_WIDTH_SHIFT 2
# define LC_DETECTED_LINK_WIDTH_MASK (0x7 << 5)
# define LC_DETECTED_LINK_WIDTH_SHIFT 5
#define PCIE_P_CNTL 0x40 /* PCIE */
# define P_IGNORE_EDB_ERR (1 << 6)
/* PCIE PORT registers idx/data 0x38/0x3c */
#define PCIE_LC_CNTL 0xa0
# define LC_L0S_INACTIVITY(x) ((x) << 8)
# define LC_L0S_INACTIVITY_MASK (0xf << 8)
# define LC_L0S_INACTIVITY_SHIFT 8
# define LC_L1_INACTIVITY(x) ((x) << 12)
# define LC_L1_INACTIVITY_MASK (0xf << 12)
# define LC_L1_INACTIVITY_SHIFT 12
# define LC_PMI_TO_L1_DIS (1 << 16)
# define LC_ASPM_TO_L1_DIS (1 << 24)
#define PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE_P */
# define LC_LINK_WIDTH_SHIFT 0
# define LC_LINK_WIDTH_MASK 0x7
# define LC_LINK_WIDTH_X0 0
# define LC_LINK_WIDTH_X1 1
# define LC_LINK_WIDTH_X2 2
# define LC_LINK_WIDTH_X4 3
# define LC_LINK_WIDTH_X8 4
# define LC_LINK_WIDTH_X16 6
# define LC_LINK_WIDTH_RD_SHIFT 4
# define LC_LINK_WIDTH_RD_MASK 0x70
# define LC_RECONFIG_ARC_MISSING_ESCAPE (1 << 7)
# define LC_RECONFIG_NOW (1 << 8)
# define LC_RENEGOTIATION_SUPPORT (1 << 9)
# define LC_RENEGOTIATE_EN (1 << 10)
# define LC_SHORT_RECONFIG_EN (1 << 11)
# define LC_UPCONFIGURE_SUPPORT (1 << 12)
# define LC_UPCONFIGURE_DIS (1 << 13)
# define LC_DYN_LANES_PWR_STATE(x) ((x) << 21)
# define LC_DYN_LANES_PWR_STATE_MASK (0x3 << 21)
# define LC_DYN_LANES_PWR_STATE_SHIFT 21
#define PCIE_LC_N_FTS_CNTL 0xa3 /* PCIE_P */
# define LC_XMIT_N_FTS(x) ((x) << 0)
# define LC_XMIT_N_FTS_MASK (0xff << 0)
# define LC_XMIT_N_FTS_SHIFT 0
# define LC_XMIT_N_FTS_OVERRIDE_EN (1 << 8)
# define LC_N_FTS_MASK (0xff << 24)
#define PCIE_LC_SPEED_CNTL 0xa4 /* PCIE_P */
# define LC_GEN2_EN_STRAP (1 << 0)
# define LC_GEN3_EN_STRAP (1 << 1)
# define LC_TARGET_LINK_SPEED_OVERRIDE_EN (1 << 2)
# define LC_TARGET_LINK_SPEED_OVERRIDE_MASK (0x3 << 3)
# define LC_TARGET_LINK_SPEED_OVERRIDE_SHIFT 3
# define LC_FORCE_EN_SW_SPEED_CHANGE (1 << 5)
# define LC_FORCE_DIS_SW_SPEED_CHANGE (1 << 6)
# define LC_FORCE_EN_HW_SPEED_CHANGE (1 << 7)
# define LC_FORCE_DIS_HW_SPEED_CHANGE (1 << 8)
# define LC_INITIATE_LINK_SPEED_CHANGE (1 << 9)
# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK (0x3 << 10)
# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT 10
# define LC_CURRENT_DATA_RATE_MASK (0x3 << 13) /* 0/1/2 = gen1/2/3 */
# define LC_CURRENT_DATA_RATE_SHIFT 13
# define LC_CLR_FAILED_SPD_CHANGE_CNT (1 << 16)
# define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 18)
# define LC_OTHER_SIDE_SUPPORTS_GEN2 (1 << 19)
# define LC_OTHER_SIDE_EVER_SENT_GEN3 (1 << 20)
# define LC_OTHER_SIDE_SUPPORTS_GEN3 (1 << 21)
#define PCIE_LC_CNTL2 0xb1
# define LC_ALLOW_PDWN_IN_L1 (1 << 17)
# define LC_ALLOW_PDWN_IN_L23 (1 << 18)
#define PCIE_LC_CNTL3 0xb5 /* PCIE_P */
# define LC_GO_TO_RECOVERY (1 << 30)
#define PCIE_LC_CNTL4 0xb6 /* PCIE_P */
# define LC_REDO_EQ (1 << 5)
# define LC_SET_QUIESCE (1 << 13)
/*
* UVD
*/
@ -838,6 +1367,21 @@
#define UVD_RBC_RB_RPTR 0xF690
#define UVD_RBC_RB_WPTR 0xF694
#define UVD_CGC_CTRL 0xF4B0
# define DCM (1 << 0)
# define CG_DT(x) ((x) << 2)
# define CG_DT_MASK (0xf << 2)
# define CLK_OD(x) ((x) << 6)
# define CLK_OD_MASK (0x1f << 6)
/* UVD CTX indirect */
#define UVD_CGC_MEM_CTRL 0xC0
#define UVD_CGC_CTRL2 0xC1
# define DYN_OR_EN (1 << 0)
# define DYN_RR_EN (1 << 1)
# define G_DIV_ID(x) ((x) << 2)
# define G_DIV_ID_MASK (0x7 << 2)
/*
* PM4
*/
@ -1082,6 +1626,11 @@
# define DMA_IDLE (1 << 0)
#define DMA_TILING_CONFIG 0xd0b8
#define DMA_PG 0xd0d4
# define PG_CNTL_ENABLE (1 << 0)
#define DMA_PGFSM_CONFIG 0xd0d8
#define DMA_PGFSM_WRITE 0xd0dc
#define DMA_PACKET(cmd, b, t, s, n) ((((cmd) & 0xF) << 28) | \
(((b) & 0x1) << 26) | \
(((t) & 0x1) << 23) | \

View File

@ -0,0 +1,397 @@
/*
* Copyright 2013 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.
*
*/
#ifndef PP_SISLANDS_SMC_H
#define PP_SISLANDS_SMC_H
#include "ppsmc.h"
#pragma pack(push, 1)
#define SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16
struct PP_SIslands_Dpm2PerfLevel
{
uint8_t MaxPS;
uint8_t TgtAct;
uint8_t MaxPS_StepInc;
uint8_t MaxPS_StepDec;
uint8_t PSSamplingTime;
uint8_t NearTDPDec;
uint8_t AboveSafeInc;
uint8_t BelowSafeInc;
uint8_t PSDeltaLimit;
uint8_t PSDeltaWin;
uint16_t PwrEfficiencyRatio;
uint8_t Reserved[4];
};
typedef struct PP_SIslands_Dpm2PerfLevel PP_SIslands_Dpm2PerfLevel;
struct PP_SIslands_DPM2Status
{
uint32_t dpm2Flags;
uint8_t CurrPSkip;
uint8_t CurrPSkipPowerShift;
uint8_t CurrPSkipTDP;
uint8_t CurrPSkipOCP;
uint8_t MaxSPLLIndex;
uint8_t MinSPLLIndex;
uint8_t CurrSPLLIndex;
uint8_t InfSweepMode;
uint8_t InfSweepDir;
uint8_t TDPexceeded;
uint8_t reserved;
uint8_t SwitchDownThreshold;
uint32_t SwitchDownCounter;
uint32_t SysScalingFactor;
};
typedef struct PP_SIslands_DPM2Status PP_SIslands_DPM2Status;
struct PP_SIslands_DPM2Parameters
{
uint32_t TDPLimit;
uint32_t NearTDPLimit;
uint32_t SafePowerLimit;
uint32_t PowerBoostLimit;
uint32_t MinLimitDelta;
};
typedef struct PP_SIslands_DPM2Parameters PP_SIslands_DPM2Parameters;
struct PP_SIslands_PAPMStatus
{
uint32_t EstimatedDGPU_T;
uint32_t EstimatedDGPU_P;
uint32_t EstimatedAPU_T;
uint32_t EstimatedAPU_P;
uint8_t dGPU_T_Limit_Exceeded;
uint8_t reserved[3];
};
typedef struct PP_SIslands_PAPMStatus PP_SIslands_PAPMStatus;
struct PP_SIslands_PAPMParameters
{
uint32_t NearTDPLimitTherm;
uint32_t NearTDPLimitPAPM;
uint32_t PlatformPowerLimit;
uint32_t dGPU_T_Limit;
uint32_t dGPU_T_Warning;
uint32_t dGPU_T_Hysteresis;
};
typedef struct PP_SIslands_PAPMParameters PP_SIslands_PAPMParameters;
struct SISLANDS_SMC_SCLK_VALUE
{
uint32_t vCG_SPLL_FUNC_CNTL;
uint32_t vCG_SPLL_FUNC_CNTL_2;
uint32_t vCG_SPLL_FUNC_CNTL_3;
uint32_t vCG_SPLL_FUNC_CNTL_4;
uint32_t vCG_SPLL_SPREAD_SPECTRUM;
uint32_t vCG_SPLL_SPREAD_SPECTRUM_2;
uint32_t sclk_value;
};
typedef struct SISLANDS_SMC_SCLK_VALUE SISLANDS_SMC_SCLK_VALUE;
struct SISLANDS_SMC_MCLK_VALUE
{
uint32_t vMPLL_FUNC_CNTL;
uint32_t vMPLL_FUNC_CNTL_1;
uint32_t vMPLL_FUNC_CNTL_2;
uint32_t vMPLL_AD_FUNC_CNTL;
uint32_t vMPLL_DQ_FUNC_CNTL;
uint32_t vMCLK_PWRMGT_CNTL;
uint32_t vDLL_CNTL;
uint32_t vMPLL_SS;
uint32_t vMPLL_SS2;
uint32_t mclk_value;
};
typedef struct SISLANDS_SMC_MCLK_VALUE SISLANDS_SMC_MCLK_VALUE;
struct SISLANDS_SMC_VOLTAGE_VALUE
{
uint16_t value;
uint8_t index;
uint8_t phase_settings;
};
typedef struct SISLANDS_SMC_VOLTAGE_VALUE SISLANDS_SMC_VOLTAGE_VALUE;
struct SISLANDS_SMC_HW_PERFORMANCE_LEVEL
{
uint8_t ACIndex;
uint8_t displayWatermark;
uint8_t gen2PCIE;
uint8_t UVDWatermark;
uint8_t VCEWatermark;
uint8_t strobeMode;
uint8_t mcFlags;
uint8_t padding;
uint32_t aT;
uint32_t bSP;
SISLANDS_SMC_SCLK_VALUE sclk;
SISLANDS_SMC_MCLK_VALUE mclk;
SISLANDS_SMC_VOLTAGE_VALUE vddc;
SISLANDS_SMC_VOLTAGE_VALUE mvdd;
SISLANDS_SMC_VOLTAGE_VALUE vddci;
SISLANDS_SMC_VOLTAGE_VALUE std_vddc;
uint8_t hysteresisUp;
uint8_t hysteresisDown;
uint8_t stateFlags;
uint8_t arbRefreshState;
uint32_t SQPowerThrottle;
uint32_t SQPowerThrottle_2;
uint32_t MaxPoweredUpCU;
SISLANDS_SMC_VOLTAGE_VALUE high_temp_vddc;
SISLANDS_SMC_VOLTAGE_VALUE low_temp_vddc;
uint32_t reserved[2];
PP_SIslands_Dpm2PerfLevel dpm2;
};
#define SISLANDS_SMC_STROBE_RATIO 0x0F
#define SISLANDS_SMC_STROBE_ENABLE 0x10
#define SISLANDS_SMC_MC_EDC_RD_FLAG 0x01
#define SISLANDS_SMC_MC_EDC_WR_FLAG 0x02
#define SISLANDS_SMC_MC_RTT_ENABLE 0x04
#define SISLANDS_SMC_MC_STUTTER_EN 0x08
#define SISLANDS_SMC_MC_PG_EN 0x10
typedef struct SISLANDS_SMC_HW_PERFORMANCE_LEVEL SISLANDS_SMC_HW_PERFORMANCE_LEVEL;
struct SISLANDS_SMC_SWSTATE
{
uint8_t flags;
uint8_t levelCount;
uint8_t padding2;
uint8_t padding3;
SISLANDS_SMC_HW_PERFORMANCE_LEVEL levels[1];
};
typedef struct SISLANDS_SMC_SWSTATE SISLANDS_SMC_SWSTATE;
#define SISLANDS_SMC_VOLTAGEMASK_VDDC 0
#define SISLANDS_SMC_VOLTAGEMASK_MVDD 1
#define SISLANDS_SMC_VOLTAGEMASK_VDDCI 2
#define SISLANDS_SMC_VOLTAGEMASK_MAX 4
struct SISLANDS_SMC_VOLTAGEMASKTABLE
{
uint32_t lowMask[SISLANDS_SMC_VOLTAGEMASK_MAX];
};
typedef struct SISLANDS_SMC_VOLTAGEMASKTABLE SISLANDS_SMC_VOLTAGEMASKTABLE;
#define SISLANDS_MAX_NO_VREG_STEPS 32
struct SISLANDS_SMC_STATETABLE
{
uint8_t thermalProtectType;
uint8_t systemFlags;
uint8_t maxVDDCIndexInPPTable;
uint8_t extraFlags;
uint32_t lowSMIO[SISLANDS_MAX_NO_VREG_STEPS];
SISLANDS_SMC_VOLTAGEMASKTABLE voltageMaskTable;
SISLANDS_SMC_VOLTAGEMASKTABLE phaseMaskTable;
PP_SIslands_DPM2Parameters dpm2Params;
SISLANDS_SMC_SWSTATE initialState;
SISLANDS_SMC_SWSTATE ACPIState;
SISLANDS_SMC_SWSTATE ULVState;
SISLANDS_SMC_SWSTATE driverState;
SISLANDS_SMC_HW_PERFORMANCE_LEVEL dpmLevels[SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1];
};
typedef struct SISLANDS_SMC_STATETABLE SISLANDS_SMC_STATETABLE;
#define SI_SMC_SOFT_REGISTER_mclk_chg_timeout 0x0
#define SI_SMC_SOFT_REGISTER_delay_vreg 0xC
#define SI_SMC_SOFT_REGISTER_delay_acpi 0x28
#define SI_SMC_SOFT_REGISTER_seq_index 0x5C
#define SI_SMC_SOFT_REGISTER_mvdd_chg_time 0x60
#define SI_SMC_SOFT_REGISTER_mclk_switch_lim 0x70
#define SI_SMC_SOFT_REGISTER_watermark_threshold 0x78
#define SI_SMC_SOFT_REGISTER_phase_shedding_delay 0x88
#define SI_SMC_SOFT_REGISTER_ulv_volt_change_delay 0x8C
#define SI_SMC_SOFT_REGISTER_mc_block_delay 0x98
#define SI_SMC_SOFT_REGISTER_ticks_per_us 0xA8
#define SI_SMC_SOFT_REGISTER_crtc_index 0xC4
#define SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min 0xC8
#define SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max 0xCC
#define SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width 0xF4
#define SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen 0xFC
#define SI_SMC_SOFT_REGISTER_vr_hot_gpio 0x100
#define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16
#define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32
#define SMC_SISLANDS_SCALE_I 7
#define SMC_SISLANDS_SCALE_R 12
struct PP_SIslands_CacConfig
{
uint16_t cac_lkge_lut[SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES];
uint32_t lkge_lut_V0;
uint32_t lkge_lut_Vstep;
uint32_t WinTime;
uint32_t R_LL;
uint32_t calculation_repeats;
uint32_t l2numWin_TDP;
uint32_t dc_cac;
uint8_t lts_truncate_n;
uint8_t SHIFT_N;
uint8_t log2_PG_LKG_SCALE;
uint8_t cac_temp;
uint32_t lkge_lut_T0;
uint32_t lkge_lut_Tstep;
};
typedef struct PP_SIslands_CacConfig PP_SIslands_CacConfig;
#define SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE 16
#define SMC_SISLANDS_MC_REGISTER_ARRAY_SET_COUNT 20
struct SMC_SIslands_MCRegisterAddress
{
uint16_t s0;
uint16_t s1;
};
typedef struct SMC_SIslands_MCRegisterAddress SMC_SIslands_MCRegisterAddress;
struct SMC_SIslands_MCRegisterSet
{
uint32_t value[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE];
};
typedef struct SMC_SIslands_MCRegisterSet SMC_SIslands_MCRegisterSet;
struct SMC_SIslands_MCRegisters
{
uint8_t last;
uint8_t reserved[3];
SMC_SIslands_MCRegisterAddress address[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE];
SMC_SIslands_MCRegisterSet data[SMC_SISLANDS_MC_REGISTER_ARRAY_SET_COUNT];
};
typedef struct SMC_SIslands_MCRegisters SMC_SIslands_MCRegisters;
struct SMC_SIslands_MCArbDramTimingRegisterSet
{
uint32_t mc_arb_dram_timing;
uint32_t mc_arb_dram_timing2;
uint8_t mc_arb_rfsh_rate;
uint8_t mc_arb_burst_time;
uint8_t padding[2];
};
typedef struct SMC_SIslands_MCArbDramTimingRegisterSet SMC_SIslands_MCArbDramTimingRegisterSet;
struct SMC_SIslands_MCArbDramTimingRegisters
{
uint8_t arb_current;
uint8_t reserved[3];
SMC_SIslands_MCArbDramTimingRegisterSet data[16];
};
typedef struct SMC_SIslands_MCArbDramTimingRegisters SMC_SIslands_MCArbDramTimingRegisters;
struct SMC_SISLANDS_SPLL_DIV_TABLE
{
uint32_t freq[256];
uint32_t ss[256];
};
#define SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK 0x01ffffff
#define SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT 0
#define SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK 0xfe000000
#define SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT 25
#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK 0x000fffff
#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT 0
#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK 0xfff00000
#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT 20
typedef struct SMC_SISLANDS_SPLL_DIV_TABLE SMC_SISLANDS_SPLL_DIV_TABLE;
#define SMC_SISLANDS_DTE_MAX_FILTER_STAGES 5
#define SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE 16
struct Smc_SIslands_DTE_Configuration
{
uint32_t tau[SMC_SISLANDS_DTE_MAX_FILTER_STAGES];
uint32_t R[SMC_SISLANDS_DTE_MAX_FILTER_STAGES];
uint32_t K;
uint32_t T0;
uint32_t MaxT;
uint8_t WindowSize;
uint8_t Tdep_count;
uint8_t temp_select;
uint8_t DTE_mode;
uint8_t T_limits[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE];
uint32_t Tdep_tau[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE];
uint32_t Tdep_R[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE];
uint32_t Tthreshold;
};
typedef struct Smc_SIslands_DTE_Configuration Smc_SIslands_DTE_Configuration;
#define SMC_SISLANDS_DTE_STATUS_FLAG_DTE_ON 1
#define SISLANDS_SMC_FIRMWARE_HEADER_LOCATION 0x10000
#define SISLANDS_SMC_FIRMWARE_HEADER_version 0x0
#define SISLANDS_SMC_FIRMWARE_HEADER_flags 0x4
#define SISLANDS_SMC_FIRMWARE_HEADER_softRegisters 0xC
#define SISLANDS_SMC_FIRMWARE_HEADER_stateTable 0x10
#define SISLANDS_SMC_FIRMWARE_HEADER_fanTable 0x14
#define SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable 0x18
#define SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable 0x24
#define SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable 0x30
#define SISLANDS_SMC_FIRMWARE_HEADER_spllTable 0x38
#define SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration 0x40
#define SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters 0x48
#pragma pack(pop)
int si_set_smc_sram_address(struct radeon_device *rdev,
u32 smc_address, u32 limit);
int si_copy_bytes_to_smc(struct radeon_device *rdev,
u32 smc_start_address,
const u8 *src, u32 byte_count, u32 limit);
void si_start_smc(struct radeon_device *rdev);
void si_reset_smc(struct radeon_device *rdev);
int si_program_jump_on_start(struct radeon_device *rdev);
void si_stop_smc_clock(struct radeon_device *rdev);
void si_start_smc_clock(struct radeon_device *rdev);
bool si_is_smc_running(struct radeon_device *rdev);
PPSMC_Result si_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg);
PPSMC_Result si_wait_for_smc_inactive(struct radeon_device *rdev);
int si_load_smc_ucode(struct radeon_device *rdev, u32 limit);
int si_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
u32 *value, u32 limit);
int si_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
u32 value, u32 limit);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,220 @@
/*
* Copyright 2012 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.
*
*/
#ifndef __SUMO_DPM_H__
#define __SUMO_DPM_H__
#include "atom.h"
#define SUMO_MAX_HARDWARE_POWERLEVELS 5
#define SUMO_PM_NUMBER_OF_TC 15
struct sumo_pl {
u32 sclk;
u32 vddc_index;
u32 ds_divider_index;
u32 ss_divider_index;
u32 allow_gnb_slow;
u32 sclk_dpm_tdp_limit;
};
/* used for the flags field */
#define SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE (1 << 0)
#define SUMO_POWERSTATE_FLAGS_BOOST_STATE (1 << 1)
struct sumo_ps {
struct sumo_pl levels[SUMO_MAX_HARDWARE_POWERLEVELS];
u32 num_levels;
/* flags */
u32 flags;
};
#define NUMBER_OF_M3ARB_PARAM_SETS 10
#define SUMO_MAX_NUMBER_VOLTAGES 4
struct sumo_disp_clock_voltage_mapping_table {
u32 num_max_voltage_levels;
u32 display_clock_frequency[SUMO_MAX_NUMBER_VOLTAGES];
};
struct sumo_vid_mapping_entry {
u16 vid_2bit;
u16 vid_7bit;
};
struct sumo_vid_mapping_table {
u32 num_entries;
struct sumo_vid_mapping_entry entries[SUMO_MAX_NUMBER_VOLTAGES];
};
struct sumo_sclk_voltage_mapping_entry {
u32 sclk_frequency;
u16 vid_2bit;
u16 rsv;
};
struct sumo_sclk_voltage_mapping_table {
u32 num_max_dpm_entries;
struct sumo_sclk_voltage_mapping_entry entries[SUMO_MAX_HARDWARE_POWERLEVELS];
};
struct sumo_sys_info {
u32 bootup_sclk;
u32 min_sclk;
u32 bootup_uma_clk;
u16 bootup_nb_voltage_index;
u8 htc_tmp_lmt;
u8 htc_hyst_lmt;
struct sumo_sclk_voltage_mapping_table sclk_voltage_mapping_table;
struct sumo_disp_clock_voltage_mapping_table disp_clk_voltage_mapping_table;
struct sumo_vid_mapping_table vid_mapping_table;
u32 csr_m3_arb_cntl_default[NUMBER_OF_M3ARB_PARAM_SETS];
u32 csr_m3_arb_cntl_uvd[NUMBER_OF_M3ARB_PARAM_SETS];
u32 csr_m3_arb_cntl_fs3d[NUMBER_OF_M3ARB_PARAM_SETS];
u32 sclk_dpm_boost_margin;
u32 sclk_dpm_throttle_margin;
u32 sclk_dpm_tdp_limit_pg;
u32 gnb_tdp_limit;
u32 sclk_dpm_tdp_limit_boost;
u32 boost_sclk;
u32 boost_vid_2bit;
bool enable_boost;
};
struct sumo_power_info {
u32 asi;
u32 pasi;
u32 bsp;
u32 bsu;
u32 pbsp;
u32 pbsu;
u32 dsp;
u32 psp;
u32 thermal_auto_throttling;
u32 uvd_m3_arbiter;
u32 fw_version;
struct sumo_sys_info sys_info;
struct sumo_pl acpi_pl;
struct sumo_pl boot_pl;
struct sumo_pl boost_pl;
bool disable_gfx_power_gating_in_uvd;
bool driver_nbps_policy_disable;
bool enable_alt_vddnb;
bool enable_dynamic_m3_arbiter;
bool enable_gfx_clock_gating;
bool enable_gfx_power_gating;
bool enable_mg_clock_gating;
bool enable_sclk_ds;
bool enable_auto_thermal_throttling;
bool enable_dynamic_patch_ps;
bool enable_dpm;
bool enable_boost;
struct radeon_ps current_rps;
struct sumo_ps current_ps;
struct radeon_ps requested_rps;
struct sumo_ps requested_ps;
};
#define SUMO_UTC_DFLT_00 0x48
#define SUMO_UTC_DFLT_01 0x44
#define SUMO_UTC_DFLT_02 0x44
#define SUMO_UTC_DFLT_03 0x44
#define SUMO_UTC_DFLT_04 0x44
#define SUMO_UTC_DFLT_05 0x44
#define SUMO_UTC_DFLT_06 0x44
#define SUMO_UTC_DFLT_07 0x44
#define SUMO_UTC_DFLT_08 0x44
#define SUMO_UTC_DFLT_09 0x44
#define SUMO_UTC_DFLT_10 0x44
#define SUMO_UTC_DFLT_11 0x44
#define SUMO_UTC_DFLT_12 0x44
#define SUMO_UTC_DFLT_13 0x44
#define SUMO_UTC_DFLT_14 0x44
#define SUMO_DTC_DFLT_00 0x48
#define SUMO_DTC_DFLT_01 0x44
#define SUMO_DTC_DFLT_02 0x44
#define SUMO_DTC_DFLT_03 0x44
#define SUMO_DTC_DFLT_04 0x44
#define SUMO_DTC_DFLT_05 0x44
#define SUMO_DTC_DFLT_06 0x44
#define SUMO_DTC_DFLT_07 0x44
#define SUMO_DTC_DFLT_08 0x44
#define SUMO_DTC_DFLT_09 0x44
#define SUMO_DTC_DFLT_10 0x44
#define SUMO_DTC_DFLT_11 0x44
#define SUMO_DTC_DFLT_12 0x44
#define SUMO_DTC_DFLT_13 0x44
#define SUMO_DTC_DFLT_14 0x44
#define SUMO_AH_DFLT 5
#define SUMO_R_DFLT0 70
#define SUMO_R_DFLT1 70
#define SUMO_R_DFLT2 70
#define SUMO_R_DFLT3 70
#define SUMO_R_DFLT4 100
#define SUMO_L_DFLT0 0
#define SUMO_L_DFLT1 20
#define SUMO_L_DFLT2 20
#define SUMO_L_DFLT3 20
#define SUMO_L_DFLT4 20
#define SUMO_VRC_DFLT 0x30033
#define SUMO_MGCGTTLOCAL0_DFLT 0
#define SUMO_MGCGTTLOCAL1_DFLT 0
#define SUMO_GICST_DFLT 19
#define SUMO_SST_DFLT 8
#define SUMO_VOLTAGEDROPT_DFLT 1
#define SUMO_GFXPOWERGATINGT_DFLT 100
/* sumo_dpm.c */
void sumo_gfx_clockgating_initialize(struct radeon_device *rdev);
void sumo_program_vc(struct radeon_device *rdev, u32 vrc);
void sumo_clear_vc(struct radeon_device *rdev);
void sumo_program_sstp(struct radeon_device *rdev);
void sumo_take_smu_control(struct radeon_device *rdev, bool enable);
void sumo_construct_sclk_voltage_mapping_table(struct radeon_device *rdev,
struct sumo_sclk_voltage_mapping_table *sclk_voltage_mapping_table,
ATOM_AVAILABLE_SCLK_LIST *table);
void sumo_construct_vid_mapping_table(struct radeon_device *rdev,
struct sumo_vid_mapping_table *vid_mapping_table,
ATOM_AVAILABLE_SCLK_LIST *table);
u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev,
struct sumo_vid_mapping_table *vid_mapping_table,
u32 vid_2bit);
u32 sumo_get_sleep_divider_from_id(u32 id);
u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
u32 sclk,
u32 min_sclk_in_sr);
/* sumo_smc.c */
void sumo_initialize_m3_arb(struct radeon_device *rdev);
void sumo_smu_pg_init(struct radeon_device *rdev);
void sumo_set_tdp_limit(struct radeon_device *rdev, u32 index, u32 tdp_limit);
void sumo_smu_notify_alt_vddnb_change(struct radeon_device *rdev,
bool powersaving, bool force_nbps1);
void sumo_boost_state_enable(struct radeon_device *rdev, bool enable);
void sumo_enable_boost_timer(struct radeon_device *rdev);
u32 sumo_get_running_fw_version(struct radeon_device *rdev);
#endif

View File

@ -0,0 +1,222 @@
/*
* Copyright 2012 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.
*
*/
#include "drmP.h"
#include "radeon.h"
#include "sumod.h"
#include "sumo_dpm.h"
#include "ppsmc.h"
#define SUMO_SMU_SERVICE_ROUTINE_PG_INIT 1
#define SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY 27
#define SUMO_SMU_SERVICE_ROUTINE_GFX_SRV_ID_20 20
struct sumo_ps *sumo_get_ps(struct radeon_ps *rps);
struct sumo_power_info *sumo_get_pi(struct radeon_device *rdev);
static void sumo_send_msg_to_smu(struct radeon_device *rdev, u32 id)
{
u32 gfx_int_req;
int i;
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(GFX_INT_STATUS) & INT_DONE)
break;
udelay(1);
}
gfx_int_req = SERV_INDEX(id) | INT_REQ;
WREG32(GFX_INT_REQ, gfx_int_req);
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(GFX_INT_REQ) & INT_REQ)
break;
udelay(1);
}
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(GFX_INT_STATUS) & INT_ACK)
break;
udelay(1);
}
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(GFX_INT_STATUS) & INT_DONE)
break;
udelay(1);
}
gfx_int_req &= ~INT_REQ;
WREG32(GFX_INT_REQ, gfx_int_req);
}
void sumo_initialize_m3_arb(struct radeon_device *rdev)
{
struct sumo_power_info *pi = sumo_get_pi(rdev);
u32 i;
if (!pi->enable_dynamic_m3_arbiter)
return;
for (i = 0; i < NUMBER_OF_M3ARB_PARAM_SETS; i++)
WREG32_RCU(MCU_M3ARB_PARAMS + (i * 4),
pi->sys_info.csr_m3_arb_cntl_default[i]);
for (; i < NUMBER_OF_M3ARB_PARAM_SETS * 2; i++)
WREG32_RCU(MCU_M3ARB_PARAMS + (i * 4),
pi->sys_info.csr_m3_arb_cntl_uvd[i % NUMBER_OF_M3ARB_PARAM_SETS]);
for (; i < NUMBER_OF_M3ARB_PARAM_SETS * 3; i++)
WREG32_RCU(MCU_M3ARB_PARAMS + (i * 4),
pi->sys_info.csr_m3_arb_cntl_fs3d[i % NUMBER_OF_M3ARB_PARAM_SETS]);
}
static bool sumo_is_alt_vddnb_supported(struct radeon_device *rdev)
{
struct sumo_power_info *pi = sumo_get_pi(rdev);
bool return_code = false;
if (!pi->enable_alt_vddnb)
return return_code;
if ((rdev->family == CHIP_SUMO) || (rdev->family == CHIP_SUMO2)) {
if (pi->fw_version >= 0x00010C00)
return_code = true;
}
return return_code;
}
void sumo_smu_notify_alt_vddnb_change(struct radeon_device *rdev,
bool powersaving, bool force_nbps1)
{
u32 param = 0;
if (!sumo_is_alt_vddnb_supported(rdev))
return;
if (powersaving)
param |= 1;
if (force_nbps1)
param |= 2;
WREG32_RCU(RCU_ALTVDDNB_NOTIFY, param);
sumo_send_msg_to_smu(rdev, SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY);
}
void sumo_smu_pg_init(struct radeon_device *rdev)
{
sumo_send_msg_to_smu(rdev, SUMO_SMU_SERVICE_ROUTINE_PG_INIT);
}
static u32 sumo_power_of_4(u32 unit)
{
u32 ret = 1;
u32 i;
for (i = 0; i < unit; i++)
ret *= 4;
return ret;
}
void sumo_enable_boost_timer(struct radeon_device *rdev)
{
struct sumo_power_info *pi = sumo_get_pi(rdev);
u32 period, unit, timer_value;
u32 xclk = radeon_get_xclk(rdev);
unit = (RREG32_RCU(RCU_LCLK_SCALING_CNTL) & LCLK_SCALING_TIMER_PRESCALER_MASK)
>> LCLK_SCALING_TIMER_PRESCALER_SHIFT;
period = 100 * (xclk / 100 / sumo_power_of_4(unit));
timer_value = (period << 16) | (unit << 4);
WREG32_RCU(RCU_GNB_PWR_REP_TIMER_CNTL, timer_value);
WREG32_RCU(RCU_BOOST_MARGIN, pi->sys_info.sclk_dpm_boost_margin);
WREG32_RCU(RCU_THROTTLE_MARGIN, pi->sys_info.sclk_dpm_throttle_margin);
WREG32_RCU(GNB_TDP_LIMIT, pi->sys_info.gnb_tdp_limit);
WREG32_RCU(RCU_SclkDpmTdpLimitPG, pi->sys_info.sclk_dpm_tdp_limit_pg);
sumo_send_msg_to_smu(rdev, SUMO_SMU_SERVICE_ROUTINE_GFX_SRV_ID_20);
}
void sumo_set_tdp_limit(struct radeon_device *rdev, u32 index, u32 tdp_limit)
{
u32 regoffset = 0;
u32 shift = 0;
u32 mask = 0xFFF;
u32 sclk_dpm_tdp_limit;
switch (index) {
case 0:
regoffset = RCU_SclkDpmTdpLimit01;
shift = 16;
break;
case 1:
regoffset = RCU_SclkDpmTdpLimit01;
shift = 0;
break;
case 2:
regoffset = RCU_SclkDpmTdpLimit23;
shift = 16;
break;
case 3:
regoffset = RCU_SclkDpmTdpLimit23;
shift = 0;
break;
case 4:
regoffset = RCU_SclkDpmTdpLimit47;
shift = 16;
break;
case 7:
regoffset = RCU_SclkDpmTdpLimit47;
shift = 0;
break;
default:
break;
}
sclk_dpm_tdp_limit = RREG32_RCU(regoffset);
sclk_dpm_tdp_limit &= ~(mask << shift);
sclk_dpm_tdp_limit |= (tdp_limit << shift);
WREG32_RCU(regoffset, sclk_dpm_tdp_limit);
}
void sumo_boost_state_enable(struct radeon_device *rdev, bool enable)
{
u32 boost_disable = RREG32_RCU(RCU_GPU_BOOST_DISABLE);
boost_disable &= 0xFFFFFFFE;
boost_disable |= (enable ? 0 : 1);
WREG32_RCU(RCU_GPU_BOOST_DISABLE, boost_disable);
}
u32 sumo_get_running_fw_version(struct radeon_device *rdev)
{
return RREG32_RCU(RCU_FW_VERSION);
}

View File

@ -0,0 +1,372 @@
/*
* Copyright 2012 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: Alex Deucher
*/
#ifndef _SUMOD_H_
#define _SUMOD_H_
/* pm registers */
/* rcu */
#define RCU_FW_VERSION 0x30c
#define RCU_PWR_GATING_SEQ0 0x408
#define RCU_PWR_GATING_SEQ1 0x40c
#define RCU_PWR_GATING_CNTL 0x410
# define PWR_GATING_EN (1 << 0)
# define RSVD_MASK (0x3 << 1)
# define PCV(x) ((x) << 3)
# define PCV_MASK (0x1f << 3)
# define PCV_SHIFT 3
# define PCP(x) ((x) << 8)
# define PCP_MASK (0xf << 8)
# define PCP_SHIFT 8
# define RPW(x) ((x) << 16)
# define RPW_MASK (0xf << 16)
# define RPW_SHIFT 16
# define ID(x) ((x) << 24)
# define ID_MASK (0xf << 24)
# define ID_SHIFT 24
# define PGS(x) ((x) << 28)
# define PGS_MASK (0xf << 28)
# define PGS_SHIFT 28
#define RCU_ALTVDDNB_NOTIFY 0x430
#define RCU_LCLK_SCALING_CNTL 0x434
# define LCLK_SCALING_EN (1 << 0)
# define LCLK_SCALING_TYPE (1 << 1)
# define LCLK_SCALING_TIMER_PRESCALER(x) ((x) << 4)
# define LCLK_SCALING_TIMER_PRESCALER_MASK (0xf << 4)
# define LCLK_SCALING_TIMER_PRESCALER_SHIFT 4
# define LCLK_SCALING_TIMER_PERIOD(x) ((x) << 16)
# define LCLK_SCALING_TIMER_PERIOD_MASK (0xf << 16)
# define LCLK_SCALING_TIMER_PERIOD_SHIFT 16
#define RCU_PWR_GATING_CNTL_2 0x4a0
# define MPPU(x) ((x) << 0)
# define MPPU_MASK (0xffff << 0)
# define MPPU_SHIFT 0
# define MPPD(x) ((x) << 16)
# define MPPD_MASK (0xffff << 16)
# define MPPD_SHIFT 16
#define RCU_PWR_GATING_CNTL_3 0x4a4
# define DPPU(x) ((x) << 0)
# define DPPU_MASK (0xffff << 0)
# define DPPU_SHIFT 0
# define DPPD(x) ((x) << 16)
# define DPPD_MASK (0xffff << 16)
# define DPPD_SHIFT 16
#define RCU_PWR_GATING_CNTL_4 0x4a8
# define RT(x) ((x) << 0)
# define RT_MASK (0xffff << 0)
# define RT_SHIFT 0
# define IT(x) ((x) << 16)
# define IT_MASK (0xffff << 16)
# define IT_SHIFT 16
/* yes these two have the same address */
#define RCU_PWR_GATING_CNTL_5 0x504
#define RCU_GPU_BOOST_DISABLE 0x508
#define MCU_M3ARB_INDEX 0x504
#define MCU_M3ARB_PARAMS 0x508
#define RCU_GNB_PWR_REP_TIMER_CNTL 0x50C
#define RCU_SclkDpmTdpLimit01 0x514
#define RCU_SclkDpmTdpLimit23 0x518
#define RCU_SclkDpmTdpLimit47 0x51C
#define RCU_SclkDpmTdpLimitPG 0x520
#define GNB_TDP_LIMIT 0x540
#define RCU_BOOST_MARGIN 0x544
#define RCU_THROTTLE_MARGIN 0x548
#define SMU_PCIE_PG_ARGS 0x58C
#define SMU_PCIE_PG_ARGS_2 0x598
#define SMU_PCIE_PG_ARGS_3 0x59C
/* mmio */
#define RCU_STATUS 0x11c
# define GMC_PWR_GATER_BUSY (1 << 8)
# define GFX_PWR_GATER_BUSY (1 << 9)
# define UVD_PWR_GATER_BUSY (1 << 10)
# define PCIE_PWR_GATER_BUSY (1 << 11)
# define GMC_PWR_GATER_STATE (1 << 12)
# define GFX_PWR_GATER_STATE (1 << 13)
# define UVD_PWR_GATER_STATE (1 << 14)
# define PCIE_PWR_GATER_STATE (1 << 15)
# define GFX1_PWR_GATER_BUSY (1 << 16)
# define GFX2_PWR_GATER_BUSY (1 << 17)
# define GFX1_PWR_GATER_STATE (1 << 18)
# define GFX2_PWR_GATER_STATE (1 << 19)
#define GFX_INT_REQ 0x120
# define INT_REQ (1 << 0)
# define SERV_INDEX(x) ((x) << 1)
# define SERV_INDEX_MASK (0xff << 1)
# define SERV_INDEX_SHIFT 1
#define GFX_INT_STATUS 0x124
# define INT_ACK (1 << 0)
# define INT_DONE (1 << 1)
#define CG_SCLK_CNTL 0x600
# define SCLK_DIVIDER(x) ((x) << 0)
# define SCLK_DIVIDER_MASK (0x7f << 0)
# define SCLK_DIVIDER_SHIFT 0
#define CG_SCLK_STATUS 0x604
# define SCLK_OVERCLK_DETECT (1 << 2)
#define CG_DCLK_CNTL 0x610
# define DCLK_DIVIDER_MASK 0x7f
# define DCLK_DIR_CNTL_EN (1 << 8)
#define CG_DCLK_STATUS 0x614
# define DCLK_STATUS (1 << 0)
#define CG_VCLK_CNTL 0x618
# define VCLK_DIVIDER_MASK 0x7f
# define VCLK_DIR_CNTL_EN (1 << 8)
#define CG_VCLK_STATUS 0x61c
#define GENERAL_PWRMGT 0x63c
# define STATIC_PM_EN (1 << 1)
#define SCLK_PWRMGT_CNTL 0x644
# define SCLK_PWRMGT_OFF (1 << 0)
# define SCLK_LOW_D1 (1 << 1)
# define FIR_RESET (1 << 4)
# define FIR_FORCE_TREND_SEL (1 << 5)
# define FIR_TREND_MODE (1 << 6)
# define DYN_GFX_CLK_OFF_EN (1 << 7)
# define GFX_CLK_FORCE_ON (1 << 8)
# define GFX_CLK_REQUEST_OFF (1 << 9)
# define GFX_CLK_FORCE_OFF (1 << 10)
# define GFX_CLK_OFF_ACPI_D1 (1 << 11)
# define GFX_CLK_OFF_ACPI_D2 (1 << 12)
# define GFX_CLK_OFF_ACPI_D3 (1 << 13)
# define GFX_VOLTAGE_CHANGE_EN (1 << 16)
# define GFX_VOLTAGE_CHANGE_MODE (1 << 17)
#define TARGET_AND_CURRENT_PROFILE_INDEX 0x66c
# define TARG_SCLK_INDEX(x) ((x) << 6)
# define TARG_SCLK_INDEX_MASK (0x7 << 6)
# define TARG_SCLK_INDEX_SHIFT 6
# define CURR_SCLK_INDEX(x) ((x) << 9)
# define CURR_SCLK_INDEX_MASK (0x7 << 9)
# define CURR_SCLK_INDEX_SHIFT 9
# define TARG_INDEX(x) ((x) << 12)
# define TARG_INDEX_MASK (0x7 << 12)
# define TARG_INDEX_SHIFT 12
# define CURR_INDEX(x) ((x) << 15)
# define CURR_INDEX_MASK (0x7 << 15)
# define CURR_INDEX_SHIFT 15
#define CG_SCLK_DPM_CTRL 0x684
# define SCLK_FSTATE_0_DIV(x) ((x) << 0)
# define SCLK_FSTATE_0_DIV_MASK (0x7f << 0)
# define SCLK_FSTATE_0_DIV_SHIFT 0
# define SCLK_FSTATE_0_VLD (1 << 7)
# define SCLK_FSTATE_1_DIV(x) ((x) << 8)
# define SCLK_FSTATE_1_DIV_MASK (0x7f << 8)
# define SCLK_FSTATE_1_DIV_SHIFT 8
# define SCLK_FSTATE_1_VLD (1 << 15)
# define SCLK_FSTATE_2_DIV(x) ((x) << 16)
# define SCLK_FSTATE_2_DIV_MASK (0x7f << 16)
# define SCLK_FSTATE_2_DIV_SHIFT 16
# define SCLK_FSTATE_2_VLD (1 << 23)
# define SCLK_FSTATE_3_DIV(x) ((x) << 24)
# define SCLK_FSTATE_3_DIV_MASK (0x7f << 24)
# define SCLK_FSTATE_3_DIV_SHIFT 24
# define SCLK_FSTATE_3_VLD (1 << 31)
#define CG_SCLK_DPM_CTRL_2 0x688
#define CG_GCOOR 0x68c
# define PHC(x) ((x) << 0)
# define PHC_MASK (0x1f << 0)
# define PHC_SHIFT 0
# define SDC(x) ((x) << 9)
# define SDC_MASK (0x3ff << 9)
# define SDC_SHIFT 9
# define SU(x) ((x) << 23)
# define SU_MASK (0xf << 23)
# define SU_SHIFT 23
# define DIV_ID(x) ((x) << 28)
# define DIV_ID_MASK (0x7 << 28)
# define DIV_ID_SHIFT 28
#define CG_FTV 0x690
#define CG_FFCT_0 0x694
# define UTC_0(x) ((x) << 0)
# define UTC_0_MASK (0x3ff << 0)
# define UTC_0_SHIFT 0
# define DTC_0(x) ((x) << 10)
# define DTC_0_MASK (0x3ff << 10)
# define DTC_0_SHIFT 10
#define CG_GIT 0x6d8
# define CG_GICST(x) ((x) << 0)
# define CG_GICST_MASK (0xffff << 0)
# define CG_GICST_SHIFT 0
# define CG_GIPOT(x) ((x) << 16)
# define CG_GIPOT_MASK (0xffff << 16)
# define CG_GIPOT_SHIFT 16
#define CG_SCLK_DPM_CTRL_3 0x6e0
# define FORCE_SCLK_STATE(x) ((x) << 0)
# define FORCE_SCLK_STATE_MASK (0x7 << 0)
# define FORCE_SCLK_STATE_SHIFT 0
# define FORCE_SCLK_STATE_EN (1 << 3)
# define GNB_TT(x) ((x) << 8)
# define GNB_TT_MASK (0xff << 8)
# define GNB_TT_SHIFT 8
# define GNB_THERMTHRO_MASK (1 << 16)
# define CNB_THERMTHRO_MASK_SCLK (1 << 17)
# define DPM_SCLK_ENABLE (1 << 18)
# define GNB_SLOW_FSTATE_0_MASK (1 << 23)
# define GNB_SLOW_FSTATE_0_SHIFT 23
# define FORCE_NB_PSTATE_1 (1 << 31)
#define CG_SSP 0x6e8
# define SST(x) ((x) << 0)
# define SST_MASK (0xffff << 0)
# define SST_SHIFT 0
# define SSTU(x) ((x) << 16)
# define SSTU_MASK (0xffff << 16)
# define SSTU_SHIFT 16
#define CG_ACPI_CNTL 0x70c
# define SCLK_ACPI_DIV(x) ((x) << 0)
# define SCLK_ACPI_DIV_MASK (0x7f << 0)
# define SCLK_ACPI_DIV_SHIFT 0
#define CG_SCLK_DPM_CTRL_4 0x71c
# define DC_HDC(x) ((x) << 14)
# define DC_HDC_MASK (0x3fff << 14)
# define DC_HDC_SHIFT 14
# define DC_HU(x) ((x) << 28)
# define DC_HU_MASK (0xf << 28)
# define DC_HU_SHIFT 28
#define CG_SCLK_DPM_CTRL_5 0x720
# define SCLK_FSTATE_BOOTUP(x) ((x) << 0)
# define SCLK_FSTATE_BOOTUP_MASK (0x7 << 0)
# define SCLK_FSTATE_BOOTUP_SHIFT 0
# define TT_TP(x) ((x) << 3)
# define TT_TP_MASK (0xffff << 3)
# define TT_TP_SHIFT 3
# define TT_TU(x) ((x) << 19)
# define TT_TU_MASK (0xff << 19)
# define TT_TU_SHIFT 19
#define CG_SCLK_DPM_CTRL_6 0x724
#define CG_AT_0 0x728
# define CG_R(x) ((x) << 0)
# define CG_R_MASK (0xffff << 0)
# define CG_R_SHIFT 0
# define CG_L(x) ((x) << 16)
# define CG_L_MASK (0xffff << 16)
# define CG_L_SHIFT 16
#define CG_AT_1 0x72c
#define CG_AT_2 0x730
#define CG_THERMAL_INT 0x734
#define DIG_THERM_INTH(x) ((x) << 8)
#define DIG_THERM_INTH_MASK 0x0000FF00
#define DIG_THERM_INTH_SHIFT 8
#define DIG_THERM_INTL(x) ((x) << 16)
#define DIG_THERM_INTL_MASK 0x00FF0000
#define DIG_THERM_INTL_SHIFT 16
#define THERM_INT_MASK_HIGH (1 << 24)
#define THERM_INT_MASK_LOW (1 << 25)
#define CG_AT_3 0x738
#define CG_AT_4 0x73c
#define CG_AT_5 0x740
#define CG_AT_6 0x744
#define CG_AT_7 0x748
#define CG_BSP_0 0x750
# define BSP(x) ((x) << 0)
# define BSP_MASK (0xffff << 0)
# define BSP_SHIFT 0
# define BSU(x) ((x) << 16)
# define BSU_MASK (0xf << 16)
# define BSU_SHIFT 16
#define CG_CG_VOLTAGE_CNTL 0x770
# define REQ (1 << 0)
# define LEVEL(x) ((x) << 1)
# define LEVEL_MASK (0x3 << 1)
# define LEVEL_SHIFT 1
# define CG_VOLTAGE_EN (1 << 3)
# define FORCE (1 << 4)
# define PERIOD(x) ((x) << 8)
# define PERIOD_MASK (0xffff << 8)
# define PERIOD_SHIFT 8
# define UNIT(x) ((x) << 24)
# define UNIT_MASK (0xf << 24)
# define UNIT_SHIFT 24
#define CG_ACPI_VOLTAGE_CNTL 0x780
# define ACPI_VOLTAGE_EN (1 << 8)
#define CG_DPM_VOLTAGE_CNTL 0x788
# define DPM_STATE0_LEVEL_MASK (0x3 << 0)
# define DPM_STATE0_LEVEL_SHIFT 0
# define DPM_VOLTAGE_EN (1 << 16)
#define CG_PWR_GATING_CNTL 0x7ac
# define DYN_PWR_DOWN_EN (1 << 0)
# define ACPI_PWR_DOWN_EN (1 << 1)
# define GFX_CLK_OFF_PWR_DOWN_EN (1 << 2)
# define IOC_DISGPU_PWR_DOWN_EN (1 << 3)
# define FORCE_POWR_ON (1 << 4)
# define PGP(x) ((x) << 8)
# define PGP_MASK (0xffff << 8)
# define PGP_SHIFT 8
# define PGU(x) ((x) << 24)
# define PGU_MASK (0xf << 24)
# define PGU_SHIFT 24
#define CG_CGTT_LOCAL_0 0x7d0
#define CG_CGTT_LOCAL_1 0x7d4
#define DEEP_SLEEP_CNTL 0x818
# define R_DIS (1 << 3)
# define HS(x) ((x) << 4)
# define HS_MASK (0xfff << 4)
# define HS_SHIFT 4
# define ENABLE_DS (1 << 31)
#define DEEP_SLEEP_CNTL2 0x81c
# define LB_UFP_EN (1 << 0)
# define INOUT_C(x) ((x) << 4)
# define INOUT_C_MASK (0xff << 4)
# define INOUT_C_SHIFT 4
#define CG_SCRATCH2 0x824
#define CG_SCLK_DPM_CTRL_11 0x830
#define HW_REV 0x5564
# define ATI_REV_ID_MASK (0xf << 28)
# define ATI_REV_ID_SHIFT 28
/* 0 = A0, 1 = A1, 2 = B0, 3 = C0, etc. */
#define DOUT_SCRATCH3 0x611c
#define GB_ADDR_CONFIG 0x98f8
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,131 @@
/*
* Copyright 2012 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.
*
*/
#ifndef __TRINITY_DPM_H__
#define __TRINITY_DPM_H__
#include "sumo_dpm.h"
#define TRINITY_SIZEOF_DPM_STATE_TABLE (SMU_SCLK_DPM_STATE_1_CNTL_0 - SMU_SCLK_DPM_STATE_0_CNTL_0)
struct trinity_pl {
u32 sclk;
u8 vddc_index;
u8 ds_divider_index;
u8 ss_divider_index;
u8 allow_gnb_slow;
u8 force_nbp_state;
u8 display_wm;
u8 vce_wm;
};
#define TRINITY_POWERSTATE_FLAGS_NBPS_FORCEHIGH (1 << 0)
#define TRINITY_POWERSTATE_FLAGS_NBPS_LOCKTOHIGH (1 << 1)
#define TRINITY_POWERSTATE_FLAGS_NBPS_LOCKTOLOW (1 << 2)
#define TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE (1 << 0)
struct trinity_ps {
u32 num_levels;
struct trinity_pl levels[SUMO_MAX_HARDWARE_POWERLEVELS];
u32 nbps_flags;
u32 bapm_flags;
u8 Dpm0PgNbPsLo;
u8 Dpm0PgNbPsHi;
u8 DpmXNbPsLo;
u8 DpmXNbPsHi;
u32 vclk_low_divider;
u32 vclk_high_divider;
u32 dclk_low_divider;
u32 dclk_high_divider;
};
#define TRINITY_NUM_NBPSTATES 4
struct trinity_uvd_clock_table_entry
{
u32 vclk;
u32 dclk;
u8 vclk_did;
u8 dclk_did;
u8 rsv[2];
};
struct trinity_sys_info {
u32 bootup_uma_clk;
u32 bootup_sclk;
u32 min_sclk;
u32 dentist_vco_freq;
u32 nb_dpm_enable;
u32 nbp_mclk[TRINITY_NUM_NBPSTATES];
u32 nbp_nclk[TRINITY_NUM_NBPSTATES];
u16 nbp_voltage_index[TRINITY_NUM_NBPSTATES];
u16 bootup_nb_voltage_index;
u8 htc_tmp_lmt;
u8 htc_hyst_lmt;
struct sumo_sclk_voltage_mapping_table sclk_voltage_mapping_table;
struct sumo_vid_mapping_table vid_mapping_table;
u32 uma_channel_number;
struct trinity_uvd_clock_table_entry uvd_clock_table_entries[4];
};
struct trinity_power_info {
u32 at[SUMO_MAX_HARDWARE_POWERLEVELS];
u32 dpm_interval;
u32 thermal_auto_throttling;
struct trinity_sys_info sys_info;
struct trinity_pl boot_pl;
u32 min_sclk_did;
bool enable_nbps_policy;
bool voltage_drop_in_dce;
bool override_dynamic_mgpg;
bool enable_gfx_clock_gating;
bool enable_gfx_power_gating;
bool enable_mg_clock_gating;
bool enable_gfx_dynamic_mgpg;
bool enable_auto_thermal_throttling;
bool enable_dpm;
bool enable_sclk_ds;
bool uvd_dpm;
struct radeon_ps current_rps;
struct trinity_ps current_ps;
struct radeon_ps requested_rps;
struct trinity_ps requested_ps;
};
#define TRINITY_AT_DFLT 30
/* trinity_smc.c */
int trinity_dpm_config(struct radeon_device *rdev, bool enable);
int trinity_uvd_dpm_config(struct radeon_device *rdev);
int trinity_dpm_force_state(struct radeon_device *rdev, u32 n);
int trinity_dpm_no_forced_level(struct radeon_device *rdev);
int trinity_dce_enable_voltage_adjustment(struct radeon_device *rdev,
bool enable);
int trinity_gfx_dynamic_mgpg_config(struct radeon_device *rdev);
void trinity_acquire_mutex(struct radeon_device *rdev);
void trinity_release_mutex(struct radeon_device *rdev);
#endif

View File

@ -0,0 +1,115 @@
/*
* Copyright 2012 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.
*
*/
#include "drmP.h"
#include "radeon.h"
#include "trinityd.h"
#include "trinity_dpm.h"
#include "ppsmc.h"
struct trinity_ps *trinity_get_ps(struct radeon_ps *rps);
struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev);
static int trinity_notify_message_to_smu(struct radeon_device *rdev, u32 id)
{
int i;
u32 v = 0;
WREG32(SMC_MESSAGE_0, id);
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(SMC_RESP_0) != 0)
break;
udelay(1);
}
v = RREG32(SMC_RESP_0);
if (v != 1) {
if (v == 0xFF) {
DRM_ERROR("SMC failed to handle the message!\n");
return -EINVAL;
} else if (v == 0xFE) {
DRM_ERROR("Unknown SMC message!\n");
return -EINVAL;
}
}
return 0;
}
int trinity_dpm_config(struct radeon_device *rdev, bool enable)
{
if (enable)
WREG32_SMC(SMU_SCRATCH0, 1);
else
WREG32_SMC(SMU_SCRATCH0, 0);
return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_Config);
}
int trinity_dpm_force_state(struct radeon_device *rdev, u32 n)
{
WREG32_SMC(SMU_SCRATCH0, n);
return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_ForceState);
}
int trinity_uvd_dpm_config(struct radeon_device *rdev)
{
return trinity_notify_message_to_smu(rdev, PPSMC_MSG_UVD_DPM_Config);
}
int trinity_dpm_no_forced_level(struct radeon_device *rdev)
{
return trinity_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel);
}
int trinity_dce_enable_voltage_adjustment(struct radeon_device *rdev,
bool enable)
{
if (enable)
return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DCE_AllowVoltageAdjustment);
else
return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DCE_RemoveVoltageAdjustment);
}
int trinity_gfx_dynamic_mgpg_config(struct radeon_device *rdev)
{
return trinity_notify_message_to_smu(rdev, PPSMC_MSG_PG_SIMD_Config);
}
void trinity_acquire_mutex(struct radeon_device *rdev)
{
int i;
WREG32(SMC_INT_REQ, 1);
for (i = 0; i < rdev->usec_timeout; i++) {
if ((RREG32(SMC_INT_REQ) & 0xffff) == 1)
break;
udelay(1);
}
}
void trinity_release_mutex(struct radeon_device *rdev)
{
WREG32(SMC_INT_REQ, 0);
}

View File

@ -0,0 +1,228 @@
/*
* Copyright 2012 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: Alex Deucher
*/
#ifndef _TRINITYD_H_
#define _TRINITYD_H_
/* pm registers */
/* cg */
#define CG_CGTT_LOCAL_0 0x0
#define CG_CGTT_LOCAL_1 0x1
/* smc */
#define SMU_SCLK_DPM_STATE_0_CNTL_0 0x1f000
# define STATE_VALID(x) ((x) << 0)
# define STATE_VALID_MASK (0xff << 0)
# define STATE_VALID_SHIFT 0
# define CLK_DIVIDER(x) ((x) << 8)
# define CLK_DIVIDER_MASK (0xff << 8)
# define CLK_DIVIDER_SHIFT 8
# define VID(x) ((x) << 16)
# define VID_MASK (0xff << 16)
# define VID_SHIFT 16
# define LVRT(x) ((x) << 24)
# define LVRT_MASK (0xff << 24)
# define LVRT_SHIFT 24
#define SMU_SCLK_DPM_STATE_0_CNTL_1 0x1f004
# define DS_DIV(x) ((x) << 0)
# define DS_DIV_MASK (0xff << 0)
# define DS_DIV_SHIFT 0
# define DS_SH_DIV(x) ((x) << 8)
# define DS_SH_DIV_MASK (0xff << 8)
# define DS_SH_DIV_SHIFT 8
# define DISPLAY_WM(x) ((x) << 16)
# define DISPLAY_WM_MASK (0xff << 16)
# define DISPLAY_WM_SHIFT 16
# define VCE_WM(x) ((x) << 24)
# define VCE_WM_MASK (0xff << 24)
# define VCE_WM_SHIFT 24
#define SMU_SCLK_DPM_STATE_0_CNTL_3 0x1f00c
# define GNB_SLOW(x) ((x) << 0)
# define GNB_SLOW_MASK (0xff << 0)
# define GNB_SLOW_SHIFT 0
# define FORCE_NBPS1(x) ((x) << 8)
# define FORCE_NBPS1_MASK (0xff << 8)
# define FORCE_NBPS1_SHIFT 8
#define SMU_SCLK_DPM_STATE_0_AT 0x1f010
# define AT(x) ((x) << 0)
# define AT_MASK (0xff << 0)
# define AT_SHIFT 0
#define SMU_SCLK_DPM_STATE_0_PG_CNTL 0x1f014
# define PD_SCLK_DIVIDER(x) ((x) << 16)
# define PD_SCLK_DIVIDER_MASK (0xff << 16)
# define PD_SCLK_DIVIDER_SHIFT 16
#define SMU_SCLK_DPM_STATE_1_CNTL_0 0x1f020
#define SMU_SCLK_DPM_CNTL 0x1f100
# define SCLK_DPM_EN(x) ((x) << 0)
# define SCLK_DPM_EN_MASK (0xff << 0)
# define SCLK_DPM_EN_SHIFT 0
# define SCLK_DPM_BOOT_STATE(x) ((x) << 16)
# define SCLK_DPM_BOOT_STATE_MASK (0xff << 16)
# define SCLK_DPM_BOOT_STATE_SHIFT 16
# define VOLTAGE_CHG_EN(x) ((x) << 24)
# define VOLTAGE_CHG_EN_MASK (0xff << 24)
# define VOLTAGE_CHG_EN_SHIFT 24
#define SMU_SCLK_DPM_TT_CNTL 0x1f108
# define SCLK_TT_EN(x) ((x) << 0)
# define SCLK_TT_EN_MASK (0xff << 0)
# define SCLK_TT_EN_SHIFT 0
#define SMU_SCLK_DPM_TTT 0x1f10c
# define LT(x) ((x) << 0)
# define LT_MASK (0xffff << 0)
# define LT_SHIFT 0
# define HT(x) ((x) << 16)
# define HT_MASK (0xffff << 16)
# define HT_SHIFT 16
#define SMU_UVD_DPM_STATES 0x1f1a0
#define SMU_UVD_DPM_CNTL 0x1f1a4
#define SMU_S_PG_CNTL 0x1f118
# define DS_PG_EN(x) ((x) << 16)
# define DS_PG_EN_MASK (0xff << 16)
# define DS_PG_EN_SHIFT 16
#define GFX_POWER_GATING_CNTL 0x1f38c
# define PDS_DIV(x) ((x) << 0)
# define PDS_DIV_MASK (0xff << 0)
# define PDS_DIV_SHIFT 0
# define SSSD(x) ((x) << 8)
# define SSSD_MASK (0xff << 8)
# define SSSD_SHIFT 8
#define PM_CONFIG 0x1f428
# define SVI_Mode (1 << 29)
#define PM_I_CNTL_1 0x1f464
# define SCLK_DPM(x) ((x) << 0)
# define SCLK_DPM_MASK (0xff << 0)
# define SCLK_DPM_SHIFT 0
# define DS_PG_CNTL(x) ((x) << 16)
# define DS_PG_CNTL_MASK (0xff << 16)
# define DS_PG_CNTL_SHIFT 16
#define PM_TP 0x1f468
#define NB_PSTATE_CONFIG 0x1f5f8
# define Dpm0PgNbPsLo(x) ((x) << 0)
# define Dpm0PgNbPsLo_MASK (3 << 0)
# define Dpm0PgNbPsLo_SHIFT 0
# define Dpm0PgNbPsHi(x) ((x) << 2)
# define Dpm0PgNbPsHi_MASK (3 << 2)
# define Dpm0PgNbPsHi_SHIFT 2
# define DpmXNbPsLo(x) ((x) << 4)
# define DpmXNbPsLo_MASK (3 << 4)
# define DpmXNbPsLo_SHIFT 4
# define DpmXNbPsHi(x) ((x) << 6)
# define DpmXNbPsHi_MASK (3 << 6)
# define DpmXNbPsHi_SHIFT 6
#define DC_CAC_VALUE 0x1f908
#define GPU_CAC_AVRG_CNTL 0x1f920
# define WINDOW_SIZE(x) ((x) << 0)
# define WINDOW_SIZE_MASK (0xff << 0)
# define WINDOW_SIZE_SHIFT 0
#define CC_SMU_MISC_FUSES 0xe0001004
# define MinSClkDid(x) ((x) << 2)
# define MinSClkDid_MASK (0x7f << 2)
# define MinSClkDid_SHIFT 2
#define CC_SMU_TST_EFUSE1_MISC 0xe000101c
# define RB_BACKEND_DISABLE(x) ((x) << 16)
# define RB_BACKEND_DISABLE_MASK (3 << 16)
# define RB_BACKEND_DISABLE_SHIFT 16
#define SMU_SCRATCH_A 0xe0003024
#define SMU_SCRATCH0 0xe0003040
/* mmio */
#define SMC_INT_REQ 0x220
#define SMC_MESSAGE_0 0x22c
#define SMC_RESP_0 0x230
#define GENERAL_PWRMGT 0x670
# define GLOBAL_PWRMGT_EN (1 << 0)
#define SCLK_PWRMGT_CNTL 0x678
# define DYN_PWR_DOWN_EN (1 << 2)
# define RESET_BUSY_CNT (1 << 4)
# define RESET_SCLK_CNT (1 << 5)
# define DYN_GFX_CLK_OFF_EN (1 << 7)
# define GFX_CLK_FORCE_ON (1 << 8)
# define DYNAMIC_PM_EN (1 << 21)
#define TARGET_AND_CURRENT_PROFILE_INDEX 0x684
# define TARGET_STATE(x) ((x) << 0)
# define TARGET_STATE_MASK (0xf << 0)
# define TARGET_STATE_SHIFT 0
# define CURRENT_STATE(x) ((x) << 4)
# define CURRENT_STATE_MASK (0xf << 4)
# define CURRENT_STATE_SHIFT 4
#define CG_GIPOTS 0x6d8
# define CG_GIPOT(x) ((x) << 16)
# define CG_GIPOT_MASK (0xffff << 16)
# define CG_GIPOT_SHIFT 16
#define CG_PG_CTRL 0x6e0
# define SP(x) ((x) << 0)
# define SP_MASK (0xffff << 0)
# define SP_SHIFT 0
# define SU(x) ((x) << 16)
# define SU_MASK (0xffff << 16)
# define SU_SHIFT 16
#define CG_MISC_REG 0x708
#define CG_THERMAL_INT_CTRL 0x738
# define DIG_THERM_INTH(x) ((x) << 0)
# define DIG_THERM_INTH_MASK (0xff << 0)
# define DIG_THERM_INTH_SHIFT 0
# define DIG_THERM_INTL(x) ((x) << 8)
# define DIG_THERM_INTL_MASK (0xff << 8)
# define DIG_THERM_INTL_SHIFT 8
# define THERM_INTH_MASK (1 << 24)
# define THERM_INTL_MASK (1 << 25)
#define CG_CG_VOLTAGE_CNTL 0x770
# define EN (1 << 9)
#define HW_REV 0x5564
# define ATI_REV_ID_MASK (0xf << 28)
# define ATI_REV_ID_SHIFT 28
/* 0 = A0, 1 = A1, 2 = B0, 3 = C0, etc. */
#define CGTS_SM_CTRL_REG 0x9150
#define GB_ADDR_CONFIG 0x98f8
#endif

View File

@ -20,10 +20,13 @@
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Dave Airlie
* Christian König
*/
#ifndef DRM_FIXED_H
#define DRM_FIXED_H
#include <linux/math64.h>
typedef union dfixed {
u32 full;
} fixed20_12;
@ -65,4 +68,95 @@ static inline u32 dfixed_div(fixed20_12 A, fixed20_12 B)
tmp /= 2;
return lower_32_bits(tmp);
}
#define DRM_FIXED_POINT 32
#define DRM_FIXED_ONE (1ULL << DRM_FIXED_POINT)
#define DRM_FIXED_DECIMAL_MASK (DRM_FIXED_ONE - 1)
#define DRM_FIXED_DIGITS_MASK (~DRM_FIXED_DECIMAL_MASK)
static inline s64 drm_int2fixp(int a)
{
return ((s64)a) << DRM_FIXED_POINT;
}
static inline int drm_fixp2int(int64_t a)
{
return ((s64)a) >> DRM_FIXED_POINT;
}
static inline s64 drm_fixp_msbset(int64_t a)
{
unsigned shift, sign = (a >> 63) & 1;
for (shift = 62; shift > 0; --shift)
if ((a >> shift) != sign)
return shift;
return 0;
}
static inline s64 drm_fixp_mul(s64 a, s64 b)
{
unsigned shift = drm_fixp_msbset(a) + drm_fixp_msbset(b);
s64 result;
if (shift > 63) {
shift = shift - 63;
a >>= shift >> 1;
b >>= shift >> 1;
} else
shift = 0;
result = a * b;
if (shift > DRM_FIXED_POINT)
return result << (shift - DRM_FIXED_POINT);
if (shift < DRM_FIXED_POINT)
return result >> (DRM_FIXED_POINT - shift);
return result;
}
static inline s64 drm_fixp_div(s64 a, s64 b)
{
unsigned shift = 63 - drm_fixp_msbset(a);
s64 result;
a <<= shift;
if (shift < DRM_FIXED_POINT)
b >>= (DRM_FIXED_POINT - shift);
result = div64_s64(a, b);
if (shift > DRM_FIXED_POINT)
return result >> (shift - DRM_FIXED_POINT);
return result;
}
static inline s64 drm_fixp_exp(s64 x)
{
s64 tolerance = div64_s64(DRM_FIXED_ONE, 1000000);
s64 sum = DRM_FIXED_ONE, term, y = x;
u64 count = 1;
if (x < 0)
y = -1 * x;
term = y;
while (term >= tolerance) {
sum = sum + term;
count = count + 1;
term = drm_fixp_mul(term, div64_s64(y, count));
}
if (x < 0)
sum = drm_fixp_div(1, sum);
return sum;
}
#endif

View File

@ -152,6 +152,14 @@
{0x1002, 0x6621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6623, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6631, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x665c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x665d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6663, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6664, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
@ -580,6 +588,22 @@
{0x1002, 0x9808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x980A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9832, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9833, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9838, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9839, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x983a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x983b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x983c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x983d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x983e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x983f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x9903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \