From bae6b5627387a950a8faf366d6027bd0a7a93078 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 22 Apr 2010 13:38:05 -0400 Subject: [PATCH] drm/radeon/kms/pm: add asic specific callbacks for setting power state (v2) (v2) Add evergreen vbl checks Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/evergreen_reg.h | 1 + drivers/gpu/drm/radeon/r100.c | 37 ++++++++++++ drivers/gpu/drm/radeon/r600.c | 37 ++++++++++++ drivers/gpu/drm/radeon/radeon.h | 4 ++ drivers/gpu/drm/radeon/radeon_asic.c | 14 +++++ drivers/gpu/drm/radeon/radeon_asic.h | 3 + drivers/gpu/drm/radeon/radeon_pm.c | 100 +++++++++++++++++---------------- drivers/gpu/drm/radeon/radeon_reg.h | 1 - 8 files changed, 148 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h index f7c7c96..9dba6d9 100644 --- a/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/drivers/gpu/drm/radeon/evergreen_reg.h @@ -166,6 +166,7 @@ /* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */ #define EVERGREEN_CRTC_CONTROL 0x6e70 # define EVERGREEN_CRTC_MASTER_EN (1 << 0) +#define EVERGREEN_CRTC_STATUS 0x6e8c #define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4 #define EVERGREEN_DC_GPIO_HPD_MASK 0x64b0 diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index d352986..b076b96f 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -67,6 +67,43 @@ MODULE_FIRMWARE(FIRMWARE_R520); * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ +void r100_set_power_state(struct radeon_device *rdev) +{ + /* if *_clock_mode are the same, *_power_state are as well */ + if (rdev->pm.requested_clock_mode == rdev->pm.current_clock_mode) + return; + + DRM_INFO("Setting: e: %d m: %d p: %d\n", + rdev->pm.requested_clock_mode->sclk, + rdev->pm.requested_clock_mode->mclk, + rdev->pm.requested_power_state->non_clock_info.pcie_lanes); + + /* set pcie lanes */ + /* TODO */ + + /* set voltage */ + /* TODO */ + + /* set engine clock */ + radeon_sync_with_vblank(rdev); + radeon_pm_debug_check_in_vbl(rdev, false); + radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk); + radeon_pm_debug_check_in_vbl(rdev, true); + +#if 0 + /* set memory clock */ + if (rdev->asic->set_memory_clock) { + radeon_sync_with_vblank(rdev); + radeon_pm_debug_check_in_vbl(rdev, false); + radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk); + radeon_pm_debug_check_in_vbl(rdev, true); + } +#endif + + rdev->pm.current_power_state = rdev->pm.requested_power_state; + rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode; +} + bool r100_gui_idle(struct radeon_device *rdev) { if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 094c29d..c2d1946 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -92,6 +92,43 @@ void r600_gpu_init(struct radeon_device *rdev); void r600_fini(struct radeon_device *rdev); void r600_irq_disable(struct radeon_device *rdev); +void r600_set_power_state(struct radeon_device *rdev) +{ + /* if *_clock_mode are the same, *_power_state are as well */ + if (rdev->pm.requested_clock_mode == rdev->pm.current_clock_mode) + return; + + DRM_INFO("Setting: e: %d m: %d p: %d\n", + rdev->pm.requested_clock_mode->sclk, + rdev->pm.requested_clock_mode->mclk, + rdev->pm.requested_power_state->non_clock_info.pcie_lanes); + + /* set pcie lanes */ + /* TODO */ + + /* set voltage */ + /* TODO */ + + /* set engine clock */ + radeon_sync_with_vblank(rdev); + radeon_pm_debug_check_in_vbl(rdev, false); + radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk); + radeon_pm_debug_check_in_vbl(rdev, true); + +#if 0 + /* set memory clock */ + if (rdev->asic->set_memory_clock) { + radeon_sync_with_vblank(rdev); + radeon_pm_debug_check_in_vbl(rdev, false); + radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk); + radeon_pm_debug_check_in_vbl(rdev, true); + } +#endif + + rdev->pm.current_power_state = rdev->pm.requested_power_state; + rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode; +} + bool r600_gui_idle(struct radeon_device *rdev) { if (RREG32(GRBM_STATUS) & GUI_ACTIVE) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 4339371..11fe1d1 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -175,6 +175,8 @@ void radeon_pm_fini(struct radeon_device *rdev); void radeon_pm_compute_clocks(struct radeon_device *rdev); void radeon_combios_get_power_modes(struct radeon_device *rdev); void radeon_atombios_get_power_modes(struct radeon_device *rdev); +bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish); +void radeon_sync_with_vblank(struct radeon_device *rdev); /* * Fences. @@ -808,6 +810,7 @@ struct radeon_asic { */ void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo); bool (*gui_idle)(struct radeon_device *rdev); + void (*set_power_state)(struct radeon_device *rdev); }; /* @@ -1215,6 +1218,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) #define radeon_hpd_sense(rdev, hpd) (rdev)->asic->hpd_sense((rdev), (hpd)) #define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd)) #define radeon_gui_idle(rdev) (rdev)->asic->gui_idle((rdev)) +#define radeon_set_power_state(rdev) (rdev)->asic->set_power_state((rdev)) /* Common functions */ /* AGP */ diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 4270846..48893fb 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -166,6 +166,7 @@ static struct radeon_asic r100_asic = { .hpd_set_polarity = &r100_hpd_set_polarity, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, + .set_power_state = &r100_set_power_state, }; static struct radeon_asic r200_asic = { @@ -205,6 +206,7 @@ static struct radeon_asic r200_asic = { .hpd_set_polarity = &r100_hpd_set_polarity, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, + .set_power_state = &r100_set_power_state, }; static struct radeon_asic r300_asic = { @@ -245,6 +247,7 @@ static struct radeon_asic r300_asic = { .hpd_set_polarity = &r100_hpd_set_polarity, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, + .set_power_state = &r100_set_power_state, }; static struct radeon_asic r300_asic_pcie = { @@ -284,6 +287,7 @@ static struct radeon_asic r300_asic_pcie = { .hpd_set_polarity = &r100_hpd_set_polarity, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, + .set_power_state = &r100_set_power_state, }; static struct radeon_asic r420_asic = { @@ -324,6 +328,7 @@ static struct radeon_asic r420_asic = { .hpd_set_polarity = &r100_hpd_set_polarity, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, + .set_power_state = &r100_set_power_state, }; static struct radeon_asic rs400_asic = { @@ -364,6 +369,7 @@ static struct radeon_asic rs400_asic = { .hpd_set_polarity = &r100_hpd_set_polarity, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, + .set_power_state = &r100_set_power_state, }; static struct radeon_asic rs600_asic = { @@ -404,6 +410,7 @@ static struct radeon_asic rs600_asic = { .hpd_set_polarity = &rs600_hpd_set_polarity, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, + .set_power_state = &r100_set_power_state, }; static struct radeon_asic rs690_asic = { @@ -444,6 +451,7 @@ static struct radeon_asic rs690_asic = { .hpd_set_polarity = &rs600_hpd_set_polarity, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, + .set_power_state = &r100_set_power_state, }; static struct radeon_asic rv515_asic = { @@ -484,6 +492,7 @@ static struct radeon_asic rv515_asic = { .hpd_set_polarity = &rs600_hpd_set_polarity, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, + .set_power_state = &r100_set_power_state, }; static struct radeon_asic r520_asic = { @@ -524,6 +533,7 @@ static struct radeon_asic r520_asic = { .hpd_set_polarity = &rs600_hpd_set_polarity, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, + .set_power_state = &r100_set_power_state, }; static struct radeon_asic r600_asic = { @@ -563,6 +573,7 @@ static struct radeon_asic r600_asic = { .hpd_set_polarity = &r600_hpd_set_polarity, .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, + .set_power_state = &r600_set_power_state, }; static struct radeon_asic rs780_asic = { @@ -602,6 +613,7 @@ static struct radeon_asic rs780_asic = { .hpd_set_polarity = &r600_hpd_set_polarity, .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, + .set_power_state = &r600_set_power_state, }; static struct radeon_asic rv770_asic = { @@ -641,6 +653,7 @@ static struct radeon_asic rv770_asic = { .hpd_set_polarity = &r600_hpd_set_polarity, .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, + .set_power_state = &r600_set_power_state, }; static struct radeon_asic evergreen_asic = { @@ -678,6 +691,7 @@ static struct radeon_asic evergreen_asic = { .hpd_sense = &evergreen_hpd_sense, .hpd_set_polarity = &evergreen_hpd_set_polarity, .gui_idle = &r600_gui_idle, + .set_power_state = &r600_set_power_state, }; int radeon_asic_init(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index c74bf9b..90d8e6d 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -127,6 +127,8 @@ void r100_enable_bm(struct radeon_device *rdev); void r100_set_common_regs(struct radeon_device *rdev); void r100_bm_disable(struct radeon_device *rdev); extern bool r100_gui_idle(struct radeon_device *rdev); +extern void r100_set_power_state(struct radeon_device *rdev); + /* * r200,rv250,rs300,rv280 */ @@ -271,6 +273,7 @@ void r600_hpd_set_polarity(struct radeon_device *rdev, enum radeon_hpd_id hpd); extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo); extern bool r600_gui_idle(struct radeon_device *rdev); +extern void r600_set_power_state(struct radeon_device *rdev); /* * rv770,rv730,rv710,rv740 diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index ff3abd8..129956d 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -29,7 +29,6 @@ #define RADEON_WAIT_VBLANK_TIMEOUT 200 #define RADEON_WAIT_IDLE_TIMEOUT 200 -static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish); static void radeon_pm_set_clocks_locked(struct radeon_device *rdev); static void radeon_pm_set_clocks(struct radeon_device *rdev); static void radeon_pm_idle_work_handler(struct work_struct *work); @@ -181,7 +180,7 @@ static void radeon_get_power_state(struct radeon_device *rdev, rdev->pm.requested_power_state->non_clock_info.pcie_lanes); } -static inline void radeon_sync_with_vblank(struct radeon_device *rdev) +void radeon_sync_with_vblank(struct radeon_device *rdev) { if (rdev->pm.active_crtcs) { rdev->pm.vblank_sync = false; @@ -191,43 +190,6 @@ static inline void radeon_sync_with_vblank(struct radeon_device *rdev) } } -static void radeon_set_power_state(struct radeon_device *rdev) -{ - /* if *_clock_mode are the same, *_power_state are as well */ - if (rdev->pm.requested_clock_mode == rdev->pm.current_clock_mode) - return; - - DRM_INFO("Setting: e: %d m: %d p: %d\n", - rdev->pm.requested_clock_mode->sclk, - rdev->pm.requested_clock_mode->mclk, - rdev->pm.requested_power_state->non_clock_info.pcie_lanes); - - /* set pcie lanes */ - /* TODO */ - - /* set voltage */ - /* TODO */ - - /* set engine clock */ - radeon_sync_with_vblank(rdev); - radeon_pm_debug_check_in_vbl(rdev, false); - radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk); - radeon_pm_debug_check_in_vbl(rdev, true); - -#if 0 - /* set memory clock */ - if (rdev->asic->set_memory_clock) { - radeon_sync_with_vblank(rdev); - radeon_pm_debug_check_in_vbl(rdev, false); - radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk); - radeon_pm_debug_check_in_vbl(rdev, true); - } -#endif - - rdev->pm.current_power_state = rdev->pm.requested_power_state; - rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode; -} - int radeon_pm_init(struct radeon_device *rdev) { rdev->pm.state = PM_STATE_DISABLED; @@ -330,26 +292,68 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) mutex_unlock(&rdev->pm.mutex); } -static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish) +bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish) { - u32 stat_crtc1 = 0, stat_crtc2 = 0; + u32 stat_crtc = 0; bool in_vbl = true; - if (ASIC_IS_AVIVO(rdev)) { + if (ASIC_IS_DCE4(rdev)) { + if (rdev->pm.active_crtcs & (1 << 0)) { + stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET); + if (!(stat_crtc & 1)) + in_vbl = false; + } + if (rdev->pm.active_crtcs & (1 << 1)) { + stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET); + if (!(stat_crtc & 1)) + in_vbl = false; + } + if (rdev->pm.active_crtcs & (1 << 2)) { + stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); + if (!(stat_crtc & 1)) + in_vbl = false; + } + if (rdev->pm.active_crtcs & (1 << 3)) { + stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); + if (!(stat_crtc & 1)) + in_vbl = false; + } + if (rdev->pm.active_crtcs & (1 << 4)) { + stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); + if (!(stat_crtc & 1)) + in_vbl = false; + } + if (rdev->pm.active_crtcs & (1 << 5)) { + stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); + if (!(stat_crtc & 1)) + in_vbl = false; + } + } else if (ASIC_IS_AVIVO(rdev)) { + if (rdev->pm.active_crtcs & (1 << 0)) { + stat_crtc = RREG32(D1CRTC_STATUS); + if (!(stat_crtc & 1)) + in_vbl = false; + } + if (rdev->pm.active_crtcs & (1 << 1)) { + stat_crtc = RREG32(D2CRTC_STATUS); + if (!(stat_crtc & 1)) + in_vbl = false; + } + } else { if (rdev->pm.active_crtcs & (1 << 0)) { - stat_crtc1 = RREG32(D1CRTC_STATUS); - if (!(stat_crtc1 & 1)) + stat_crtc = RREG32(RADEON_CRTC_STATUS); + if (!(stat_crtc & 1)) in_vbl = false; } if (rdev->pm.active_crtcs & (1 << 1)) { - stat_crtc2 = RREG32(D2CRTC_STATUS); - if (!(stat_crtc2 & 1)) + stat_crtc = RREG32(RADEON_CRTC2_STATUS); + if (!(stat_crtc & 1)) in_vbl = false; } } if (in_vbl == false) - DRM_INFO("not in vbl for pm change %08x %08x at %s\n", stat_crtc1, - stat_crtc2, finish ? "exit" : "entry"); + DRM_INFO("not in vbl for pm change %08x at %s\n", stat_crtc, + finish ? "exit" : "entry"); return in_vbl; } static void radeon_pm_set_clocks_locked(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h index 74d1cbf..c332f46 100644 --- a/drivers/gpu/drm/radeon/radeon_reg.h +++ b/drivers/gpu/drm/radeon/radeon_reg.h @@ -553,7 +553,6 @@ # define RADEON_CRTC_CRNT_VLINE_MASK (0x7ff << 16) #define RADEON_CRTC2_CRNT_FRAME 0x0314 #define RADEON_CRTC2_GUI_TRIG_VLINE 0x0318 -#define RADEON_CRTC2_STATUS 0x03fc #define RADEON_CRTC2_VLINE_CRNT_VLINE 0x0310 #define RADEON_CRTC8_DATA 0x03d5 /* VGA, 0x3b5 */ #define RADEON_CRTC8_IDX 0x03d4 /* VGA, 0x3b4 */ -- 2.7.4