diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_combios.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_combios.c | 108 |
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 | ||
2377 | void 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 | |||
2468 | default_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 | |||
2377 | void radeon_external_tmds_setup(struct drm_encoder *encoder) | 2485 | void 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); |