diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_pm.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 93ba0fb27e9d..87d2776624bb 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -79,6 +79,128 @@ static void radeon_print_power_mode_info(struct radeon_device *rdev) | |||
79 | } | 79 | } |
80 | } | 80 | } |
81 | 81 | ||
82 | static struct radeon_power_state * radeon_pick_power_state(struct radeon_device *rdev, | ||
83 | enum radeon_pm_state_type type) | ||
84 | { | ||
85 | int i; | ||
86 | struct radeon_power_state *power_state = NULL; | ||
87 | |||
88 | switch (type) { | ||
89 | case POWER_STATE_TYPE_DEFAULT: | ||
90 | default: | ||
91 | return rdev->pm.default_power_state; | ||
92 | case POWER_STATE_TYPE_POWERSAVE: | ||
93 | for (i = 0; i < rdev->pm.num_power_states; i++) { | ||
94 | if (rdev->pm.power_state[i].type == POWER_STATE_TYPE_POWERSAVE) { | ||
95 | power_state = &rdev->pm.power_state[i]; | ||
96 | break; | ||
97 | } | ||
98 | } | ||
99 | if (power_state == NULL) { | ||
100 | for (i = 0; i < rdev->pm.num_power_states; i++) { | ||
101 | if (rdev->pm.power_state[i].type == POWER_STATE_TYPE_BATTERY) { | ||
102 | power_state = &rdev->pm.power_state[i]; | ||
103 | break; | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | break; | ||
108 | case POWER_STATE_TYPE_BATTERY: | ||
109 | for (i = 0; i < rdev->pm.num_power_states; i++) { | ||
110 | if (rdev->pm.power_state[i].type == POWER_STATE_TYPE_BATTERY) { | ||
111 | power_state = &rdev->pm.power_state[i]; | ||
112 | break; | ||
113 | } | ||
114 | } | ||
115 | if (power_state == NULL) { | ||
116 | for (i = 0; i < rdev->pm.num_power_states; i++) { | ||
117 | if (rdev->pm.power_state[i].type == POWER_STATE_TYPE_POWERSAVE) { | ||
118 | power_state = &rdev->pm.power_state[i]; | ||
119 | break; | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | break; | ||
124 | case POWER_STATE_TYPE_BALANCED: | ||
125 | case POWER_STATE_TYPE_PERFORMANCE: | ||
126 | for (i = 0; i < rdev->pm.num_power_states; i++) { | ||
127 | if (rdev->pm.power_state[i].type == type) { | ||
128 | power_state = &rdev->pm.power_state[i]; | ||
129 | break; | ||
130 | } | ||
131 | } | ||
132 | break; | ||
133 | } | ||
134 | |||
135 | if (power_state == NULL) | ||
136 | return rdev->pm.default_power_state; | ||
137 | |||
138 | return power_state; | ||
139 | } | ||
140 | |||
141 | static struct radeon_pm_clock_info * radeon_pick_clock_mode(struct radeon_device *rdev, | ||
142 | struct radeon_power_state *power_state, | ||
143 | enum radeon_pm_clock_mode_type type) | ||
144 | { | ||
145 | switch (type) { | ||
146 | case POWER_MODE_TYPE_DEFAULT: | ||
147 | default: | ||
148 | return power_state->default_clock_mode; | ||
149 | case POWER_MODE_TYPE_LOW: | ||
150 | return &power_state->clock_info[0]; | ||
151 | case POWER_MODE_TYPE_MID: | ||
152 | if (power_state->num_clock_modes > 2) | ||
153 | return &power_state->clock_info[1]; | ||
154 | else | ||
155 | return &power_state->clock_info[0]; | ||
156 | break; | ||
157 | case POWER_MODE_TYPE_HIGH: | ||
158 | return &power_state->clock_info[power_state->num_clock_modes - 1]; | ||
159 | } | ||
160 | |||
161 | } | ||
162 | |||
163 | static void radeon_get_power_state(struct radeon_device *rdev, | ||
164 | enum radeon_pm_action action) | ||
165 | { | ||
166 | switch (action) { | ||
167 | case PM_ACTION_NONE: | ||
168 | default: | ||
169 | rdev->pm.requested_power_state = rdev->pm.current_power_state; | ||
170 | rdev->pm.requested_power_state->requested_clock_mode = | ||
171 | rdev->pm.requested_power_state->current_clock_mode; | ||
172 | break; | ||
173 | case PM_ACTION_MINIMUM: | ||
174 | rdev->pm.requested_power_state = radeon_pick_power_state(rdev, POWER_STATE_TYPE_BATTERY); | ||
175 | rdev->pm.requested_power_state->requested_clock_mode = | ||
176 | radeon_pick_clock_mode(rdev, rdev->pm.requested_power_state, POWER_MODE_TYPE_LOW); | ||
177 | break; | ||
178 | case PM_ACTION_DOWNCLOCK: | ||
179 | rdev->pm.requested_power_state = radeon_pick_power_state(rdev, POWER_STATE_TYPE_POWERSAVE); | ||
180 | rdev->pm.requested_power_state->requested_clock_mode = | ||
181 | radeon_pick_clock_mode(rdev, rdev->pm.requested_power_state, POWER_MODE_TYPE_MID); | ||
182 | break; | ||
183 | case PM_ACTION_UPCLOCK: | ||
184 | rdev->pm.requested_power_state = radeon_pick_power_state(rdev, POWER_STATE_TYPE_DEFAULT); | ||
185 | rdev->pm.requested_power_state->requested_clock_mode = | ||
186 | radeon_pick_clock_mode(rdev, rdev->pm.requested_power_state, POWER_MODE_TYPE_HIGH); | ||
187 | break; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | static void radeon_set_power_state(struct radeon_device *rdev) | ||
192 | { | ||
193 | if (rdev->pm.requested_power_state == rdev->pm.current_power_state) | ||
194 | return; | ||
195 | /* set pcie lanes */ | ||
196 | /* set voltage */ | ||
197 | /* set engine clock */ | ||
198 | radeon_set_engine_clock(rdev, rdev->pm.requested_power_state->requested_clock_mode->sclk); | ||
199 | /* set memory clock */ | ||
200 | |||
201 | rdev->pm.current_power_state = rdev->pm.requested_power_state; | ||
202 | } | ||
203 | |||
82 | int radeon_pm_init(struct radeon_device *rdev) | 204 | int radeon_pm_init(struct radeon_device *rdev) |
83 | { | 205 | { |
84 | rdev->pm.state = PM_STATE_DISABLED; | 206 | rdev->pm.state = PM_STATE_DISABLED; |