Skip to content

Commit bae6b56

Browse files
agd5fairlied
authored andcommitted
drm/radeon/kms/pm: add asic specific callbacks for setting power state (v2)
(v2) Add evergreen vbl checks Signed-off-by: Alex Deucher <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
1 parent 03214bd commit bae6b56

File tree

8 files changed

+148
-49
lines changed

8 files changed

+148
-49
lines changed

drivers/gpu/drm/radeon/evergreen_reg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@
166166
/* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */
167167
#define EVERGREEN_CRTC_CONTROL 0x6e70
168168
# define EVERGREEN_CRTC_MASTER_EN (1 << 0)
169+
#define EVERGREEN_CRTC_STATUS 0x6e8c
169170
#define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4
170171

171172
#define EVERGREEN_DC_GPIO_HPD_MASK 0x64b0

drivers/gpu/drm/radeon/r100.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,43 @@ MODULE_FIRMWARE(FIRMWARE_R520);
6767
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
6868
*/
6969

70+
void r100_set_power_state(struct radeon_device *rdev)
71+
{
72+
/* if *_clock_mode are the same, *_power_state are as well */
73+
if (rdev->pm.requested_clock_mode == rdev->pm.current_clock_mode)
74+
return;
75+
76+
DRM_INFO("Setting: e: %d m: %d p: %d\n",
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+
81+
/* set pcie lanes */
82+
/* TODO */
83+
84+
/* set voltage */
85+
/* TODO */
86+
87+
/* set engine clock */
88+
radeon_sync_with_vblank(rdev);
89+
radeon_pm_debug_check_in_vbl(rdev, false);
90+
radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk);
91+
radeon_pm_debug_check_in_vbl(rdev, true);
92+
93+
#if 0
94+
/* set memory clock */
95+
if (rdev->asic->set_memory_clock) {
96+
radeon_sync_with_vblank(rdev);
97+
radeon_pm_debug_check_in_vbl(rdev, false);
98+
radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk);
99+
radeon_pm_debug_check_in_vbl(rdev, true);
100+
}
101+
#endif
102+
103+
rdev->pm.current_power_state = rdev->pm.requested_power_state;
104+
rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode;
105+
}
106+
70107
bool r100_gui_idle(struct radeon_device *rdev)
71108
{
72109
if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)

drivers/gpu/drm/radeon/r600.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,43 @@ void r600_gpu_init(struct radeon_device *rdev);
9292
void r600_fini(struct radeon_device *rdev);
9393
void r600_irq_disable(struct radeon_device *rdev);
9494

95+
void r600_set_power_state(struct radeon_device *rdev)
96+
{
97+
/* if *_clock_mode are the same, *_power_state are as well */
98+
if (rdev->pm.requested_clock_mode == rdev->pm.current_clock_mode)
99+
return;
100+
101+
DRM_INFO("Setting: e: %d m: %d p: %d\n",
102+
rdev->pm.requested_clock_mode->sclk,
103+
rdev->pm.requested_clock_mode->mclk,
104+
rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
105+
106+
/* set pcie lanes */
107+
/* TODO */
108+
109+
/* set voltage */
110+
/* TODO */
111+
112+
/* set engine clock */
113+
radeon_sync_with_vblank(rdev);
114+
radeon_pm_debug_check_in_vbl(rdev, false);
115+
radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk);
116+
radeon_pm_debug_check_in_vbl(rdev, true);
117+
118+
#if 0
119+
/* set memory clock */
120+
if (rdev->asic->set_memory_clock) {
121+
radeon_sync_with_vblank(rdev);
122+
radeon_pm_debug_check_in_vbl(rdev, false);
123+
radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk);
124+
radeon_pm_debug_check_in_vbl(rdev, true);
125+
}
126+
#endif
127+
128+
rdev->pm.current_power_state = rdev->pm.requested_power_state;
129+
rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode;
130+
}
131+
95132
bool r600_gui_idle(struct radeon_device *rdev)
96133
{
97134
if (RREG32(GRBM_STATUS) & GUI_ACTIVE)

drivers/gpu/drm/radeon/radeon.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ void radeon_pm_fini(struct radeon_device *rdev);
175175
void radeon_pm_compute_clocks(struct radeon_device *rdev);
176176
void radeon_combios_get_power_modes(struct radeon_device *rdev);
177177
void radeon_atombios_get_power_modes(struct radeon_device *rdev);
178+
bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish);
179+
void radeon_sync_with_vblank(struct radeon_device *rdev);
178180

