aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r600.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/r600.c')
-rw-r--r--drivers/gpu/drm/radeon/r600.c217
1 files changed, 191 insertions, 26 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index c2d1946535ab..cc2797949ee5 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -92,41 +92,206 @@ void r600_gpu_init(struct radeon_device *rdev);
92void r600_fini(struct radeon_device *rdev); 92void r600_fini(struct radeon_device *rdev);
93void r600_irq_disable(struct radeon_device *rdev); 93void r600_irq_disable(struct radeon_device *rdev);
94 94
95void r600_set_power_state(struct radeon_device *rdev) 95void r600_get_power_state(struct radeon_device *rdev,
96 enum radeon_pm_action action)
96{ 97{
97 /* if *_clock_mode are the same, *_power_state are as well */ 98 int i;
98 if (rdev->pm.requested_clock_mode == rdev->pm.current_clock_mode) 99
99 return; 100 rdev->pm.can_upclock = true;
101 rdev->pm.can_downclock = true;
102
103 /* power state array is low to high, default is first */
104 if ((rdev->flags & RADEON_IS_IGP) || (rdev->family == CHIP_R600)) {
105 int min_power_state_index = 0;
106
107 if (rdev->pm.num_power_states > 2)
108 min_power_state_index = 1;
109
110 switch (action) {
111 case PM_ACTION_MINIMUM:
112 rdev->pm.requested_power_state_index = min_power_state_index;
113 rdev->pm.requested_clock_mode_index = 0;
114 rdev->pm.can_downclock = false;
115 break;
116 case PM_ACTION_DOWNCLOCK:
117 if (rdev->pm.current_power_state_index == min_power_state_index) {
118 rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
119 rdev->pm.can_downclock = false;
120 } else {
121 if (rdev->pm.active_crtc_count > 1) {
122 for (i = 0; i < rdev->pm.num_power_states; i++) {
123 if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
124 continue;
125 else if (i >= rdev->pm.current_power_state_index) {
126 rdev->pm.requested_power_state_index =
127 rdev->pm.current_power_state_index;
128 break;
129 } else {
130 rdev->pm.requested_power_state_index = i;
131 break;
132 }
133 }
134 } else
135 rdev->pm.requested_power_state_index =
136 rdev->pm.current_power_state_index - 1;
137 }
138 rdev->pm.requested_clock_mode_index = 0;
139 break;
140 case PM_ACTION_UPCLOCK:
141 if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) {
142 rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
143 rdev->pm.can_upclock = false;
144 } else {
145 if (rdev->pm.active_crtc_count > 1) {
146 for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) {
147 if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
148 continue;
149 else if (i <= rdev->pm.current_power_state_index) {
150 rdev->pm.requested_power_state_index =
151 rdev->pm.current_power_state_index;
152 break;
153 } else {
154 rdev->pm.requested_power_state_index = i;
155 break;
156 }
157 }
158 } else
159 rdev->pm.requested_power_state_index =
160 rdev->pm.current_power_state_index + 1;
161 }
162 rdev->pm.requested_clock_mode_index = 0;
163 break;
164 case PM_ACTION_NONE:
165 default:
166 DRM_ERROR("Requested mode for not defined action\n");
167 return;
168 }
169 } else {
170 /* XXX select a power state based on AC/DC, single/dualhead, etc. */
171 /* for now just select the first power state and switch between clock modes */
172 /* power state array is low to high, default is first (0) */
173 if (rdev->pm.active_crtc_count > 1) {
174 rdev->pm.requested_power_state_index = -1;
175 /* start at 1 as we don't want the default mode */
176 for (i = 1; i < rdev->pm.num_power_states; i++) {
177 if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
178 continue;
179 else if ((rdev->pm.power_state[i].type == POWER_STATE_TYPE_PERFORMANCE) ||
180 (rdev->pm.power_state[i].type == POWER_STATE_TYPE_BATTERY)) {
181 rdev->pm.requested_power_state_index = i;
182 break;
183 }
184 }
185 /* if nothing selected, grab the default state. */
186 if (rdev->pm.requested_power_state_index == -1)
187 rdev->pm.requested_power_state_index = 0;
188 } else
189 rdev->pm.requested_power_state_index = 1;
190
191 switch (action) {
192 case PM_ACTION_MINIMUM:
193 rdev->pm.requested_clock_mode_index = 0;
194 rdev->pm.can_downclock = false;
195 break;
196 case PM_ACTION_DOWNCLOCK:
197 if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) {
198 if (rdev->pm.current_clock_mode_index == 0) {
199 rdev->pm.requested_clock_mode_index = 0;
200 rdev->pm.can_downclock = false;
201 } else
202 rdev->pm.requested_clock_mode_index =
203 rdev->pm.current_clock_mode_index - 1;
204 } else {
205 rdev->pm.requested_clock_mode_index = 0;
206 rdev->pm.can_downclock = false;
207 }
208 break;
209 case PM_ACTION_UPCLOCK:
210 if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) {
211 if (rdev->pm.current_clock_mode_index ==
212 (rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1)) {
213 rdev->pm.requested_clock_mode_index = rdev->pm.current_clock_mode_index;
214 rdev->pm.can_upclock = false;
215 } else
216 rdev->pm.requested_clock_mode_index =
217 rdev->pm.current_clock_mode_index + 1;
218 } else {
219 rdev->pm.requested_clock_mode_index =
220 rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1;
221 rdev->pm.can_upclock = false;
222 }
223 break;
224 case PM_ACTION_NONE:
225 default:
226 DRM_ERROR("Requested mode for not defined action\n");
227 return;
228 }
229 }
100 230
101 DRM_INFO("Setting: e: %d m: %d p: %d\n", 231 DRM_INFO("Requested: e: %d m: %d p: %d\n",
102 rdev->pm.requested_clock_mode->sclk, 232 rdev->pm.power_state[rdev->pm.requested_power_state_index].
103 rdev->pm.requested_clock_mode->mclk, 233 clock_info[rdev->pm.requested_clock_mode_index].sclk,
104 rdev->pm.requested_power_state->non_clock_info.pcie_lanes); 234 rdev->pm.power_state[rdev->pm.requested_power_state_index].
235 clock_info[rdev->pm.requested_clock_mode_index].mclk,
236 rdev->pm.power_state[rdev->pm.requested_power_state_index].
237 non_clock_info.pcie_lanes);
238}
105 239
106 /* set pcie lanes */ 240void r600_set_power_state(struct radeon_device *rdev)
107 /* TODO */ 241{
242 u32 sclk, mclk;
108 243
109 /* set voltage */ 244 if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
110 /* TODO */ 245 (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index))
246 return;
111 247
112 /* set engine clock */ 248 if (radeon_gui_idle(rdev)) {
113 radeon_sync_with_vblank(rdev); 249
114 radeon_pm_debug_check_in_vbl(rdev, false); 250 sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
115 radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk); 251 clock_info[rdev->pm.requested_clock_mode_index].sclk;
116 radeon_pm_debug_check_in_vbl(rdev, true); 252 if (sclk > rdev->clock.default_sclk)
253 sclk = rdev->clock.default_sclk;
254
255 mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
256 clock_info[rdev->pm.requested_clock_mode_index].mclk;
257 if (mclk > rdev->clock.default_mclk)
258 mclk = rdev->clock.default_mclk;
259 /* don't change the mclk with multiple crtcs */
260 if (rdev->pm.active_crtc_count > 1)
261 mclk = rdev->clock.default_mclk;
262
263 /* set pcie lanes */
264 /* TODO */
265
266 /* set voltage */
267 /* TODO */
268
269 /* set engine clock */
270 if (sclk != rdev->pm.current_sclk) {
271 radeon_sync_with_vblank(rdev);
272 radeon_pm_debug_check_in_vbl(rdev, false);
273 radeon_set_engine_clock(rdev, sclk);
274 radeon_pm_debug_check_in_vbl(rdev, true);
275 rdev->pm.current_sclk = sclk;
276 DRM_INFO("Setting: e: %d\n", sclk);
277 }
117 278
118#if 0 279#if 0
119 /* set memory clock */ 280 /* set memory clock */
120 if (rdev->asic->set_memory_clock) { 281 if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
121 radeon_sync_with_vblank(rdev); 282 radeon_sync_with_vblank(rdev);
122 radeon_pm_debug_check_in_vbl(rdev, false); 283 radeon_pm_debug_check_in_vbl(rdev, false);
123 radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk); 284 radeon_set_memory_clock(rdev, mclk);
124 radeon_pm_debug_check_in_vbl(rdev, true); 285 radeon_pm_debug_check_in_vbl(rdev, true);
125 } 286 rdev->pm.current_mclk = mclk;
287 DRM_INFO("Setting: m: %d\n", mclk);
288 }
126#endif 289#endif
127 290
128 rdev->pm.current_power_state = rdev->pm.requested_power_state; 291 rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
129 rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode; 292 rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;
293 } else
294 DRM_INFO("GUI not idle!!!\n");
130} 295}
131 296
132bool r600_gui_idle(struct radeon_device *rdev) 297bool r600_gui_idle(struct radeon_device *rdev)