24,8 → 24,8 |
#include "radeon.h" |
#include "avivod.h" |
#include "atom.h" |
#include "r600_dpm.h" |
|
|
#define RADEON_IDLE_LOOP_MS 100 |
#define RADEON_RECLOCK_DELAY_MS 200 |
#define RADEON_WAIT_VBLANK_TIMEOUT 200 |
155,9 → 155,9 |
{ |
if (rdev->pm.active_crtcs) { |
rdev->pm.vblank_sync = false; |
// wait_event_timeout( |
// rdev->irq.vblank_queue, rdev->pm.vblank_sync, |
// msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT)); |
wait_event_timeout( |
rdev->irq.vblank_queue, rdev->pm.vblank_sync, |
msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT)); |
} |
} |
|
250,7 → 250,6 |
(rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index)) |
return; |
|
mutex_lock(&rdev->ddev->struct_mutex); |
down_write(&rdev->pm.mclk_lock); |
mutex_lock(&rdev->ring_lock); |
|
265,7 → 264,6 |
/* needs a GPU reset dont reset here */ |
mutex_unlock(&rdev->ring_lock); |
up_write(&rdev->pm.mclk_lock); |
mutex_unlock(&rdev->ddev->struct_mutex); |
return; |
} |
} |
276,7 → 274,7 |
for (i = 0; i < rdev->num_crtc; i++) { |
if (rdev->pm.active_crtcs & (1 << i)) { |
rdev->pm.req_vblank |= (1 << i); |
// drm_vblank_get(rdev->ddev, i); |
drm_vblank_get(rdev->ddev, i); |
} |
} |
} |
287,7 → 285,7 |
for (i = 0; i < rdev->num_crtc; i++) { |
if (rdev->pm.req_vblank & (1 << i)) { |
rdev->pm.req_vblank &= ~(1 << i); |
// drm_vblank_put(rdev->ddev, i); |
drm_vblank_put(rdev->ddev, i); |
} |
} |
} |
301,7 → 299,6 |
|
mutex_unlock(&rdev->ring_lock); |
up_write(&rdev->pm.mclk_lock); |
mutex_unlock(&rdev->ddev->struct_mutex); |
} |
|
static void radeon_pm_print_states(struct radeon_device *rdev) |
663,12 → 660,8 |
radeon_pm_compute_clocks(rdev); |
} |
|
static struct radeon_ps *radeon_dpm_pick_power_state(struct radeon_device *rdev, |
enum radeon_pm_state_type dpm_state) |
static bool radeon_dpm_single_display(struct radeon_device *rdev) |
{ |
int i; |
struct radeon_ps *ps; |
u32 ui_class; |
bool single_display = (rdev->pm.dpm.new_active_crtc_count < 2) ? |
true : false; |
|
678,6 → 671,23 |
single_display = false; |
} |
|
/* 120hz tends to be problematic even if they are under the |
* vblank limit. |
*/ |
if (single_display && (r600_dpm_get_vrefresh(rdev) >= 120)) |
single_display = false; |
|
return single_display; |
} |
|
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; |
bool single_display = radeon_dpm_single_display(rdev); |
|
/* certain older asics have a separare 3D performance state, |
* so try that first if the user selected performance |
*/ |
803,6 → 813,7 |
struct radeon_ps *ps; |
enum radeon_pm_state_type dpm_state; |
int ret; |
bool single_display = radeon_dpm_single_display(rdev); |
|
/* if dpm init failed */ |
if (!rdev->pm.dpm_enabled) |
827,6 → 838,9 |
/* vce just modifies an existing state so force a change */ |
if (ps->vce_active != rdev->pm.dpm.vce_active) |
goto force; |
/* user has made a display change (such as timing) */ |
if (rdev->pm.dpm.single_display != single_display) |
goto force; |
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. |
871,7 → 885,6 |
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); |
|
889,6 → 902,7 |
|
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; |
rdev->pm.dpm.single_display = single_display; |
|
/* wait for the rings to drain */ |
for (i = 0; i < RADEON_NUM_RINGS; i++) { |
921,7 → 935,6 |
done: |
mutex_unlock(&rdev->ring_lock); |
up_write(&rdev->pm.mclk_lock); |
mutex_unlock(&rdev->ddev->struct_mutex); |
} |
|
void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable) |
1218,8 → 1231,39 |
return ret; |
} |
|
struct radeon_dpm_quirk { |
u32 chip_vendor; |
u32 chip_device; |
u32 subsys_vendor; |
u32 subsys_device; |
}; |
|
/* cards with dpm stability problems */ |
static struct radeon_dpm_quirk radeon_dpm_quirk_list[] = { |
/* TURKS - https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1386534 */ |
{ PCI_VENDOR_ID_ATI, 0x6759, 0x1682, 0x3195 }, |
/* TURKS - https://bugzilla.kernel.org/show_bug.cgi?id=83731 */ |
{ PCI_VENDOR_ID_ATI, 0x6840, 0x1179, 0xfb81 }, |
{ 0, 0, 0, 0 }, |
}; |
|
int radeon_pm_init(struct radeon_device *rdev) |
{ |
struct radeon_dpm_quirk *p = radeon_dpm_quirk_list; |
bool disable_dpm = false; |
|
/* Apply dpm quirks */ |
while (p && p->chip_device != 0) { |
if (rdev->pdev->vendor == p->chip_vendor && |
rdev->pdev->device == p->chip_device && |
rdev->pdev->subsystem_vendor == p->subsys_vendor && |
rdev->pdev->subsystem_device == p->subsys_device) { |
disable_dpm = true; |
break; |
} |
++p; |
} |
|
/* enable dpm on rv6xx+ */ |
switch (rdev->family) { |
case CHIP_RV610: |
1275,6 → 1319,8 |
(!(rdev->flags & RADEON_IS_IGP)) && |
(!rdev->smc_fw)) |
rdev->pm.pm_method = PM_METHOD_PROFILE; |
else if (disable_dpm && (radeon_dpm == -1)) |
rdev->pm.pm_method = PM_METHOD_PROFILE; |
else if (radeon_dpm == 0) |
rdev->pm.pm_method = PM_METHOD_PROFILE; |
else |
1477,7 → 1523,11 |
*/ |
for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { |
if (rdev->pm.active_crtcs & (1 << crtc)) { |
vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, 0, &vpos, &hpos, NULL, NULL); |
vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, |
crtc, |
USE_REAL_VBLANKSTART, |
&vpos, &hpos, NULL, NULL, |
&rdev->mode_info.crtcs[crtc]->base.hwmode); |
if ((vbl_status & DRM_SCANOUTPOS_VALID) && |
!(vbl_status & DRM_SCANOUTPOS_IN_VBLANK)) |
in_vbl = false; |