diff options
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 61 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 299 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_combios.c | 108 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 38 |
4 files changed, 506 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index df21edcbae16..d73d37d5effd 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -150,6 +150,8 @@ struct radeon_clock { | |||
150 | */ | 150 | */ |
151 | int radeon_pm_init(struct radeon_device *rdev); | 151 | int radeon_pm_init(struct radeon_device *rdev); |
152 | void radeon_pm_compute_clocks(struct radeon_device *rdev); | 152 | void radeon_pm_compute_clocks(struct radeon_device *rdev); |
153 | void radeon_combios_get_power_modes(struct radeon_device *rdev); | ||
154 | void radeon_atombios_get_power_modes(struct radeon_device *rdev); | ||
153 | 155 | ||
154 | /* | 156 | /* |
155 | * Fences. | 157 | * Fences. |
@@ -583,6 +585,59 @@ enum radeon_pm_action { | |||
583 | PM_ACTION_DOWNCLOCK, | 585 | PM_ACTION_DOWNCLOCK, |
584 | PM_ACTION_UPCLOCK | 586 | PM_ACTION_UPCLOCK |
585 | }; | 587 | }; |
588 | |||
589 | enum radeon_voltage_type { | ||
590 | VOLTAGE_NONE = 0, | ||
591 | VOLTAGE_GPIO, | ||
592 | VOLTAGE_VDDC, | ||
593 | VOLTAGE_SW | ||
594 | }; | ||
595 | |||
596 | struct radeon_voltage { | ||
597 | enum radeon_voltage_type type; | ||
598 | /* gpio voltage */ | ||
599 | struct radeon_gpio_rec gpio; | ||
600 | u32 delay; /* delay in usec from voltage drop to sclk change */ | ||
601 | bool active_high; /* voltage drop is active when bit is high */ | ||
602 | /* VDDC voltage */ | ||
603 | u8 vddc_id; /* index into vddc voltage table */ | ||
604 | u8 vddci_id; /* index into vddci voltage table */ | ||
605 | bool vddci_enabled; | ||
606 | /* r6xx+ sw */ | ||
607 | u32 voltage; | ||
608 | }; | ||
609 | |||
610 | struct radeon_pm_non_clock_info { | ||
611 | /* pcie lanes */ | ||
612 | int pcie_lanes; | ||
613 | /* standardized non-clock flags */ | ||
614 | u32 flags; | ||
615 | }; | ||
616 | |||
617 | struct radeon_pm_clock_info { | ||
618 | /* memory clock */ | ||
619 | u32 mclk; | ||
620 | /* engine clock */ | ||
621 | u32 sclk; | ||
622 | /* voltage info */ | ||
623 | struct radeon_voltage voltage; | ||
624 | /* standardized clock flags - not sure we'll need these */ | ||
625 | u32 flags; | ||
626 | }; | ||
627 | |||
628 | struct radeon_power_state { | ||
629 | /* XXX: use a define for num clock modes */ | ||
630 | struct radeon_pm_clock_info clock_info[8]; | ||
631 | /* number of valid clock modes in this power state */ | ||
632 | int num_clock_modes; | ||
633 | /* currently selected clock mode */ | ||
634 | struct radeon_pm_clock_info *current_clock_mode; | ||
635 | struct radeon_pm_clock_info *default_clock_mode; | ||
636 | /* non clock info about this state */ | ||
637 | struct radeon_pm_non_clock_info non_clock_info; | ||
638 | bool voltage_drop_active; | ||
639 | }; | ||
640 | |||
586 | struct radeon_pm { | 641 | struct radeon_pm { |
587 | struct mutex mutex; | 642 | struct mutex mutex; |
588 | struct work_struct reclock_work; | 643 | struct work_struct reclock_work; |
@@ -609,6 +664,12 @@ struct radeon_pm { | |||
609 | fixed20_12 core_bandwidth; | 664 | fixed20_12 core_bandwidth; |
610 | fixed20_12 sclk; | 665 | fixed20_12 sclk; |
611 | fixed20_12 needed_bandwidth; | 666 | fixed20_12 needed_bandwidth; |
667 | /* XXX: use a define for num power modes */ | ||
668 | struct radeon_power_state power_state[8]; | ||
669 | /* number of valid power states */ | ||
670 | int num_power_states; | ||
671 | struct radeon_power_state *current_power_state; | ||
672 | struct radeon_power_state *default_power_state; | ||
612 | }; | 673 | }; |
613 | 674 | ||
614 | 675 | ||
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; |
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); |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index a9c61f435c06..6eb0e0b3264b 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * OTHER DEALINGS IN THE SOFTWARE. | 18 | * OTHER DEALINGS IN THE SOFTWARE. |
19 | * | 19 | * |
20 | * Authors: Rafał Miłecki <zajec5@gmail.com> | 20 | * Authors: Rafał Miłecki <zajec5@gmail.com> |
21 | * Alex Deucher <alexdeucher@gmail.com> | ||
21 | */ | 22 | */ |
22 | #include "drmP.h" | 23 | #include "drmP.h" |
23 | #include "radeon.h" | 24 | #include "radeon.h" |
@@ -39,6 +40,35 @@ static const char *pm_state_names[4] = { | |||
39 | "PM_STATE_ACTIVE" | 40 | "PM_STATE_ACTIVE" |
40 | }; | 41 | }; |
41 | 42 | ||
43 | static void radeon_print_power_mode_info(struct radeon_device *rdev) | ||
44 | { | ||
45 | int i, j; | ||
46 | bool is_default; | ||
47 | |||
48 | DRM_INFO("%d Power State(s)\n", rdev->pm.num_power_states); | ||
49 | for (i = 0; i < rdev->pm.num_power_states; i++) { | ||
50 | if (rdev->pm.default_power_state == &rdev->pm.power_state[i]) | ||
51 | is_default = true; | ||
52 | else | ||
53 | is_default = false; | ||
54 | DRM_INFO("State %d %s\n", i, is_default ? "(default)" : ""); | ||
55 | if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP)) | ||
56 | DRM_INFO("\t%d PCIE Lanes\n", rdev->pm.power_state[i].non_clock_info.pcie_lanes); | ||
57 | DRM_INFO("\t%d Clock Mode(s)\n", rdev->pm.power_state[i].num_clock_modes); | ||
58 | for (j = 0; j < rdev->pm.power_state[i].num_clock_modes; j++) { | ||
59 | if (rdev->flags & RADEON_IS_IGP) | ||
60 | DRM_INFO("\t\t%d engine: %d\n", | ||
61 | j, | ||
62 | rdev->pm.power_state[i].clock_info[j].sclk * 10); | ||
63 | else | ||
64 | DRM_INFO("\t\t%d engine/memory: %d/%d\n", | ||
65 | j, | ||
66 | rdev->pm.power_state[i].clock_info[j].sclk * 10, | ||
67 | rdev->pm.power_state[i].clock_info[j].mclk * 10); | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | |||
42 | int radeon_pm_init(struct radeon_device *rdev) | 72 | int radeon_pm_init(struct radeon_device *rdev) |
43 | { | 73 | { |
44 | rdev->pm.state = PM_STATE_DISABLED; | 74 | rdev->pm.state = PM_STATE_DISABLED; |
@@ -46,6 +76,14 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
46 | rdev->pm.downclocked = false; | 76 | rdev->pm.downclocked = false; |
47 | rdev->pm.vblank_callback = false; | 77 | rdev->pm.vblank_callback = false; |
48 | 78 | ||
79 | if (rdev->bios) { | ||
80 | if (rdev->is_atom_bios) | ||
81 | radeon_atombios_get_power_modes(rdev); | ||
82 | else | ||
83 | radeon_combios_get_power_modes(rdev); | ||
84 | radeon_print_power_mode_info(rdev); | ||
85 | } | ||
86 | |||
49 | radeon_pm_check_limits(rdev); | 87 | radeon_pm_check_limits(rdev); |
50 | 88 | ||
51 | if (radeon_debugfs_pm_init(rdev)) { | 89 | if (radeon_debugfs_pm_init(rdev)) { |