Commit 4795b95a authored by Dave Airlie's avatar Dave Airlie

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

r600 dpm fixes, old school card dac fixes, lockup fixes
endian fixes
* 'drm-fixes-3.11' of git://people.freedesktop.org/~agd5f/linux:
  drm/radeon/dpm: fix r600_enable_sclk_control()
  drm/radeon/dpm: implement force performance levels for rv6xx
  drm/radeon/dpm: fix displaygap programming on rv6xx
  drm/radeon/dpm: fix a typo in the rv6xx mclk setup
  drm/radeon: fix combios tables on older cards
  drm/radeon: improve dac adjust heuristics for legacy pdac
  drm/radeon: Another card with wrong primary dac adj
  drm/radeon: fix endian issues with DP handling (v3)
  drm/radeon/vm: only align the pt base to 32k
  drm/radeon: wait for 3D idle before using CP DMA
parents 07bc9dc1 f5d9b7f0
...@@ -44,6 +44,41 @@ static char *pre_emph_names[] = { ...@@ -44,6 +44,41 @@ static char *pre_emph_names[] = {
}; };
/***** radeon AUX functions *****/ /***** radeon AUX functions *****/
/* Atom needs data in little endian format
* so swap as appropriate when copying data to
* or from atom. Note that atom operates on
* dw units.
*/
static void radeon_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le)
{
#ifdef __BIG_ENDIAN
u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */
u32 *dst32, *src32;
int i;
memcpy(src_tmp, src, num_bytes);
src32 = (u32 *)src_tmp;
dst32 = (u32 *)dst_tmp;
if (to_le) {
for (i = 0; i < ((num_bytes + 3) / 4); i++)
dst32[i] = cpu_to_le32(src32[i]);
memcpy(dst, dst_tmp, num_bytes);
} else {
u8 dws = num_bytes & ~3;
for (i = 0; i < ((num_bytes + 3) / 4); i++)
dst32[i] = le32_to_cpu(src32[i]);
memcpy(dst, dst_tmp, dws);
if (num_bytes % 4) {
for (i = 0; i < (num_bytes % 4); i++)
dst[dws+i] = dst_tmp[dws+i];
}
}
#else
memcpy(dst, src, num_bytes);
#endif
}
union aux_channel_transaction { union aux_channel_transaction {
PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1;
PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2;
...@@ -65,10 +100,10 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, ...@@ -65,10 +100,10 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);
memcpy(base, send, send_bytes); radeon_copy_swap(base, send, send_bytes, true);
args.v1.lpAuxRequest = 0 + 4; args.v1.lpAuxRequest = cpu_to_le16((u16)(0 + 4));
args.v1.lpDataOut = 16 + 4; args.v1.lpDataOut = cpu_to_le16((u16)(16 + 4));
args.v1.ucDataOutLen = 0; args.v1.ucDataOutLen = 0;
args.v1.ucChannelID = chan->rec.i2c_id; args.v1.ucChannelID = chan->rec.i2c_id;
args.v1.ucDelay = delay / 10; args.v1.ucDelay = delay / 10;
...@@ -102,7 +137,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, ...@@ -102,7 +137,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
recv_bytes = recv_size; recv_bytes = recv_size;
if (recv && recv_size) if (recv && recv_size)
memcpy(recv, base + 16, recv_bytes); radeon_copy_swap(recv, base + 16, recv_bytes, false);
return recv_bytes; return recv_bytes;
} }
......
...@@ -3166,7 +3166,7 @@ int r600_copy_cpdma(struct radeon_device *rdev, ...@@ -3166,7 +3166,7 @@ int r600_copy_cpdma(struct radeon_device *rdev,
size_in_bytes = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT); size_in_bytes = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT);
num_loops = DIV_ROUND_UP(size_in_bytes, 0x1fffff); num_loops = DIV_ROUND_UP(size_in_bytes, 0x1fffff);
r = radeon_ring_lock(rdev, ring, num_loops * 6 + 21); r = radeon_ring_lock(rdev, ring, num_loops * 6 + 24);
if (r) { if (r) {
DRM_ERROR("radeon: moving bo (%d).\n", r); DRM_ERROR("radeon: moving bo (%d).\n", r);
radeon_semaphore_free(rdev, &sem, NULL); radeon_semaphore_free(rdev, &sem, NULL);
...@@ -3181,6 +3181,9 @@ int r600_copy_cpdma(struct radeon_device *rdev, ...@@ -3181,6 +3181,9 @@ int r600_copy_cpdma(struct radeon_device *rdev,
radeon_semaphore_free(rdev, &sem, NULL); radeon_semaphore_free(rdev, &sem, NULL);
} }
radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
radeon_ring_write(ring, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
radeon_ring_write(ring, WAIT_3D_IDLE_bit);
for (i = 0; i < num_loops; i++) { for (i = 0; i < num_loops; i++) {
cur_size_in_bytes = size_in_bytes; cur_size_in_bytes = size_in_bytes;
if (cur_size_in_bytes > 0x1fffff) if (cur_size_in_bytes > 0x1fffff)
......
...@@ -278,9 +278,9 @@ bool r600_dynamicpm_enabled(struct radeon_device *rdev) ...@@ -278,9 +278,9 @@ bool r600_dynamicpm_enabled(struct radeon_device *rdev)
void r600_enable_sclk_control(struct radeon_device *rdev, bool enable) void r600_enable_sclk_control(struct radeon_device *rdev, bool enable)
{ {
if (enable) if (enable)
WREG32_P(GENERAL_PWRMGT, 0, ~SCLK_PWRMGT_OFF); WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF);
else else
WREG32_P(GENERAL_PWRMGT, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF); WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF);
} }
void r600_enable_mclk_control(struct radeon_device *rdev, bool enable) void r600_enable_mclk_control(struct radeon_device *rdev, bool enable)
......
...@@ -1161,6 +1161,7 @@ static struct radeon_asic rv6xx_asic = { ...@@ -1161,6 +1161,7 @@ static struct radeon_asic rv6xx_asic = {
.get_mclk = &rv6xx_dpm_get_mclk, .get_mclk = &rv6xx_dpm_get_mclk,
.print_power_state = &rv6xx_dpm_print_power_state, .print_power_state = &rv6xx_dpm_print_power_state,
.debugfs_print_current_performance_level = &rv6xx_dpm_debugfs_print_current_performance_level, .debugfs_print_current_performance_level = &rv6xx_dpm_debugfs_print_current_performance_level,
.force_performance_level = &rv6xx_dpm_force_performance_level,
}, },
.pflip = { .pflip = {
.pre_page_flip = &rs600_pre_page_flip, .pre_page_flip = &rs600_pre_page_flip,
......
...@@ -421,6 +421,8 @@ void rv6xx_dpm_print_power_state(struct radeon_device *rdev, ...@@ -421,6 +421,8 @@ void rv6xx_dpm_print_power_state(struct radeon_device *rdev,
struct radeon_ps *ps); struct radeon_ps *ps);
void rv6xx_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, void rv6xx_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
struct seq_file *m); struct seq_file *m);
int rv6xx_dpm_force_performance_level(struct radeon_device *rdev,
enum radeon_dpm_forced_level level);
/* rs780 dpm */ /* rs780 dpm */
int rs780_dpm_init(struct radeon_device *rdev); int rs780_dpm_init(struct radeon_device *rdev);
int rs780_dpm_enable(struct radeon_device *rdev); int rs780_dpm_enable(struct radeon_device *rdev);
......
...@@ -147,7 +147,7 @@ static uint16_t combios_get_table_offset(struct drm_device *dev, ...@@ -147,7 +147,7 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
enum radeon_combios_table_offset table) enum radeon_combios_table_offset table)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
int rev; int rev, size;
uint16_t offset = 0, check_offset; uint16_t offset = 0, check_offset;
if (!rdev->bios) if (!rdev->bios)
...@@ -156,174 +156,106 @@ static uint16_t combios_get_table_offset(struct drm_device *dev, ...@@ -156,174 +156,106 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
switch (table) { switch (table) {
/* absolute offset tables */ /* absolute offset tables */
case COMBIOS_ASIC_INIT_1_TABLE: case COMBIOS_ASIC_INIT_1_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0xc); check_offset = 0xc;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_BIOS_SUPPORT_TABLE: case COMBIOS_BIOS_SUPPORT_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x14); check_offset = 0x14;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_DAC_PROGRAMMING_TABLE: case COMBIOS_DAC_PROGRAMMING_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x2a); check_offset = 0x2a;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_MAX_COLOR_DEPTH_TABLE: case COMBIOS_MAX_COLOR_DEPTH_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x2c); check_offset = 0x2c;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_CRTC_INFO_TABLE: case COMBIOS_CRTC_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x2e); check_offset = 0x2e;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_PLL_INFO_TABLE: case COMBIOS_PLL_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x30); check_offset = 0x30;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_TV_INFO_TABLE: case COMBIOS_TV_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x32); check_offset = 0x32;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_DFP_INFO_TABLE: case COMBIOS_DFP_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x34); check_offset = 0x34;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_HW_CONFIG_INFO_TABLE: case COMBIOS_HW_CONFIG_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x36); check_offset = 0x36;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_MULTIMEDIA_INFO_TABLE: case COMBIOS_MULTIMEDIA_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x38); check_offset = 0x38;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_TV_STD_PATCH_TABLE: case COMBIOS_TV_STD_PATCH_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x3e); check_offset = 0x3e;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_LCD_INFO_TABLE: case COMBIOS_LCD_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x40); check_offset = 0x40;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_MOBILE_INFO_TABLE: case COMBIOS_MOBILE_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x42); check_offset = 0x42;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_PLL_INIT_TABLE: case COMBIOS_PLL_INIT_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x46); check_offset = 0x46;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_MEM_CONFIG_TABLE: case COMBIOS_MEM_CONFIG_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x48); check_offset = 0x48;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_SAVE_MASK_TABLE: case COMBIOS_SAVE_MASK_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x4a); check_offset = 0x4a;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_HARDCODED_EDID_TABLE: case COMBIOS_HARDCODED_EDID_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x4c); check_offset = 0x4c;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_ASIC_INIT_2_TABLE: case COMBIOS_ASIC_INIT_2_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x4e); check_offset = 0x4e;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_CONNECTOR_INFO_TABLE: case COMBIOS_CONNECTOR_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x50); check_offset = 0x50;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_DYN_CLK_1_TABLE: case COMBIOS_DYN_CLK_1_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x52); check_offset = 0x52;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_RESERVED_MEM_TABLE: case COMBIOS_RESERVED_MEM_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x54); check_offset = 0x54;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_EXT_TMDS_INFO_TABLE: case COMBIOS_EXT_TMDS_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x58); check_offset = 0x58;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_MEM_CLK_INFO_TABLE: case COMBIOS_MEM_CLK_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x5a); check_offset = 0x5a;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_EXT_DAC_INFO_TABLE: case COMBIOS_EXT_DAC_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x5c); check_offset = 0x5c;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_MISC_INFO_TABLE: case COMBIOS_MISC_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x5e); check_offset = 0x5e;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_CRT_INFO_TABLE: case COMBIOS_CRT_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x60); check_offset = 0x60;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE: case COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x62); check_offset = 0x62;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_COMPONENT_VIDEO_INFO_TABLE: case COMBIOS_COMPONENT_VIDEO_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x64); check_offset = 0x64;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_FAN_SPEED_INFO_TABLE: case COMBIOS_FAN_SPEED_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x66); check_offset = 0x66;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_OVERDRIVE_INFO_TABLE: case COMBIOS_OVERDRIVE_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x68); check_offset = 0x68;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_OEM_INFO_TABLE: case COMBIOS_OEM_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x6a); check_offset = 0x6a;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_DYN_CLK_2_TABLE: case COMBIOS_DYN_CLK_2_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x6c); check_offset = 0x6c;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_POWER_CONNECTOR_INFO_TABLE: case COMBIOS_POWER_CONNECTOR_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x6e); check_offset = 0x6e;
if (check_offset)
offset = check_offset;
break; break;
case COMBIOS_I2C_INFO_TABLE: case COMBIOS_I2C_INFO_TABLE:
check_offset = RBIOS16(rdev->bios_header_start + 0x70); check_offset = 0x70;
if (check_offset)
offset = check_offset;
break; break;
/* relative offset tables */ /* relative offset tables */
case COMBIOS_ASIC_INIT_3_TABLE: /* offset from misc info */ case COMBIOS_ASIC_INIT_3_TABLE: /* offset from misc info */
...@@ -439,11 +371,16 @@ static uint16_t combios_get_table_offset(struct drm_device *dev, ...@@ -439,11 +371,16 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
} }
break; break;
default: default:
check_offset = 0;
break; break;
} }
return offset; size = RBIOS8(rdev->bios_header_start + 0x6);
/* check absolute offset tables */
if (table < COMBIOS_ASIC_INIT_3_TABLE && check_offset && check_offset < size)
offset = RBIOS16(rdev->bios_header_start + check_offset);
return offset;
} }
bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev) bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
...@@ -965,16 +902,22 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct ...@@ -965,16 +902,22 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
dac = RBIOS8(dac_info + 0x3) & 0xf; dac = RBIOS8(dac_info + 0x3) & 0xf;
p_dac->ps2_pdac_adj = (bg << 8) | (dac); p_dac->ps2_pdac_adj = (bg << 8) | (dac);
} }
/* if the values are all zeros, use the table */ /* if the values are zeros, use the table */
if (p_dac->ps2_pdac_adj) if ((dac == 0) || (bg == 0))
found = 0;
else
found = 1; found = 1;
} }
/* quirks */ /* quirks */
/* Radeon 7000 (RV100) */
if (((dev->pdev->device == 0x5159) &&
(dev->pdev->subsystem_vendor == 0x174B) &&
(dev->pdev->subsystem_device == 0x7c28)) ||
/* Radeon 9100 (R200) */ /* Radeon 9100 (R200) */
if ((dev->pdev->device == 0x514D) && ((dev->pdev->device == 0x514D) &&
(dev->pdev->subsystem_vendor == 0x174B) && (dev->pdev->subsystem_vendor == 0x174B) &&
(dev->pdev->subsystem_device == 0x7149)) { (dev->pdev->subsystem_device == 0x7149))) {
/* vbios value is bad, use the default */ /* vbios value is bad, use the default */
found = 0; found = 0;
} }
......
...@@ -466,7 +466,7 @@ int radeon_vm_manager_init(struct radeon_device *rdev) ...@@ -466,7 +466,7 @@ int radeon_vm_manager_init(struct radeon_device *rdev)
size += rdev->vm_manager.max_pfn * 8; size += rdev->vm_manager.max_pfn * 8;
size *= 2; size *= 2;
r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager,
RADEON_VM_PTB_ALIGN(size), RADEON_GPU_PAGE_ALIGN(size),
RADEON_VM_PTB_ALIGN_SIZE, RADEON_VM_PTB_ALIGN_SIZE,
RADEON_GEM_DOMAIN_VRAM); RADEON_GEM_DOMAIN_VRAM);
if (r) { if (r) {
...@@ -621,7 +621,7 @@ int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm) ...@@ -621,7 +621,7 @@ int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm)
} }
retry: retry:
pd_size = RADEON_VM_PTB_ALIGN(radeon_vm_directory_size(rdev)); pd_size = radeon_vm_directory_size(rdev);
r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager,
&vm->page_directory, pd_size, &vm->page_directory, pd_size,
RADEON_VM_PTB_ALIGN_SIZE, false); RADEON_VM_PTB_ALIGN_SIZE, false);
...@@ -953,8 +953,8 @@ static int radeon_vm_update_pdes(struct radeon_device *rdev, ...@@ -953,8 +953,8 @@ static int radeon_vm_update_pdes(struct radeon_device *rdev,
retry: retry:
r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager,
&vm->page_tables[pt_idx], &vm->page_tables[pt_idx],
RADEON_VM_PTB_ALIGN(RADEON_VM_PTE_COUNT * 8), RADEON_VM_PTE_COUNT * 8,
RADEON_VM_PTB_ALIGN_SIZE, false); RADEON_GPU_PAGE_SIZE, false);
if (r == -ENOMEM) { if (r == -ENOMEM) {
r = radeon_vm_evict(rdev, vm); r = radeon_vm_evict(rdev, vm);
......
...@@ -819,7 +819,7 @@ static void rv6xx_program_memory_timing_parameters(struct radeon_device *rdev) ...@@ -819,7 +819,7 @@ static void rv6xx_program_memory_timing_parameters(struct radeon_device *rdev)
POWERMODE1(calculate_memory_refresh_rate(rdev, POWERMODE1(calculate_memory_refresh_rate(rdev,
pi->hw.sclks[R600_POWER_LEVEL_MEDIUM])) | pi->hw.sclks[R600_POWER_LEVEL_MEDIUM])) |
POWERMODE2(calculate_memory_refresh_rate(rdev, POWERMODE2(calculate_memory_refresh_rate(rdev,
pi->hw.sclks[R600_POWER_LEVEL_MEDIUM])) | pi->hw.sclks[R600_POWER_LEVEL_HIGH])) |
POWERMODE3(calculate_memory_refresh_rate(rdev, POWERMODE3(calculate_memory_refresh_rate(rdev,
pi->hw.sclks[R600_POWER_LEVEL_HIGH]))); pi->hw.sclks[R600_POWER_LEVEL_HIGH])));
WREG32(ARB_RFSH_RATE, arb_refresh_rate); WREG32(ARB_RFSH_RATE, arb_refresh_rate);
...@@ -1182,10 +1182,10 @@ static void rv6xx_program_display_gap(struct radeon_device *rdev) ...@@ -1182,10 +1182,10 @@ static void rv6xx_program_display_gap(struct radeon_device *rdev)
u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL); u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL);
tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK); tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK);
if (RREG32(AVIVO_D1CRTC_CONTROL) & AVIVO_CRTC_EN) { if (rdev->pm.dpm.new_active_crtcs & 1) {
tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK); tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK);
tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE); tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE);
} else if (RREG32(AVIVO_D2CRTC_CONTROL) & AVIVO_CRTC_EN) { } else if (rdev->pm.dpm.new_active_crtcs & 2) {
tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE); tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE);
tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK); tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK);
} else { } else {
...@@ -1670,6 +1670,8 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev) ...@@ -1670,6 +1670,8 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
struct radeon_ps *old_ps = rdev->pm.dpm.current_ps; struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
int ret; int ret;
pi->restricted_levels = 0;
rv6xx_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps); rv6xx_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
rv6xx_clear_vc(rdev); rv6xx_clear_vc(rdev);
...@@ -1756,6 +1758,8 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev) ...@@ -1756,6 +1758,8 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
rv6xx_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); rv6xx_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO;
return 0; return 0;
} }
...@@ -2085,3 +2089,34 @@ u32 rv6xx_dpm_get_mclk(struct radeon_device *rdev, bool low) ...@@ -2085,3 +2089,34 @@ u32 rv6xx_dpm_get_mclk(struct radeon_device *rdev, bool low)
else else
return requested_state->high.mclk; return requested_state->high.mclk;
} }
int rv6xx_dpm_force_performance_level(struct radeon_device *rdev,
enum radeon_dpm_forced_level level)
{
struct rv6xx_power_info *pi = rv6xx_get_pi(rdev);
if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
pi->restricted_levels = 3;
} else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
pi->restricted_levels = 2;
} else {
pi->restricted_levels = 0;
}
rv6xx_clear_vc(rdev);
r600_power_level_enable(rdev, R600_POWER_LEVEL_LOW, true);
r600_set_at(rdev, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF);
r600_wait_for_power_level(rdev, R600_POWER_LEVEL_LOW);
r600_power_level_enable(rdev, R600_POWER_LEVEL_HIGH, false);
r600_power_level_enable(rdev, R600_POWER_LEVEL_MEDIUM, false);
rv6xx_enable_medium(rdev);
rv6xx_enable_high(rdev);
if (pi->restricted_levels == 3)
r600_power_level_enable(rdev, R600_POWER_LEVEL_LOW, false);
rv6xx_program_vc(rdev);
rv6xx_program_at(rdev);
rdev->pm.dpm.forced_level = level;
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment