radeon_hd: Polaris10 power distribution fix

* Helps prevent mainboard explosions and other bad stuff.
* ...maybe not explosions, but bad things.
* The RX 480 reference design can pull as much as 90W
  from its PCIe slot at load. PCIe is rated for 75W.
* This change overloads the PCIe power cables vs the PCIe
  slot. The PCIe power cables can handle going over spec.
* Untested since we really can't come close to loading a
  RX 480 without hardware OpenGL ^_^
* Should be able to test on real hardware within a week.
This commit is contained in:
Alexander von Gluck IV
2016-09-28 15:46:14 -05:00
parent 6c12ba4014
commit 38f17b01ce
5 changed files with 56 additions and 2 deletions
@@ -190,7 +190,8 @@ struct overlay_registers;
struct radeon_shared_info {
uint32 deviceIndex; // accelerant index
uint32 pciID; // device pciid
uint32 pciID; // device pci id
uint32 pciRev; // device pci revision
area_id mode_list_area; // area containing display mode list
uint32 mode_count;
@@ -258,6 +258,9 @@ radeon_init_accelerant(int device)
// probe firmware information
radeon_gpu_probe();
// apply GPU quirks
radeon_gpu_quirks();
// find GPIO pins from AtomBIOS
gpio_populate();
+43
View File
@@ -223,6 +223,49 @@ radeon_gpu_reset()
}
status_t
radeon_gpu_quirks()
{
radeon_shared_info &info = *gInfo->shared_info;
// Fix PCIe power distribution issue for Polaris10 XT
// aka "Card draws >75W from PCIe bus"
if (info.chipsetID == RADEON_POLARIS && info.pciRev == 0xc7) {
ERROR("%s: Applying Polaris10 power distribution fix.\n",
__func__);
radeon_gpu_i2c_cmd(0x10, 0x96, 0x1e, 0xdd);
radeon_gpu_i2c_cmd(0x10, 0x96, 0x1f, 0xd0);
}
return B_OK;
}
status_t
radeon_gpu_i2c_cmd(uint16 slaveAddr, uint16 lineNumber, uint8 offset,
uint8 data)
{
TRACE("%s\n", __func__);
PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args;
memset(&args, 0, sizeof(args));
int index = GetIndexIntoMasterTable(COMMAND,
ProcessI2cChannelTransaction);
args.ucRegIndex = offset;
args.lpI2CDataOut = data;
args.ucFlag = HW_I2C_WRITE;
args.ucI2CSpeed = TARGET_HW_I2C_CLOCK;
args.ucTransBytes = 1;
args.ucSlaveAddr = slaveAddr;
args.ucLineNumber = lineNumber;
atom_execute_table(gAtomContext, index, (uint32*)&args);
return B_OK;
}
void
radeon_gpu_mc_halt(gpu_state* gpuState)
{
+7 -1
View File
@@ -165,9 +165,16 @@
#define SOFT_RESET_VGT (1 << 14)
#define SOFT_RESET_IA (1 << 15)
#define TARGET_HW_I2C_CLOCK 50
status_t radeon_gpu_probe();
status_t radeon_gpu_reset();
status_t radeon_gpu_quirks();
status_t radeon_gpu_i2c_cmd(uint16 slaveAddr, uint16 lineNumber, uint8 offset,
uint8 data);
void radeon_gpu_mc_halt(struct gpu_state *gpuState);
void radeon_gpu_mc_resume(struct gpu_state *gpuState);
status_t radeon_gpu_mc_idlewait();
@@ -177,5 +184,4 @@ status_t radeon_gpu_ring_boot(uint32 ringType);
status_t radeon_gpu_ss_control(pll_info* pll, bool enable);
#endif
@@ -650,6 +650,7 @@ radeon_hd_init(radeon_info &info)
// Pass common information to accelerant
info.shared_info->deviceIndex = info.id;
info.shared_info->pciID = info.pciID;
info.shared_info->pciRev = info.pci->revision;
info.shared_info->chipsetID = info.chipsetID;
info.shared_info->chipsetFlags = info.chipsetFlags;
info.shared_info->dceMajor = info.dceMajor;