diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-12-23 14:28:05 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-02-08 18:32:29 -0500 |
commit | 516d0e46c80d2d20391f4145c2c5e3915253b8bf (patch) | |
tree | cb0ada4d61e4c78bcdc3ce9a97a6b7ad6d79b8f1 /drivers/gpu/drm/radeon | |
parent | 0ec0e74f784ca08eab0354ab1dada46924c39b73 (diff) |
drm/radeon/kms: add code to select power state
not hooked up yet.
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 122 |
2 files changed, 131 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 53468680de70..ece84fde76a6 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -601,6 +601,13 @@ enum radeon_pm_state_type { | |||
601 | POWER_STATE_TYPE_PERFORMANCE, | 601 | POWER_STATE_TYPE_PERFORMANCE, |
602 | }; | 602 | }; |
603 | 603 | ||
604 | enum radeon_pm_clock_mode_type { | ||
605 | POWER_MODE_TYPE_DEFAULT, | ||
606 | POWER_MODE_TYPE_LOW, | ||
607 | POWER_MODE_TYPE_MID, | ||
608 | POWER_MODE_TYPE_HIGH, | ||
609 | }; | ||
610 | |||
604 | struct radeon_voltage { | 611 | struct radeon_voltage { |
605 | enum radeon_voltage_type type; | 612 | enum radeon_voltage_type type; |
606 | /* gpio voltage */ | 613 | /* gpio voltage */ |
@@ -641,6 +648,7 @@ struct radeon_power_state { | |||
641 | int num_clock_modes; | 648 | int num_clock_modes; |
642 | /* currently selected clock mode */ | 649 | /* currently selected clock mode */ |
643 | struct radeon_pm_clock_info *current_clock_mode; | 650 | struct radeon_pm_clock_info *current_clock_mode; |
651 | struct radeon_pm_clock_info *requested_clock_mode; | ||
644 | struct radeon_pm_clock_info *default_clock_mode; | 652 | struct radeon_pm_clock_info *default_clock_mode; |
645 | /* non clock info about this state */ | 653 | /* non clock info about this state */ |
646 | struct radeon_pm_non_clock_info non_clock_info; | 654 | struct radeon_pm_non_clock_info non_clock_info; |
@@ -678,6 +686,7 @@ struct radeon_pm { | |||
678 | /* number of valid power states */ | 686 | /* number of valid power states */ |
679 | int num_power_states; | 687 | int num_power_states; |
680 | struct radeon_power_state *current_power_state; | 688 | struct radeon_power_state *current_power_state; |
689 | struct radeon_power_state *requested_power_state; | ||
681 | struct radeon_power_state *default_power_state; | 690 | struct radeon_power_state *default_power_state; |
682 | }; | 691 | }; |
683 | 692 | ||
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; |