aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2009-12-23 14:28:05 -0500
committerDave Airlie <airlied@redhat.com>2010-02-08 18:32:29 -0500
commit516d0e46c80d2d20391f4145c2c5e3915253b8bf (patch)
treecb0ada4d61e4c78bcdc3ce9a97a6b7ad6d79b8f1 /drivers/gpu/drm/radeon
parent0ec0e74f784ca08eab0354ab1dada46924c39b73 (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.h9
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c122
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
604enum 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
604struct radeon_voltage { 611struct 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
82static 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
141static 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
163static 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
191static 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
82int radeon_pm_init(struct radeon_device *rdev) 204int radeon_pm_init(struct radeon_device *rdev)
83{ 205{
84 rdev->pm.state = PM_STATE_DISABLED; 206 rdev->pm.state = PM_STATE_DISABLED;