aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r100.c
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2010-04-22 14:03:55 -0400
committerDave Airlie <airlied@redhat.com>2010-05-18 04:20:58 -0400
commita48b9b4edb8bb87deb13b9f088a595cf71457b69 (patch)
tree2cfe4156f911042a6c3943ee98503d452941dd92 /drivers/gpu/drm/radeon/r100.c
parentbae6b5627387a950a8faf366d6027bd0a7a93078 (diff)
drm/radeon/kms/pm: add asic specific callbacks for getting power state (v2)
This also simplifies the code and enables reclocking with multiple heads active by tracking whether the power states are single or multi-head capable. Eventually, we will want to select a power state based on external factors (AC/DC state, user selection, etc.). (v2) Update for evergreen Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
-rw-r--r--drivers/gpu/drm/radeon/r100.c140
1 files changed, 116 insertions, 24 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index b076b96f8b6c..a6b2aca36b47 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -67,41 +67,133 @@ MODULE_FIRMWARE(FIRMWARE_R520);
67 * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 67 * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
68 */ 68 */
69 69
70void r100_get_power_state(struct radeon_device *rdev,
71 enum radeon_pm_action action)
72{
73 int i;
74 rdev->pm.can_upclock = true;
75 rdev->pm.can_downclock = true;
76
77 switch (action) {
78 case PM_ACTION_MINIMUM:
79 rdev->pm.requested_power_state_index = 0;
80 rdev->pm.can_downclock = false;
81 break;
82 case PM_ACTION_DOWNCLOCK:
83 if (rdev->pm.current_power_state_index == 0) {
84 rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
85 rdev->pm.can_downclock = false;
86 } else {
87 if (rdev->pm.active_crtc_count > 1) {
88 for (i = 0; i < rdev->pm.num_power_states; i++) {
89 if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
90 continue;
91 else if (i >= rdev->pm.current_power_state_index) {
92 rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
93 break;
94 } else {
95 rdev->pm.requested_power_state_index = i;
96 break;
97 }
98 }
99 } else
100 rdev->pm.requested_power_state_index =
101 rdev->pm.current_power_state_index - 1;
102 }
103 break;
104 case PM_ACTION_UPCLOCK:
105 if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) {
106 rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
107 rdev->pm.can_upclock = false;
108 } else {
109 if (rdev->pm.active_crtc_count > 1) {
110 for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) {
111 if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
112 continue;
113 else if (i <= rdev->pm.current_power_state_index) {
114 rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
115 break;
116 } else {
117 rdev->pm.requested_power_state_index = i;
118 break;
119 }
120 }
121 } else
122 rdev->pm.requested_power_state_index =
123 rdev->pm.current_power_state_index + 1;
124 }
125 break;
126 case PM_ACTION_NONE:
127 default:
128 DRM_ERROR("Requested mode for not defined action\n");
129 return;
130 }
131 /* only one clock mode per power state */
132 rdev->pm.requested_clock_mode_index = 0;
133
134 DRM_INFO("Requested: e: %d m: %d p: %d\n",
135 rdev->pm.power_state[rdev->pm.requested_power_state_index].
136 clock_info[rdev->pm.requested_clock_mode_index].sclk,
137 rdev->pm.power_state[rdev->pm.requested_power_state_index].
138 clock_info[rdev->pm.requested_clock_mode_index].mclk,
139 rdev->pm.power_state[rdev->pm.requested_power_state_index].
140 non_clock_info.pcie_lanes);
141}
142
70void r100_set_power_state(struct radeon_device *rdev) 143void r100_set_power_state(struct radeon_device *rdev)
71{ 144{
72 /* if *_clock_mode are the same, *_power_state are as well */ 145 u32 sclk, mclk;
73 if (rdev->pm.requested_clock_mode == rdev->pm.current_clock_mode) 146
147 if (rdev->pm.current_power_state_index == rdev->pm.requested_power_state_index)
74 return; 148 return;
75 149
76 DRM_INFO("Setting: e: %d m: %d p: %d\n", 150 if (radeon_gui_idle(rdev)) {
77 rdev->pm.requested_clock_mode->sclk,
78 rdev->pm.requested_clock_mode->mclk,
79 rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
80 151
81 /* set pcie lanes */ 152 sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
82 /* TODO */ 153 clock_info[rdev->pm.requested_clock_mode_index].sclk;
154 if (sclk > rdev->clock.default_sclk)
155 sclk = rdev->clock.default_sclk;
83 156
84 /* set voltage */ 157 mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
85 /* TODO */ 158 clock_info[rdev->pm.requested_clock_mode_index].mclk;
159 if (mclk > rdev->clock.default_mclk)
160 mclk = rdev->clock.default_mclk;
161 /* don't change the mclk with multiple crtcs */
162 if (rdev->pm.active_crtc_count > 1)
163 mclk = rdev->clock.default_mclk;
86 164
87 /* set engine clock */ 165 /* set pcie lanes */
88 radeon_sync_with_vblank(rdev); 166 /* TODO */
89 radeon_pm_debug_check_in_vbl(rdev, false); 167
90 radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk); 168 /* set voltage */
91 radeon_pm_debug_check_in_vbl(rdev, true); 169 /* TODO */
170
171 /* set engine clock */
172 if (sclk != rdev->pm.current_sclk) {
173 radeon_sync_with_vblank(rdev);
174 radeon_pm_debug_check_in_vbl(rdev, false);
175 radeon_set_engine_clock(rdev, sclk);
176 radeon_pm_debug_check_in_vbl(rdev, true);
177 rdev->pm.current_sclk = sclk;
178 DRM_INFO("Setting: e: %d\n", sclk);
179 }
92 180
93#if 0 181#if 0
94 /* set memory clock */ 182 /* set memory clock */
95 if (rdev->asic->set_memory_clock) { 183 if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
96 radeon_sync_with_vblank(rdev); 184 radeon_sync_with_vblank(rdev);
97 radeon_pm_debug_check_in_vbl(rdev, false); 185 radeon_pm_debug_check_in_vbl(rdev, false);
98 radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk); 186 radeon_set_memory_clock(rdev, mclk);
99 radeon_pm_debug_check_in_vbl(rdev, true); 187 radeon_pm_debug_check_in_vbl(rdev, true);
100 } 188 rdev->pm.current_mclk = mclk;
189 DRM_INFO("Setting: m: %d\n", mclk);
190 }
101#endif 191#endif
102 192
103 rdev->pm.current_power_state = rdev->pm.requested_power_state; 193 rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
104 rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode; 194 rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;
195 } else
196 DRM_INFO("GUI not idle!!!\n");
105} 197}
106 198
107bool r100_gui_idle(struct radeon_device *rdev) 199bool r100_gui_idle(struct radeon_device *rdev)