179181
/*
180182
* Fences.
@@ -808,6 +810,7 @@ struct radeon_asic {
808810
*/
809811
void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo);
810812
bool (*gui_idle)(struct radeon_device *rdev);
813+
void (*set_power_state)(struct radeon_device *rdev);
811814
};
812815

813816
/*
@@ -1215,6 +1218,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
12151218
#define radeon_hpd_sense(rdev, hpd) (rdev)->asic->hpd_sense((rdev), (hpd))
12161219
#define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd))
12171220
#define radeon_gui_idle(rdev) (rdev)->asic->gui_idle((rdev))
1221+
#define radeon_set_power_state(rdev) (rdev)->asic->set_power_state((rdev))
12181222

12191223
/* Common functions */
12201224
/* AGP */

drivers/gpu/drm/radeon/radeon_asic.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ static struct radeon_asic r100_asic = {
166166
.hpd_set_polarity = &r100_hpd_set_polarity,
167167
.ioctl_wait_idle = NULL,
168168
.gui_idle = &r100_gui_idle,
169+
.set_power_state = &r100_set_power_state,
169170
};
170171

171172
static struct radeon_asic r200_asic = {
@@ -205,6 +206,7 @@ static struct radeon_asic r200_asic = {
205206
.hpd_set_polarity = &r100_hpd_set_polarity,
206207
.ioctl_wait_idle = NULL,
207208
.gui_idle = &r100_gui_idle,
209+
.set_power_state = &r100_set_power_state,
208210
};
209211

210212
static struct radeon_asic r300_asic = {
@@ -245,6 +247,7 @@ static struct radeon_asic r300_asic = {
245247
.hpd_set_polarity = &r100_hpd_set_polarity,
246248
.ioctl_wait_idle = NULL,
247249
.gui_idle = &r100_gui_idle,
250+
.set_power_state = &r100_set_power_state,
248251
};
249252

250253
static struct radeon_asic r300_asic_pcie = {
@@ -284,6 +287,7 @@ static struct radeon_asic r300_asic_pcie = {
284287
.hpd_set_polarity = &r100_hpd_set_polarity,
285288
.ioctl_wait_idle = NULL,
286289
.gui_idle = &r100_gui_idle,
290+
.set_power_state = &r100_set_power_state,
287291
};
288292

289293
static struct radeon_asic r420_asic = {
@@ -324,6 +328,7 @@ static struct radeon_asic r420_asic = {
324328
.hpd_set_polarity = &r100_hpd_set_polarity,
325329
.ioctl_wait_idle = NULL,
326330
.gui_idle = &r100_gui_idle,
331+
.set_power_state = &r100_set_power_state,
327332
};
328333

329334
static struct radeon_asic rs400_asic = {
@@ -364,6 +369,7 @@ static struct radeon_asic rs400_asic = {
364369
.hpd_set_polarity = &r100_hpd_set_polarity,
365370
.ioctl_wait_idle = NULL,
366371
.gui_idle = &r100_gui_idle,
372+
.set_power_state = &r100_set_power_state,
367373
};
368374

369375
static struct radeon_asic rs600_asic = {
@@ -404,6 +410,7 @@ static struct radeon_asic rs600_asic = {
404410
.hpd_set_polarity = &rs600_hpd_set_polarity,
405411
.ioctl_wait_idle = NULL,
406412
.gui_idle = &r100_gui_idle,
413+
.set_power_state = &r100_set_power_state,
407414
};
408415

409416
static struct radeon_asic rs690_asic = {
@@ -444,6 +451,7 @@ static struct radeon_asic rs690_asic = {
444451
.hpd_set_polarity = &rs600_hpd_set_polarity,
445452
.ioctl_wait_idle = NULL,
446453
.gui_idle = &r100_gui_idle,
454+
.set_power_state = &r100_set_power_state,
447455
};
448456

449457
static struct radeon_asic rv515_asic = {
@@ -484,6 +492,7 @@ static struct radeon_asic rv515_asic = {
484492
.hpd_set_polarity = &rs600_hpd_set_polarity,
485493
.ioctl_wait_idle = NULL,
486494
.gui_idle = &r100_gui_idle,
495+
.set_power_state = &r100_set_power_state,
487496
};
488497

489498
static struct radeon_asic r520_asic = {
@@ -524,6 +533,7 @@ static struct radeon_asic r520_asic = {
524533
.hpd_set_polarity = &rs600_hpd_set_polarity,
525534
.ioctl_wait_idle = NULL,
526535
.gui_idle = &r100_gui_idle,
536+
.set_power_state = &r100_set_power_state,
527537
};
528538

529539
static struct radeon_asic r600_asic = {
@@ -563,6 +573,7 @@ static struct radeon_asic r600_asic = {
563573
.hpd_set_polarity = &r600_hpd_set_polarity,
564574
.ioctl_wait_idle = r600_ioctl_wait_idle,
565575
.gui_idle = &r600_gui_idle,
576+
.set_power_state = &r600_set_power_state,
566577
};
567578

568579
static struct radeon_asic rs780_asic = {
@@ -602,6 +613,7 @@ static struct radeon_asic rs780_asic = {
602613
.hpd_set_polarity = &r600_hpd_set_polarity,
603614
.ioctl_wait_idle = r600_ioctl_wait_idle,
604615
.gui_idle = &r600_gui_idle,
616+
.set_power_state = &r600_set_power_state,
605617
};
606618

607619
static struct radeon_asic rv770_asic = {
@@ -641,6 +653,7 @@ static struct radeon_asic rv770_asic = {
641653
.hpd_set_polarity = &r600_hpd_set_polarity,
642654
.ioctl_wait_idle = r600_ioctl_wait_idle,
643655
.gui_idle = &r600_gui_idle,
656+
.set_power_state = &r600_set_power_state,
644657
};
645658

646659
static struct radeon_asic evergreen_asic = {
@@ -678,6 +691,7 @@ static struct radeon_asic evergreen_asic = {
678691
.hpd_sense = &evergreen_hpd_sense,
679692
.hpd_set_polarity = &evergreen_hpd_set_polarity,
680693
.gui_idle = &r600_gui_idle,
694+
.set_power_state = &r600_set_power_state,
681695
};
682696

683697
int radeon_asic_init(struct radeon_device *rdev)

drivers/gpu/drm/radeon/radeon_asic.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ void r100_enable_bm(struct radeon_device *rdev);
127127
void r100_set_common_regs(struct radeon_device *rdev);
128128
void r100_bm_disable(struct radeon_device *rdev);
129129
extern bool r100_gui_idle(struct radeon_device *rdev);
130+
extern void r100_set_power_state(struct radeon_device *rdev);
131+
130132
/*
131133
* r200,rv250,rs300,rv280
132134
*/
@@ -271,6 +273,7 @@ void r600_hpd_set_polarity(struct radeon_device *rdev,
271273
enum radeon_hpd_id hpd);
272274
extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo);
273275
extern bool r600_gui_idle(struct radeon_device *rdev);
276+
extern void r600_set_power_state(struct radeon_device *rdev);
274277

275278
/*
276279
* rv770,rv730,rv710,rv740

drivers/gpu/drm/radeon/radeon_pm.c

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#define RADEON_WAIT_VBLANK_TIMEOUT 200
3030
#define RADEON_WAIT_IDLE_TIMEOUT 200
3131

32-
static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish);
3332
static void radeon_pm_set_clocks_locked(struct radeon_device *rdev);
3433
static void radeon_pm_set_clocks(struct radeon_device *rdev);
3534
static void radeon_pm_idle_work_handler(struct work_struct *work);
@@ -181,7 +180,7 @@ static void radeon_get_power_state(struct radeon_device *rdev,
181180
rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
182181
}
183182

184-
static inline void radeon_sync_with_vblank(struct radeon_device *rdev)
183+
void radeon_sync_with_vblank(struct radeon_device *rdev)
185184
{
186185
if (rdev->pm.active_crtcs) {
187186
rdev->pm.vblank_sync = false;
@@ -191,43 +190,6 @@ static inline void radeon_sync_with_vblank(struct radeon_device *rdev)
191190
}
192191
}
193192

194-
static void radeon_set_power_state(struct radeon_device *rdev)
195-
{
196-
/* if *_clock_mode are the same, *_power_state are as well */
197-
if (rdev->pm.requested_clock_mode == rdev->pm.current_clock_mode)
198-
return;
199-
200-
DRM_INFO("Setting: e: %d m: %d p: %d\n",
201-
rdev->pm.requested_clock_mode->sclk,
202-
rdev->pm.requested_clock_mode->mclk,
203-
rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
204-
205-
/* set pcie lanes */
206-
/* TODO */
207-
208-
/* set voltage */
209-
/* TODO */
210-
211-
/* set engine clock */
212-
radeon_sync_with_vblank(rdev);
213-
radeon_pm_debug_check_in_vbl(rdev, false);
214-
radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk);
215-
radeon_pm_debug_check_in_vbl(rdev, true);
216-
217-
#if 0
218-
/* set memory clock */
219-
if (rdev->asic->set_memory_clock) {
220-
radeon_sync_with_vblank(rdev);
221-
radeon_pm_debug_check_in_vbl(rdev, false);
222-
radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk);
223-
radeon_pm_debug_check_in_vbl(rdev, true);
224-
}
225-
#endif
226-
227-
rdev->pm.current_power_state = rdev->pm.requested_power_state;
228-
rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode;
229-
}
230-
231193
int radeon_pm_init(struct radeon_device *rdev)
232194
{
233195
rdev->pm.state = PM_STATE_DISABLED;
@@ -330,26 +292,68 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
330292
mutex_unlock(&rdev->pm.mutex);
331293
}
332294

333-
static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish)
295+
bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish)
334296
{
335-
u32 stat_crtc1 = 0, stat_crtc2 = 0;
297+
u32 stat_crtc = 0;
336298
bool in_vbl = true;
337299

338-
if (ASIC_IS_AVIVO(rdev)) {
300+
if (ASIC_IS_DCE4(rdev)) {
301+
if (rdev->pm.active_crtcs & (1 << 0)) {
302+
stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET);
303+
if (!(stat_crtc & 1))
304+
in_vbl = false;
305+
}
306+
if (rdev->pm.active_crtcs & (1 << 1)) {
307+
stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET);
308+
if (!(stat_crtc & 1))
309+
in_vbl = false;
310+
}
311+
if (rdev->pm.active_crtcs & (1 << 2)) {
312+
stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET);
313+
if (!(stat_crtc & 1))
314+
in_vbl = false;
315+
}
316+
if (rdev->pm.active_crtcs & (1 << 3)) {
317+
stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET);
318+
if (!(stat_crtc & 1))
319+
in_vbl = false;
320+
}
321+
if (rdev->pm.active_crtcs & (1 << 4)) {
322+
stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
323+
if (!(stat_crtc & 1))
324+
in_vbl = false;
325+
}
326+
if (rdev->pm.active_crtcs & (1 << 5)) {
327+
stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
328+
if (!(stat_crtc & 1))
329+
in_vbl = false;
330+
}
331+
} else if (ASIC_IS_AVIVO(rdev)) {
332+
if (rdev->pm.active_crtcs & (1 << 0)) {
333+
stat_crtc = RREG32(D1CRTC_STATUS);
334+
if (!(stat_crtc & 1))
335+
in_vbl = false;
336+
}
337+
if (rdev->pm.active_crtcs & (1 << 1)) {
338+
stat_crtc = RREG32(D2CRTC_STATUS);
339+
if (!(stat_crtc & 1))
340+
in_vbl = false;
341+
}
342+
} else {
339343
if (rdev->pm.active_crtcs & (1 << 0)) {
340-
stat_crtc1 = RREG32(D1CRTC_STATUS);
341-
if (!(stat_crtc1 & 1))
344+
stat_crtc = RREG32(RADEON_CRTC_STATUS);
345+
if (!(stat_crtc & 1))
342346
in_vbl = false;
343347
}
344348
if (rdev->pm.active_crtcs & (1 << 1)) {
345-
stat_crtc2 = RREG32(D2CRTC_STATUS);
346-
if (!(stat_crtc2 & 1))
349+
stat_crtc = RREG32(RADEON_CRTC2_STATUS);
350+
if (!(stat_crtc & 1))
347351
in_vbl = false;
348352
}
349353
}
350354
if (in_vbl == false)
351-
DRM_INFO("not in vbl for pm change %08x %08x at %s\n", stat_crtc1,
352-
stat_crtc2, finish ? "exit" : "entry");
355+
DRM_INFO("not in vbl for pm change %08x at %s\n", stat_crtc,
356+
finish ? "exit" : "entry");
353357
return in_vbl;
354358
}
355359
static void radeon_pm_set_clocks_locked(struct radeon_device *rdev)

drivers/gpu/drm/radeon/radeon_reg.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,6 @@
553553
# define RADEON_CRTC_CRNT_VLINE_MASK (0x7ff << 16)
554554
#define RADEON_CRTC2_CRNT_FRAME 0x0314
555555
#define RADEON_CRTC2_GUI_TRIG_VLINE 0x0318
556-
#define RADEON_CRTC2_STATUS 0x03fc
557556
#define RADEON_CRTC2_VLINE_CRNT_VLINE 0x0310
558557
#define RADEON_CRTC8_DATA 0x03d5 /* VGA, 0x3b5 */
559558
#define RADEON_CRTC8_IDX 0x03d4 /* VGA, 0x3b4 */

0 commit comments

Comments
 (0)