diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_atombios.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 299 |
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 | ||
1396 | union 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 | |||
1403 | void 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 | |||
1396 | void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) | 1695 | void 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; |