diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_pm.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 46 | 
1 files changed, 37 insertions, 9 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index d4d1c39a0e9..a4b57493aa7 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -28,6 +28,7 @@  #define RADEON_RECLOCK_DELAY_MS 200  #define RADEON_WAIT_VBLANK_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); @@ -179,6 +180,16 @@ 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) +{ +	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)); +	} +} +  static void radeon_set_power_state(struct radeon_device *rdev)  {  	/* if *_clock_mode are the same, *_power_state are as well */ @@ -189,11 +200,28 @@ static void radeon_set_power_state(struct radeon_device *rdev)  		 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; @@ -229,6 +257,12 @@ int radeon_pm_init(struct radeon_device *rdev)  	return 0;  } +void radeon_pm_fini(struct radeon_device *rdev) +{ +	if (rdev->pm.i2c_bus) +		radeon_i2c_destroy(rdev->pm.i2c_bus); +} +  void radeon_pm_compute_clocks(struct radeon_device *rdev)  {  	struct drm_device *ddev = rdev->ddev; @@ -245,7 +279,8 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)  	list_for_each_entry(connector,  		&ddev->mode_config.connector_list, head) {  		if (connector->encoder && -			connector->dpms != DRM_MODE_DPMS_OFF) { +		    connector->encoder->crtc && +		    connector->dpms != DRM_MODE_DPMS_OFF) {  			radeon_crtc = to_radeon_crtc(connector->encoder->crtc);  			rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);  			++count; @@ -333,10 +368,7 @@ static void radeon_pm_set_clocks_locked(struct radeon_device *rdev)  		break;  	} -	/* check if we are in vblank */ -	radeon_pm_debug_check_in_vbl(rdev, false);  	radeon_set_power_state(rdev); -	radeon_pm_debug_check_in_vbl(rdev, true);  	rdev->pm.planned_action = PM_ACTION_NONE;  } @@ -353,10 +385,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)  		rdev->pm.req_vblank |= (1 << 1);  		drm_vblank_get(rdev->ddev, 1);  	} -	if (rdev->pm.active_crtcs) -		wait_event_interruptible_timeout( -			rdev->irq.vblank_queue, 0, -			msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT)); +	radeon_pm_set_clocks_locked(rdev);  	if (rdev->pm.req_vblank & (1 << 0)) {  		rdev->pm.req_vblank &= ~(1 << 0);  		drm_vblank_put(rdev->ddev, 0); @@ -366,7 +395,6 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)  		drm_vblank_put(rdev->ddev, 1);  	} -	radeon_pm_set_clocks_locked(rdev);  	mutex_unlock(&rdev->cp.mutex);  }  |