From 077bc3bcd02d0fad855bcb23f169fad02dc7af0b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 21 Dec 2009 18:08:12 -0500 Subject: [PATCH] radeontool/avivotool: power mode updates - fix some issues with power mode dumping on pre-atom - dump power tables on atom --- atombios.h | 199 +++++++++++++++++++++++++ atombios_tables.c | 426 +++++++++++++++++++++++++++++++++++++++++++++++++++++ radeontool.c | 3 +- 3 files changed, 627 insertions(+), 1 deletions(-) diff --git a/atombios.h b/atombios.h index 1f7fe14..a7878ab 100644 --- a/atombios.h +++ b/atombios.h @@ -4916,6 +4916,205 @@ typedef struct _ATOM_POWERPLAY_INFO_V3 }ATOM_POWERPLAY_INFO_V3; +/* New PPlib */ +/**************************************************************************/ +typedef struct _ATOM_PPLIB_THERMALCONTROLLER + +{ + UCHAR ucType; // one of ATOM_PP_THERMALCONTROLLER_* + UCHAR ucI2cLine; // as interpreted by DAL I2C + UCHAR ucI2cAddress; + UCHAR ucFanParameters; // Fan Control Parameters. + UCHAR ucFanMinRPM; // Fan Minimum RPM (hundreds) -- for display purposes only. + UCHAR ucFanMaxRPM; // Fan Maximum RPM (hundreds) -- for display purposes only. + UCHAR ucReserved; // ---- + UCHAR ucFlags; // to be defined +} ATOM_PPLIB_THERMALCONTROLLER; + +#define ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f +#define ATOM_PP_FANPARAMETERS_NOFAN 0x80 // No fan is connected to this controller. + +#define ATOM_PP_THERMALCONTROLLER_NONE 0 +#define ATOM_PP_THERMALCONTROLLER_LM63 1 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_ADM1032 2 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_ADM1030 3 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_MUA6649 4 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_LM64 5 +#define ATOM_PP_THERMALCONTROLLER_F75375 6 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_RV6xx 7 +#define ATOM_PP_THERMALCONTROLLER_RV770 8 +#define ATOM_PP_THERMALCONTROLLER_ADT7473 9 + +typedef struct _ATOM_PPLIB_STATE +{ + UCHAR ucNonClockStateIndex; + UCHAR ucClockStateIndices[1]; // variable-sized +} ATOM_PPLIB_STATE; + +//// ATOM_PPLIB_POWERPLAYTABLE::ulPlatformCaps +#define ATOM_PP_PLATFORM_CAP_BACKBIAS 1 +#define ATOM_PP_PLATFORM_CAP_POWERPLAY 2 +#define ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 4 +#define ATOM_PP_PLATFORM_CAP_ASPM_L0s 8 +#define ATOM_PP_PLATFORM_CAP_ASPM_L1 16 +#define ATOM_PP_PLATFORM_CAP_HARDWAREDC 32 +#define ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY 64 +#define ATOM_PP_PLATFORM_CAP_STEPVDDC 128 +#define ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL 256 +#define ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL 512 +#define ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 1024 +#define ATOM_PP_PLATFORM_CAP_HTLINKCONTROL 2048 + +typedef struct _ATOM_PPLIB_POWERPLAYTABLE +{ + ATOM_COMMON_TABLE_HEADER sHeader; + + UCHAR ucDataRevision; + + UCHAR ucNumStates; + UCHAR ucStateEntrySize; + UCHAR ucClockInfoSize; + UCHAR ucNonClockSize; + + // offset from start of this table to array of ucNumStates ATOM_PPLIB_STATE structures + USHORT usStateArrayOffset; + + // offset from start of this table to array of ASIC-specific structures, + // currently ATOM_PPLIB_CLOCK_INFO. + USHORT usClockInfoArrayOffset; + + // offset from start of this table to array of ATOM_PPLIB_NONCLOCK_INFO + USHORT usNonClockInfoArrayOffset; + + USHORT usBackbiasTime; // in microseconds + USHORT usVoltageTime; // in microseconds + USHORT usTableSize; //the size of this structure, or the extended structure + + ULONG ulPlatformCaps; // See ATOM_PPLIB_CAPS_* + + ATOM_PPLIB_THERMALCONTROLLER sThermalController; + + USHORT usBootClockInfoOffset; + USHORT usBootNonClockInfoOffset; + +} ATOM_PPLIB_POWERPLAYTABLE; + +//// ATOM_PPLIB_NONCLOCK_INFO::usClassification +#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 +#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1 +#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3 +#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5 +// 2, 4, 6, 7 are reserved + +#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008 +#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010 +#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020 +#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040 +#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080 +#define ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE 0x0100 +#define ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE 0x0200 +#define ATOM_PPLIB_CLASSIFICATION_UVDSTATE 0x0400 +#define ATOM_PPLIB_CLASSIFICATION_3DLOW 0x0800 +#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000 +// remaining 3 bits are reserved + +//// ATOM_PPLIB_NONCLOCK_INFO::ulCapsAndSettings +#define ATOM_PPLIB_SINGLE_DISPLAY_ONLY 0x00000001 +#define ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK 0x00000002 + +// 0 is 2.5Gb/s, 1 is 5Gb/s +#define ATOM_PPLIB_PCIE_LINK_SPEED_MASK 0x00000004 +#define ATOM_PPLIB_PCIE_LINK_SPEED_SHIFT 2 + +// lanes - 1: 1, 2, 4, 8, 12, 16 permitted by PCIE spec +#define ATOM_PPLIB_PCIE_LINK_WIDTH_MASK 0x000000F8 +#define ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT 3 + +// lookup into reduced refresh-rate table +#define ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK 0x00000F00 +#define ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT 8 + +#define ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED 0 +#define ATOM_PPLIB_LIMITED_REFRESHRATE_50HZ 1 +// 2-15 TBD as needed. + +#define ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING 0x00001000 +#define ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS 0x00002000 +#define ATOM_PPLIB_ENABLE_VARIBRIGHT 0x00008000 + +#define ATOM_PPLIB_DISALLOW_ON_DC 0x00004000 + +// Contained in an array starting at the offset +// in ATOM_PPLIB_POWERPLAYTABLE::usNonClockInfoArrayOffset. +// referenced from ATOM_PPLIB_STATE_INFO::ucNonClockStateIndex +typedef struct _ATOM_PPLIB_NONCLOCK_INFO +{ + USHORT usClassification; + UCHAR ucMinTemperature; + UCHAR ucMaxTemperature; + ULONG ulCapsAndSettings; + UCHAR ucRequiredPower; + UCHAR ucUnused1[3]; +} ATOM_PPLIB_NONCLOCK_INFO; + +// Contained in an array starting at the offset +// in ATOM_PPLIB_POWERPLAYTABLE::usClockInfoArrayOffset. +// referenced from ATOM_PPLIB_STATE::ucClockStateIndices +typedef struct _ATOM_PPLIB_R600_CLOCK_INFO +{ + USHORT usEngineClockLow; + UCHAR ucEngineClockHigh; + + USHORT usMemoryClockLow; + UCHAR ucMemoryClockHigh; + + USHORT usVDDC; + USHORT usUnused1; + USHORT usUnused2; + + ULONG ulFlags; // ATOM_PPLIB_R600_FLAGS_* + +} ATOM_PPLIB_R600_CLOCK_INFO; + +// ulFlags in ATOM_PPLIB_R600_CLOCK_INFO +#define ATOM_PPLIB_R600_FLAGS_PCIEGEN2 1 +#define ATOM_PPLIB_R600_FLAGS_UVDSAFE 2 +#define ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE 4 +#define ATOM_PPLIB_R600_FLAGS_MEMORY_ODT_OFF 8 +#define ATOM_PPLIB_R600_FLAGS_MEMORY_DLL_OFF 16 + +typedef struct _ATOM_PPLIB_RS780_CLOCK_INFO + +{ + USHORT usLowEngineClockLow; // Low Engine clock in MHz (the same way as on the R600). + UCHAR ucLowEngineClockHigh; + USHORT usHighEngineClockLow; // High Engine clock in MHz. + UCHAR ucHighEngineClockHigh; + USHORT usMemoryClockLow; // For now one of the ATOM_PPLIB_RS780_SPMCLK_XXXX constants. + UCHAR ucMemoryClockHigh; // Currentyl unused. + UCHAR ucPadding; // For proper alignment and size. + USHORT usVDDC; // For the 780, use: None, Low, High, Variable + UCHAR ucMaxHTLinkWidth; // From SBIOS - {2, 4, 8, 16} + UCHAR ucMinHTLinkWidth; // From SBIOS - {2, 4, 8, 16}. Effective only if CDLW enabled. Minimum down stream width could be bigger as display BW requriement. + USHORT usHTLinkFreq; // See definition ATOM_PPLIB_RS780_HTLINKFREQ_xxx or in MHz(>=200). + ULONG ulFlags; +} ATOM_PPLIB_RS780_CLOCK_INFO; + +#define ATOM_PPLIB_RS780_VOLTAGE_NONE 0 +#define ATOM_PPLIB_RS780_VOLTAGE_LOW 1 +#define ATOM_PPLIB_RS780_VOLTAGE_HIGH 2 +#define ATOM_PPLIB_RS780_VOLTAGE_VARIABLE 3 + +#define ATOM_PPLIB_RS780_SPMCLK_NONE 0 // We cannot change the side port memory clock, leave it as it is. +#define ATOM_PPLIB_RS780_SPMCLK_LOW 1 +#define ATOM_PPLIB_RS780_SPMCLK_HIGH 2 + +#define ATOM_PPLIB_RS780_HTLINKFREQ_NONE 0 +#define ATOM_PPLIB_RS780_HTLINKFREQ_LOW 1 +#define ATOM_PPLIB_RS780_HTLINKFREQ_HIGH 2 + /**************************************************************************/ diff --git a/atombios_tables.c b/atombios_tables.c index 6cd7584..1169296 100644 --- a/atombios_tables.c +++ b/atombios_tables.c @@ -559,7 +559,431 @@ void radeon_execute_hw_i2c_table(struct atom_context *ctx) } +static char *thermal_controller_names[] = { + "NONE", + "LM63", + "ADM1032", + "ADM1030", + "MUA6649", + "LM64", + "F75375", + "ASC7512", +}; + +static char *pp_lib_thermal_controller_names[] = { + "NONE", + "LM63", + "ADM1032", + "ADM1030", + "MUA6649", + "LM64", + "F75375", + "RV6xx", + "RV770", + "ADT7473", +}; + +static void radeon_print_pp_misc(uint32_t misc) +{ + if (misc & ATOM_PM_MISCINFO_SPLIT_CLOCK) + printf("\t\tSPLIT_CLOCK\n"); + if (misc & ATOM_PM_MISCINFO_USING_MCLK_SRC) + printf("\t\tUSING_MCLK_SRC\n"); + if (misc & ATOM_PM_MISCINFO_USING_SCLK_SRC) + printf("\t\tUSING_SCLK_SRC\n"); + if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) + printf("\t\tVOLTAGE_DROP_SUPPORT\n"); + if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) + printf("\t\tVOLTAGE_DROP_ACTIVE_HIGH\n"); + if (misc & ATOM_PM_MISCINFO_LOAD_PERFORMANCE_EN) + printf("\t\tLOAD_PERFORMANCE_EN\n"); + if (misc & ATOM_PM_MISCINFO_ENGINE_CLOCK_CONTRL_EN) + printf("\t\tENGINE_CLOCK_CONTRL_EN\n"); + if (misc & ATOM_PM_MISCINFO_MEMORY_CLOCK_CONTRL_EN) + printf("\t\tMEMORY_CLOCK_CONTRL_EN\n"); + if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) + printf("\t\tPROGRAM_VOLTAGE\n"); + if (misc & ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN) + printf("\t\tASIC_REDUCED_SPEED_SCLK_EN\n"); + if (misc & ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN) + printf("\t\tASIC_DYNAMIC_VOLTAGE_EN\n"); + if (misc & ATOM_PM_MISCINFO_ASIC_SLEEP_MODE_EN) + printf("\t\tASIC_SLEEP_MODE_EN\n"); + if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) + printf("\t\tLOAD_BALANCE_EN\n"); + if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) + printf("\t\tDEFAULT_DC_STATE_ENTRY_TRUE\n"); + if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) + printf("\t\tDEFAULT_LOW_DC_STATE_ENTRY_TRUE\n"); + if (misc & ATOM_PM_MISCINFO_LOW_LCD_REFRESH_RATE) + printf("\t\tLOW_LCD_REFRESH_RATE\n"); + if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) + printf("\t\tDRIVER_DEFAULT_MODE\n"); + if (misc & ATOM_PM_MISCINFO_OVER_CLOCK_MODE) + printf("\t\tOVER_CLOCK_MODE\n"); + if (misc & ATOM_PM_MISCINFO_OVER_DRIVE_MODE) + printf("\t\tOVER_DRIVE_MODE\n"); + if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) + printf("\t\tPOWER_SAVING_MODE\n"); + if (misc & ATOM_PM_MISCINFO_THERMAL_DIODE_MODE) + printf("\t\tTHERMAL_DIODE_MODE\n"); + if (misc & ATOM_PM_MISCINFO_FRAME_MODULATION_MASK) + printf("\t\tFM: 0x%x\n", + (misc & ATOM_PM_MISCINFO_FRAME_MODULATION_MASK) >> ATOM_PM_MISCINFO_FRAME_MODULATION_SHIFT); + if (misc & ATOM_PM_MISCINFO_DYN_CLK_3D_IDLE) + printf("\t\tDYN_CLK_3D_IDLE\n"); + if (misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2) + printf("\t\tDYNAMIC_CLOCK_DIVIDER_BY_2\n"); + if (misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4) + printf("\t\tDYNAMIC_CLOCK_DIVIDER_BY_4\n"); + if (misc & ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN) + printf("\t\tDYNAMIC_HDP_BLOCK_EN\n"); + if (misc & ATOM_PM_MISCINFO_DYNAMIC_MC_HOST_BLOCK_EN) + printf("\t\tDYNAMIC_MC_HOST_BLOCK_EN\n"); + if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) + printf("\t\t3D_ACCELERATION_EN\n"); + switch ((misc & ATOM_PM_MISCINFO_POWERPLAY_SETTINGS_GROUP_MASK) >> + ATOM_PM_MISCINFO_POWERPLAY_SETTINGS_GROUP_SHIFT) { + case 1: + printf("\t\tOptimal Battery Life\n"); + break; + case 2: + printf("\t\tHigh Battery\n"); + break; + case 3: + printf("\t\tBalanced\n"); + break; + case 4: + printf("\t\tHigh Performance\n"); + break; + case 5: + printf("\t\tOptimal Performance (Default state with Default clocks)\n"); + break; + default: + break; + } + if (misc & ATOM_PM_MISCINFO_ENABLE_BACK_BIAS) + printf("\t\tENABLE_BACK_BIAS\n"); +} + +static void radeon_print_pp_misc2(uint32_t misc) +{ + if (misc & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) + printf("\t\tSYSTEM_AC_LITE_MODE\n"); + if (misc & ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT) + printf("\t\tMULTI_DISPLAY_SUPPORT\n"); + if (misc & ATOM_PM_MISCINFO2_DYNAMIC_BACK_BIAS_EN) + printf("\t\tDYNAMIC_BACK_BIAS_EN\n"); + if (misc & ATOM_PM_MISCINFO2_FS3D_OVERDRIVE_INFO) + printf("\t\tFS3D_OVERDRIVE_INFO\n"); + if (misc & ATOM_PM_MISCINFO2_FORCEDLOWPWR_MODE) + printf("\t\tFORCEDLOWPWR_MODE\n"); + if (misc & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) + printf("\t\tVDDCI_DYNAMIC_VOLTAGE_EN\n"); + if (misc & ATOM_PM_MISCINFO2_VIDEO_PLAYBACK_CAPABLE) + printf("\t\tVIDEO_PLAYBACK_CAPABLE\n"); + if (misc & ATOM_PM_MISCINFO2_NOT_VALID_ON_DC) + printf("\t\tNOT_VALID_ON_DC\n"); + if (misc & ATOM_PM_MISCINFO2_STUTTER_MODE_EN) + printf("\t\tSTUTTER_MODE_EN\n"); + if (misc & ATOM_PM_MISCINFO2_UVD_SUPPORT_MODE) + printf("\t\tUVD_SUPPORT_MODE\n"); + +} + +static void radeon_print_pp_lib_platform_caps(uint32_t caps) +{ + if (caps & ATOM_PP_PLATFORM_CAP_BACKBIAS) + printf("\tBACKBIAS\n"); + if (caps & ATOM_PP_PLATFORM_CAP_POWERPLAY) + printf("\tPOWERPLAY\n"); + if (caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE) + printf("\tSBIOSPOWERSOURCE\n"); + if (caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s) + printf("\tASPM_L0s\n"); + if (caps & ATOM_PP_PLATFORM_CAP_ASPM_L1) + printf("\tASPM_L1\n"); + if (caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC) + printf("\tHARDWAREDC\n"); + if (caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY) + printf("\tGEMINIPRIMARY\n"); + if (caps & ATOM_PP_PLATFORM_CAP_STEPVDDC) + printf("\tSTEPVDDC\n"); + if (caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL) + printf("\tVOLTAGECONTROL\n"); + if (caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL) + printf("\tSIDEPORTCONTROL\n"); + if (caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1) + printf("\tTURNOFFPLL_ASPML1\n"); + if (caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL) + printf("\tHTLINKCONTROL\n"); +} + +static void radeon_print_pp_lib_clock_flags_discrete(uint32_t flags) +{ + if (flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) + printf("\t\tPCIEGEN2\n"); + if (flags & ATOM_PPLIB_R600_FLAGS_UVDSAFE) + printf("\t\tUVDSAFE\n"); + if (flags & ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE) + printf("\t\tBACKBIASENABLE\n"); + if (flags & ATOM_PPLIB_R600_FLAGS_MEMORY_ODT_OFF) + printf("\t\tMEMORY_ODT_OFF\n"); + if (flags & ATOM_PPLIB_R600_FLAGS_MEMORY_DLL_OFF) + printf("\t\tMEMORY_DLL_OFF\n"); + +} + +static void radeon_print_pp_lib_clock_flags_igp(uint32_t flags) +{ + printf("\t\t0x%08x\n", flags); + +} + +static void radeon_print_pp_lib_non_clock_flags(uint32_t flags) +{ + int link_speed = (flags & ATOM_PPLIB_PCIE_LINK_SPEED_MASK) >> ATOM_PPLIB_PCIE_LINK_SPEED_SHIFT; + int link_width = (flags & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT; + if (flags & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) + printf("\t\tSINGLE_DISPLAY_ONLY\n"); + if (flags & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK) + printf("\t\tSUPPORTS_VIDEO_PLAYBACK\n"); + if (flags & ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING) + printf("\t\tDISABLE_LOADBALANCING\n"); + if (flags & ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS) + printf("\t\tENABLE_SLEEP_FOR_TIMESTAMPS\n"); + if (flags & ATOM_PPLIB_ENABLE_VARIBRIGHT) + printf("\t\tENABLE_VARIBRIGHT\n"); + if (flags & ATOM_PPLIB_DISALLOW_ON_DC) + printf("\t\tDISALLOW_ON_DC\n"); + printf("\tPCIE link speed: %s\n", link_speed ? "5.0 Gbps" : "2.5 Gbps"); + printf("\tPCIE lanes: %d\n", link_width + 1); +} +static void radeon_print_pp_lib_non_clock_class(uint16_t class) +{ + int class_type = (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; + switch (class_type) { + case ATOM_PPLIB_CLASSIFICATION_UI_NONE: + printf("\t\tNONE\n"); + break; + case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: + printf("\t\tBATTERY\n"); + break; + case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: + printf("\t\tBALANCED\n"); + break; + case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: + printf("\t\tPERFORMANCE\n"); + break; + default: + break; + } + if (class & ATOM_PPLIB_CLASSIFICATION_BOOT) + printf("\t\tBOOT\n"); + if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL) + printf("\t\tTHERMAL\n"); + if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) + printf("\t\tLIMITEDPOWERSOURCE\n"); + if (class & ATOM_PPLIB_CLASSIFICATION_REST) + printf("\t\tREST\n"); + if (class & ATOM_PPLIB_CLASSIFICATION_FORCED) + printf("\t\tFORCED\n"); + if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) + printf("\t\t3DPERFORMANCE\n"); + if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) + printf("\t\tOVERDRIVETEMPLATE\n"); + if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) + printf("\t\tUVDSTATE\n"); + if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW) + printf("\t\t3DLOW\n"); + if (class & ATOM_PPLIB_CLASSIFICATION_ACPI) + printf("\t\tACPI\n"); +} + +union pp_info { + struct _ATOM_POWERPLAY_INFO info; + struct _ATOM_POWERPLAY_INFO_V2 info_2; + struct _ATOM_POWERPLAY_INFO_V3 info_3; + struct _ATOM_PPLIB_POWERPLAYTABLE info_4; +}; + +/* asic specific */ +union clock_info { + struct _ATOM_PPLIB_R600_CLOCK_INFO r600; + struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; +}; + +void radeon_dump_bios_pp_table(struct atom_context *ctx) +{ + uint16_t size, data_offset; + uint8_t frev, crev; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + union pp_info *pp_info; + union clock_info *clock_info; + ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; + ATOM_PPLIB_STATE *power_state; + int num_modes = 0, i, j; + uint32_t sclk, mclk; + + atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); + + pp_info = (union pp_info *)(ctx->bios + data_offset); + + printf("\nPOWERPLAY\n"); + printf("pp v %d %d\n", frev, crev); + + if (frev < 4) { + printf("thermal controller: %s on 0x%02x at 0x%02x - int bitmap 0x%02x\n", + thermal_controller_names[pp_info->info.ucOverdriveThermalController], + pp_info->info.ucOverdriveI2cLine, + pp_info->info.ucOverdriveControllerAddress, + pp_info->info.ucOverdriveIntBitmap); + printf("%d power modes (lowest to highest)\n", pp_info->info.ucNumOfPowerModeEntries); + num_modes = pp_info->info.ucNumOfPowerModeEntries; + if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) + num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; + + for (i = 0; i < num_modes; i++) { + printf("== power mode %d ==\n", i); + switch (frev) { + case 1: + printf("\tengine: %d, memory: %d\n", + pp_info->info.asPowerPlayInfo[i].usEngineClock, + pp_info->info.asPowerPlayInfo[i].usMemoryClock); + printf("\tpcie lanes: %d\n", + pp_info->info.asPowerPlayInfo[i].ucNumPciELanes); + printf("\ttemp: %d - %d\n", + pp_info->info.asPowerPlayInfo[i].ucMinTemperature, + pp_info->info.asPowerPlayInfo[i].ucMaxTemperature); + printf("\tpanel refresh: %d\n", + pp_info->info.asPowerPlayInfo[i].ucSelectedPanel_RefreshRate); + printf("\tvoltage gpio id: 0x%02x\n", + pp_info->info.asPowerPlayInfo[i].ucVoltageDropIndex); + printf("\tflags:\n"); + radeon_print_pp_misc(pp_info->info.asPowerPlayInfo[i].ulMiscInfo); + break; + case 2: + printf("\tengine: %d, memory: %d\n", + pp_info->info_2.asPowerPlayInfo[i].ulEngineClock, + pp_info->info_2.asPowerPlayInfo[i].ulMemoryClock); + printf("\tpcie lanes: %d\n", + pp_info->info_2.asPowerPlayInfo[i].ucNumPciELanes); + printf("\ttemp: %d - %d\n", + pp_info->info_2.asPowerPlayInfo[i].ucMinTemperature, + pp_info->info_2.asPowerPlayInfo[i].ucMaxTemperature); + printf("\tpanel refresh: %d\n", + pp_info->info_2.asPowerPlayInfo[i].ucSelectedPanel_RefreshRate); + printf("\tvoltage gpio id: 0x%02x\n", + pp_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex); + printf("\tflags:\n"); + radeon_print_pp_misc(pp_info->info_2.asPowerPlayInfo[i].ulMiscInfo); + radeon_print_pp_misc2(pp_info->info_2.asPowerPlayInfo[i].ulMiscInfo2); + break; + case 3: + printf("\tengine: %d, memory: %d\n", + pp_info->info_3.asPowerPlayInfo[i].ulEngineClock, + pp_info->info_3.asPowerPlayInfo[i].ulMemoryClock); + printf("\tpcie lanes: %d\n", + pp_info->info_3.asPowerPlayInfo[i].ucNumPciELanes); + printf("\ttemp: %d - %d\n", + pp_info->info_3.asPowerPlayInfo[i].ucMinTemperature, + pp_info->info_3.asPowerPlayInfo[i].ucMaxTemperature); + printf("\tpanel refresh: %d\n", + pp_info->info_3.asPowerPlayInfo[i].ucSelectedPanel_RefreshRate); + printf("\tVDDC index: 0x%02x\n", + pp_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex); + printf("\tVDDCI index: 0x%02x\n", + pp_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex); + printf("\tflags:\n"); + radeon_print_pp_misc(pp_info->info_3.asPowerPlayInfo[i].ulMiscInfo); + radeon_print_pp_misc2(pp_info->info_3.asPowerPlayInfo[i].ulMiscInfo2); + break; + default: + break; + } + } + } else { + printf("thermal controller: %s on 0x%02x at 0x%02x\n", + pp_lib_thermal_controller_names[pp_info->info_4.sThermalController.ucType], + pp_info->info_4.sThermalController.ucI2cLine, + pp_info->info_4.sThermalController.ucI2cAddress); + if (pp_info->info_4.sThermalController.ucType != 0) { + if (pp_info->info_4.sThermalController.ucFanParameters) + printf("\tno fan connected\n"); + else { + printf("\tfan connected\n"); + printf("\ttach pulse per rev: %d\n", + pp_info->info_4.sThermalController.ucFanParameters & + ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK); + printf("\trpm: %d - %d\n", pp_info->info_4.sThermalController.ucFanMinRPM, + pp_info->info_4.sThermalController.ucFanMaxRPM); + } + } + printf("back bias time: %d usec\n",pp_info->info_4.usBackbiasTime); + printf("voltage time: %d usec\n",pp_info->info_4.usVoltageTime); + printf("platform caps:\n"); + radeon_print_pp_lib_platform_caps(pp_info->info_4.ulPlatformCaps); + printf("%d power modes\n", pp_info->info_4.ucNumStates); + for (i = 0; i < pp_info->info_4.ucNumStates; i++) { + printf("== power mode %d ==\n", i); + power_state = (ATOM_PPLIB_STATE *)(ctx->bios + data_offset + + pp_info->info_4.usStateArrayOffset + + i * pp_info->info_4.ucStateEntrySize); + non_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)(ctx->bios + data_offset + + pp_info->info_4.usNonClockInfoArrayOffset + + power_state->ucNonClockStateIndex * + pp_info->info_4.ucNonClockSize); + printf(" non-clock info\n"); + printf("\ttemp: %d - %d\n", non_clock_info->ucMinTemperature, + non_clock_info->ucMaxTemperature); + printf("\trequired power: %d\n", non_clock_info->ucRequiredPower); + printf("\tflags: \n"); + radeon_print_pp_lib_non_clock_flags(non_clock_info->ulCapsAndSettings); + printf("\tclass info: \n"); + radeon_print_pp_lib_non_clock_class(non_clock_info->usClassification); + + for (j = 0; j < (pp_info->info_4.ucStateEntrySize - 1); j++) { + clock_info = (union clock_info *)(ctx->bios + data_offset + + pp_info->info_4.usClockInfoArrayOffset + + power_state->ucClockStateIndices[j] * + pp_info->info_4.ucClockInfoSize); + + if (1) { + //discrete + printf(" clock info %d\n", j); + sclk = clock_info->r600.usEngineClockLow; + sclk |= clock_info->r600.ucEngineClockHigh << 16; + mclk = clock_info->r600.usMemoryClockLow; + mclk |= clock_info->r600.ucMemoryClockHigh << 16; + printf("\tengine %d, memory %d\n", sclk, mclk); + printf("\tVDDC: %d\n", clock_info->r600.usVDDC); + printf("\tflags: \n"); + radeon_print_pp_lib_clock_flags_discrete(clock_info->r600.ulFlags); + } else { + // igp + sclk = clock_info->rs780.usLowEngineClockLow; + sclk |= clock_info->rs780.ucLowEngineClockHigh << 16; + mclk = clock_info->rs780.usMemoryClockLow; + mclk |= clock_info->rs780.ucMemoryClockHigh << 16; + printf("\tengine %d\n", sclk); + printf("\tsideport memory %d\n", mclk); + printf("\tHT links %d - %d\n", clock_info->rs780.ucMinHTLinkWidth, + clock_info->rs780.ucMaxHTLinkWidth); + if (clock_info->rs780.usHTLinkFreq & ATOM_PPLIB_RS780_HTLINKFREQ_HIGH) + printf("\tHT freq HIGH\n"); + else if (clock_info->rs780.usHTLinkFreq & ATOM_PPLIB_RS780_HTLINKFREQ_LOW) + printf("\tHT freq LOW\n"); + else + printf("\tHT freq NONE\n"); + printf("\tVDDC: %d\n", clock_info->rs780.usVDDC); + printf("\tflags: \n"); + radeon_print_pp_lib_clock_flags_igp(clock_info->rs780.ulFlags); + } + } + } + } +} void dump_vram_table(struct atom_context *ctx) { @@ -657,6 +1081,8 @@ void atom_dump(struct atom_context *ctx) radeon_dump_bios_object_table(ctx); + radeon_dump_bios_pp_table(ctx); + //dump_vram_table(ctx); //radeon_execute_aux_channel_table(ctx); diff --git a/radeontool.c b/radeontool.c index c9a080e..ca2785b 100644 --- a/radeontool.c +++ b/radeontool.c @@ -1397,6 +1397,7 @@ static void radeon_rom_legacy_mobiletable(unsigned char *bios, int hdr) unsigned int powerplay_flags; int powerplay_rev = BIOS8(powerplayoffset); printf("powerplay table revision: %d\n", powerplay_rev); + printf("powerplay table size: %d bytes\n", BIOS8(powerplayoffset) + 1); blocks = BIOS8(powerplayoffset+0x2); printf("powerplay states: %d\n", blocks); for (i = 0; i < blocks; i++) { @@ -1518,7 +1519,7 @@ static void radeon_rom_legacy_mobiletable(unsigned char *bios, int hdr) printf("\t\tvoltage drop register: 0x%x\n", BIOS16(voltage_table_offset) * 4); printf("\t\tvoltage drop register bits: %d\n", - BIOS16(voltage_table_offset + 0x2)); + BIOS8(voltage_table_offset + 0x2)); } } } -- 1.5.4.3