aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_atombios.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_atombios.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_atombios.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c299
1 files changed, 299 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index d33fb4174b13..adf900e368ac 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -1393,6 +1393,305 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
1393 return tv_dac; 1393 return tv_dac;
1394} 1394}
1395 1395
1396union power_info {
1397 struct _ATOM_POWERPLAY_INFO info;
1398 struct _ATOM_POWERPLAY_INFO_V2 info_2;
1399 struct _ATOM_POWERPLAY_INFO_V3 info_3;
1400 struct _ATOM_PPLIB_POWERPLAYTABLE info_4;
1401};
1402
1403void radeon_atombios_get_power_modes(struct radeon_device *rdev)
1404{
1405 struct radeon_mode_info *mode_info = &rdev->mode_info;
1406 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
1407 u16 data_offset;
1408 u8 frev, crev;
1409 u32 misc, misc2 = 0, sclk, mclk;
1410 union power_info *power_info;
1411 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
1412 struct _ATOM_PPLIB_STATE *power_state;
1413 int num_modes = 0, i, j;
1414 int state_index = 0, mode_index = 0;
1415
1416 atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
1417
1418 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
1419
1420 rdev->pm.default_power_state = NULL;
1421 rdev->pm.current_power_state = NULL;
1422
1423 if (power_info) {
1424 if (frev < 4) {
1425 num_modes = power_info->info.ucNumOfPowerModeEntries;
1426 if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
1427 num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
1428 for (i = 0; i < num_modes; i++) {
1429 rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
1430 switch (frev) {
1431 case 1:
1432 rdev->pm.power_state[state_index].num_clock_modes = 1;
1433 rdev->pm.power_state[state_index].clock_info[0].mclk =
1434 le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock);
1435 rdev->pm.power_state[state_index].clock_info[0].sclk =
1436 le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock);
1437 /* skip invalid modes */
1438 if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
1439 (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
1440 continue;
1441 /* skip overclock modes for now */
1442 if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
1443 rdev->clock.default_mclk) ||
1444 (rdev->pm.power_state[state_index].clock_info[0].sclk >
1445 rdev->clock.default_sclk))
1446 continue;
1447 rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
1448 power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
1449 misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
1450 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
1451 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1452 VOLTAGE_GPIO;
1453 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
1454 radeon_lookup_gpio(rdev,
1455 power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex);
1456 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
1457 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
1458 true;
1459 else
1460 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
1461 false;
1462 } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
1463 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1464 VOLTAGE_VDDC;
1465 rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
1466 power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
1467 }
1468 if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
1469 rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
1470 rdev->pm.current_power_state = &rdev->pm.power_state[state_index];
1471 rdev->pm.power_state[state_index].default_clock_mode =
1472 &rdev->pm.power_state[state_index].clock_info[0];
1473 rdev->pm.power_state[state_index].current_clock_mode =
1474 &rdev->pm.power_state[state_index].clock_info[0];
1475 }
1476 state_index++;
1477 break;
1478 case 2:
1479 rdev->pm.power_state[state_index].num_clock_modes = 1;
1480 rdev->pm.power_state[state_index].clock_info[0].mclk =
1481 le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock);
1482 rdev->pm.power_state[state_index].clock_info[0].sclk =
1483 le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock);
1484 /* skip invalid modes */
1485 if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
1486 (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
1487 continue;
1488 /* skip overclock modes for now */
1489 if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
1490 rdev->clock.default_mclk) ||
1491 (rdev->pm.power_state[state_index].clock_info[0].sclk >
1492 rdev->clock.default_sclk))
1493 continue;
1494 rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
1495 power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
1496 misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
1497 misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
1498 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
1499 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1500 VOLTAGE_GPIO;
1501 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
1502 radeon_lookup_gpio(rdev,
1503 power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex);
1504 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
1505 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
1506 true;
1507 else
1508 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
1509 false;
1510 } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
1511 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1512 VOLTAGE_VDDC;
1513 rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
1514 power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
1515 }
1516 if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
1517 rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
1518 rdev->pm.current_power_state = &rdev->pm.power_state[state_index];
1519 rdev->pm.power_state[state_index].default_clock_mode =
1520 &rdev->pm.power_state[state_index].clock_info[0];
1521 rdev->pm.power_state[state_index].current_clock_mode =
1522 &rdev->pm.power_state[state_index].clock_info[0];
1523 }
1524 state_index++;
1525 break;
1526 case 3:
1527 rdev->pm.power_state[state_index].num_clock_modes = 1;
1528 rdev->pm.power_state[state_index].clock_info[0].mclk =
1529 le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock);
1530 rdev->pm.power_state[state_index].clock_info[0].sclk =
1531 le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock);
1532 /* skip invalid modes */
1533 if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
1534 (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
1535 continue;
1536 /* skip overclock modes for now */
1537 if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
1538 rdev->clock.default_mclk) ||
1539 (rdev->pm.power_state[state_index].clock_info[0].sclk >
1540 rdev->clock.default_sclk))
1541 continue;
1542 rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
1543 power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
1544 misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
1545 misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
1546 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
1547 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1548 VOLTAGE_GPIO;
1549 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
1550 radeon_lookup_gpio(rdev,
1551 power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex);
1552 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
1553 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
1554 true;
1555 else
1556 rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
1557 false;
1558 } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
1559 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1560 VOLTAGE_VDDC;
1561 rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
1562 power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex;
1563 if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) {
1564 rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled =
1565 true;
1566 rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id =
1567 power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
1568 }
1569 }
1570 if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
1571 rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
1572 rdev->pm.current_power_state = &rdev->pm.power_state[state_index];
1573 rdev->pm.power_state[state_index].default_clock_mode =
1574 &rdev->pm.power_state[state_index].clock_info[0];
1575 rdev->pm.power_state[state_index].current_clock_mode =
1576 &rdev->pm.power_state[state_index].clock_info[0];
1577 }
1578 state_index++;
1579 break;
1580 }
1581 }
1582 } else if (frev == 4) {
1583 for (i = 0; i < power_info->info_4.ucNumStates; i++) {
1584 mode_index = 0;
1585 power_state = (struct _ATOM_PPLIB_STATE *)
1586 (mode_info->atom_context->bios +
1587 data_offset +
1588 le16_to_cpu(power_info->info_4.usStateArrayOffset) +
1589 i * power_info->info_4.ucStateEntrySize);
1590 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
1591 (mode_info->atom_context->bios +
1592 data_offset +
1593 le16_to_cpu(power_info->info_4.usNonClockInfoArrayOffset) +
1594 (power_state->ucNonClockStateIndex *
1595 power_info->info_4.ucNonClockSize));
1596 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
1597 rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
1598 ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
1599 ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
1600 for (j = 0; j < (power_info->info_4.ucStateEntrySize - 1); j++) {
1601 if (rdev->flags & RADEON_IS_IGP) {
1602 struct _ATOM_PPLIB_RS780_CLOCK_INFO *clock_info =
1603 (struct _ATOM_PPLIB_RS780_CLOCK_INFO *)
1604 (mode_info->atom_context->bios +
1605 data_offset +
1606 le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
1607 (power_state->ucClockStateIndices[j] *
1608 power_info->info_4.ucClockInfoSize));
1609 sclk = le16_to_cpu(clock_info->usLowEngineClockLow);
1610 sclk |= clock_info->ucLowEngineClockHigh << 16;
1611 rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
1612 /* skip invalid modes */
1613 if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
1614 continue;
1615 /* skip overclock modes for now */
1616 if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
1617 rdev->clock.default_sclk)
1618 continue;
1619 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
1620 VOLTAGE_SW;
1621 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
1622 clock_info->usVDDC;
1623 mode_index++;
1624 } else {
1625 struct _ATOM_PPLIB_R600_CLOCK_INFO *clock_info =
1626 (struct _ATOM_PPLIB_R600_CLOCK_INFO *)
1627 (mode_info->atom_context->bios +
1628 data_offset +
1629 le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
1630 (power_state->ucClockStateIndices[j] *
1631 power_info->info_4.ucClockInfoSize));
1632 sclk = le16_to_cpu(clock_info->usEngineClockLow);
1633 sclk |= clock_info->ucEngineClockHigh << 16;
1634 mclk = le16_to_cpu(clock_info->usMemoryClockLow);
1635 mclk |= clock_info->ucMemoryClockHigh << 16;
1636 rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
1637 rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
1638 /* skip invalid modes */
1639 if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
1640 (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
1641 continue;
1642 /* skip overclock modes for now */
1643 if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk >
1644 rdev->clock.default_mclk) ||
1645 (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
1646 rdev->clock.default_sclk))
1647 continue;
1648 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
1649 VOLTAGE_SW;
1650 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
1651 clock_info->usVDDC;
1652 mode_index++;
1653 }
1654 }
1655 rdev->pm.power_state[state_index].num_clock_modes = mode_index;
1656 if (mode_index) {
1657 misc2 = le16_to_cpu(non_clock_info->usClassification);
1658 if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) {
1659 rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
1660 rdev->pm.current_power_state = &rdev->pm.power_state[state_index];
1661 rdev->pm.power_state[state_index].default_clock_mode =
1662 &rdev->pm.power_state[state_index].clock_info[mode_index - 1];
1663 rdev->pm.power_state[state_index].current_clock_mode =
1664 &rdev->pm.power_state[state_index].clock_info[mode_index - 1];
1665 }
1666 state_index++;
1667 }
1668 }
1669 }
1670 } else {
1671 /* XXX figure out some good default low power mode for cards w/out power tables */
1672 }
1673
1674 if (rdev->pm.default_power_state == NULL) {
1675 /* add the default mode */
1676 rdev->pm.power_state[state_index].num_clock_modes = 1;
1677 rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
1678 rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
1679 rdev->pm.power_state[state_index].default_clock_mode =
1680 &rdev->pm.power_state[state_index].clock_info[0];
1681 rdev->pm.power_state[state_index].current_clock_mode =
1682 &rdev->pm.power_state[state_index].clock_info[0];
1683 rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
1684 if (rdev->asic->get_pcie_lanes)
1685 rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = radeon_get_pcie_lanes(rdev);
1686 else
1687 rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = 16;
1688 rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
1689 rdev->pm.current_power_state = &rdev->pm.power_state[state_index];
1690 state_index++;
1691 }
1692 rdev->pm.num_power_states = state_index;
1693}
1694
1396void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) 1695void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
1397{ 1696{
1398 DYNAMIC_CLOCK_GATING_PS_ALLOCATION args; 1697 DYNAMIC_CLOCK_GATING_PS_ALLOCATION args;