aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_combios.c
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2009-12-28 13:58:44 -0500
committerDave Airlie <airlied@redhat.com>2010-02-08 18:32:27 -0500
commit56278a8edacee9ae9e3bc9d8c8e2d37e9969f3eb (patch)
tree2aea5e4707e5caffb30abacc78230bd6f7295c32 /drivers/gpu/drm/radeon/radeon_combios.c
parentc836a4126768cd76af9ee33b3c11f57695d5fda6 (diff)
drm/radeon/kms: pull power mode info from bios tables (v3)
The general idea is to validate the current hw state against the set of power states and select a power state based on that. This patch just pulls the power states from the bios and prints the information. It is not currently hooked up in the actual power management code. Hooking it up will require reworking the the current power state selection code and will be handled in a future patch. Additionally, we'd need to decide on some default lower power states for cards without power tables. v2 - increment state_index after checking for default state v3 - fix typo in pm init on pre-atom cards, handle pre-atom cards without x86 bioses Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_combios.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 257ce1774e40..eac2174abc5b 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -2374,6 +2374,114 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
2374 return true; 2374 return true;
2375} 2375}
2376 2376
2377void radeon_combios_get_power_modes(struct radeon_device *rdev)
2378{
2379 struct drm_device *dev = rdev->ddev;
2380 u16 offset, misc, misc2 = 0;
2381 u8 rev, blocks, tmp;
2382 int state_index = 0;
2383
2384 rdev->pm.default_power_state = NULL;
2385 rdev->pm.current_power_state = NULL;
2386
2387 /* XXX mac/sparc cards */
2388 if (rdev->bios == NULL)
2389 goto default_mode;
2390
2391 if (rdev->flags & RADEON_IS_MOBILITY) {
2392 offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE);
2393 if (offset) {
2394 rev = RBIOS8(offset);
2395 blocks = RBIOS8(offset + 0x2);
2396 /* power mode 0 tends to be the only valid one */
2397 rdev->pm.power_state[state_index].num_clock_modes = 1;
2398 rdev->pm.power_state[state_index].clock_info[0].mclk = RBIOS32(offset + 0x5 + 0x2);
2399 rdev->pm.power_state[state_index].clock_info[0].sclk = RBIOS32(offset + 0x5 + 0x6);
2400 if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
2401 (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
2402 goto default_mode;
2403 /* skip overclock modes for now */
2404 if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
2405 rdev->clock.default_mclk) ||
2406 (rdev->pm.power_state[state_index].clock_info[0].sclk >
2407 rdev->clock.default_sclk))
2408 goto default_mode;
2409 misc = RBIOS16(offset + 0x5 + 0x0);
2410 if (rev > 4)
2411 misc2 = RBIOS16(offset + 0x5 + 0xe);
2412 if (misc & 0x4) {
2413 rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_GPIO;
2414 if (misc & 0x8)
2415 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2416 true;
2417 else
2418 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
2419 false;
2420 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.valid = true;
2421 if (rev < 6) {
2422 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.reg =
2423 RBIOS16(offset + 0x5 + 0xb) * 4;
2424 tmp = RBIOS8(offset + 0x5 + 0xd);
2425 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.mask = (1 << tmp);
2426 } else {
2427 u8 entries = RBIOS8(offset + 0x5 + 0xb);
2428 u16 voltage_table_offset = RBIOS16(offset + 0x5 + 0xc);
2429 if (entries && voltage_table_offset) {
2430 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.reg =
2431 RBIOS16(voltage_table_offset) * 4;
2432 tmp = RBIOS8(voltage_table_offset + 0x2);
2433 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.mask = (1 << tmp);
2434 } else
2435 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.valid = false;
2436 }
2437 switch ((misc2 & 0x700) >> 8) {
2438 case 0:
2439 default:
2440 rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 0;
2441 break;
2442 case 1:
2443 rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 33;
2444 break;
2445 case 2:
2446 rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 66;
2447 break;
2448 case 3:
2449 rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 99;
2450 break;
2451 case 4:
2452 rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 132;
2453 break;
2454 }
2455 } else
2456 rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
2457 if (rev > 6)
2458 rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
2459 RBIOS8(offset + 0x5 + 0x10);
2460 state_index++;
2461 } else {
2462 /* XXX figure out some good default low power mode for mobility cards w/out power tables */
2463 }
2464 } else {
2465 /* XXX figure out some good default low power mode for desktop cards */
2466 }
2467
2468default_mode:
2469 /* add the default mode */
2470 rdev->pm.power_state[state_index].num_clock_modes = 1;
2471 rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
2472 rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
2473 rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0];
2474 rdev->pm.power_state[state_index].current_clock_mode = &rdev->pm.power_state[state_index].clock_info[0];
2475 rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
2476 if (rdev->asic->get_pcie_lanes)
2477 rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = radeon_get_pcie_lanes(rdev);
2478 else
2479 rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = 16;
2480 rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
2481 rdev->pm.current_power_state = &rdev->pm.power_state[state_index];
2482 rdev->pm.num_power_states = state_index + 1;
2483}
2484
2377void radeon_external_tmds_setup(struct drm_encoder *encoder) 2485void radeon_external_tmds_setup(struct drm_encoder *encoder)
2378{ 2486{
2379 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2487 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);