aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2012-08-31 11:56:50 -0400
committerAlex Deucher <alexander.deucher@amd.com>2012-09-20 13:10:43 -0400
commitf3dd8508d459a2d0d0bc426144b92f1696d4fe86 (patch)
tree000ca4a5d664dca3837cc5c11d59c332bea8c046
parenta59fbb8e18566a346a2736000d979576ab7525fe (diff)
drm/radeon: rework pll selection (v4)
For DP we can use the same PPLL for all active DP encoders. Take advantage of that to prevent cases where we may end up sharing a PPLL between DP and non-DP which won't work. Also clean up the code a bit. v2: - fix missing pll_id assignment in crtc init v3: - fix DP PPLL check - document functions - break in main encoder search loop after matching. no need to keep checking additional encoders. v4: - same as v3, but re-apply to drm-next as the corner cases are fixed properly in subsequent patches. fixes: https://bugs.freedesktop.org/show_bug.cgi?id=54471 Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c163
1 files changed, 129 insertions, 34 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index cc1b2444a5e5..8e73d53b769e 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1482,14 +1482,98 @@ static void radeon_legacy_atom_fixup(struct drm_crtc *crtc)
1482 } 1482 }
1483} 1483}
1484 1484
1485/**
1486 * radeon_get_pll_use_mask - look up a mask of which pplls are in use
1487 *
1488 * @crtc: drm crtc
1489 *
1490 * Returns the mask of which PPLLs (Pixel PLLs) are in use.
1491 */
1492static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc)
1493{
1494 struct drm_device *dev = crtc->dev;
1495 struct drm_crtc *test_crtc;
1496 struct radeon_crtc *radeon_test_crtc;
1497 u32 pll_in_use = 0;
1498
1499 list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
1500 if (crtc == test_crtc)
1501 continue;
1502
1503 radeon_test_crtc = to_radeon_crtc(test_crtc);
1504 if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID)
1505 pll_in_use |= (1 << radeon_test_crtc->pll_id);
1506 }
1507 return pll_in_use;
1508}
1509
1510/**
1511 * radeon_get_shared_dp_ppll - return the PPLL used by another crtc for DP
1512 *
1513 * @crtc: drm crtc
1514 *
1515 * Returns the PPLL (Pixel PLL) used by another crtc/encoder which is
1516 * also in DP mode. For DP, a single PPLL can be used for all DP
1517 * crtcs/encoders.
1518 */
1519static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc)
1520{
1521 struct drm_device *dev = crtc->dev;
1522 struct drm_encoder *test_encoder;
1523 struct radeon_crtc *radeon_test_crtc;
1524
1525 list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
1526 if (test_encoder->crtc && (test_encoder->crtc != crtc)) {
1527 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
1528 /* for DP use the same PLL for all */
1529 radeon_test_crtc = to_radeon_crtc(test_encoder->crtc);
1530 if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID)
1531 return radeon_test_crtc->pll_id;
1532 }
1533 }
1534 }
1535 return ATOM_PPLL_INVALID;
1536}
1537
1538/**
1539 * radeon_atom_pick_pll - Allocate a PPLL for use by the crtc.
1540 *
1541 * @crtc: drm crtc
1542 *
1543 * Returns the PPLL (Pixel PLL) to be used by the crtc. For DP monitors
1544 * a single PPLL can be used for all DP crtcs/encoders. For non-DP
1545 * monitors a dedicated PPLL must be used. If a particular board has
1546 * an external DP PLL, return ATOM_PPLL_INVALID to skip PLL programming
1547 * as there is no need to program the PLL itself. If we are not able to
1548 * allocate a PLL, return ATOM_PPLL_INVALID to skip PLL programming to
1549 * avoid messing up an existing monitor.
1550 *
1551 * Asic specific PLL information
1552 *
1553 * DCE 6.1
1554 * - PPLL2 is only available to UNIPHYA (both DP and non-DP)
1555 * - PPLL0, PPLL1 are available for UNIPHYB/C/D/E/F (both DP and non-DP)
1556 *
1557 * DCE 6.0
1558 * - PPLL0 is available to all UNIPHY (DP only)
1559 * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC
1560 *
1561 * DCE 5.0
1562 * - DCPLL is available to all UNIPHY (DP only)
1563 * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC
1564 *
1565 * DCE 3.0/4.0/4.1
1566 * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC
1567 *
1568 */
1485static int radeon_atom_pick_pll(struct drm_crtc *crtc) 1569static int radeon_atom_pick_pll(struct drm_crtc *crtc)
1486{ 1570{
1487 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 1571 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1488 struct drm_device *dev = crtc->dev; 1572 struct drm_device *dev = crtc->dev;
1489 struct radeon_device *rdev = dev->dev_private; 1573 struct radeon_device *rdev = dev->dev_private;
1490 struct drm_encoder *test_encoder; 1574 struct drm_encoder *test_encoder;
1491 struct drm_crtc *test_crtc; 1575 u32 pll_in_use;
1492 uint32_t pll_in_use = 0; 1576 int pll;
1493 1577
1494 if (ASIC_IS_DCE61(rdev)) { 1578 if (ASIC_IS_DCE61(rdev)) {
1495 list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { 1579 list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
@@ -1501,32 +1585,40 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
1501 1585
1502 if ((test_radeon_encoder->encoder_id == 1586 if ((test_radeon_encoder->encoder_id ==
1503 ENCODER_OBJECT_ID_INTERNAL_UNIPHY) && 1587 ENCODER_OBJECT_ID_INTERNAL_UNIPHY) &&
1504 (dig->linkb == false)) /* UNIPHY A uses PPLL2 */ 1588 (dig->linkb == false))
1589 /* UNIPHY A uses PPLL2 */
1505 return ATOM_PPLL2; 1590 return ATOM_PPLL2;
1591 else if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
1592 /* UNIPHY B/C/D/E/F */
1593 if (rdev->clock.dp_extclk)
1594 /* skip PPLL programming if using ext clock */
1595 return ATOM_PPLL_INVALID;
1596 else {
1597 /* use the same PPLL for all DP monitors */
1598 pll = radeon_get_shared_dp_ppll(crtc);
1599 if (pll != ATOM_PPLL_INVALID)
1600 return pll;
1601 }
1602 }
1603 break;
1506 } 1604 }
1507 } 1605 }
1508 /* UNIPHY B/C/D/E/F */ 1606 /* UNIPHY B/C/D/E/F */
1509 list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { 1607 pll_in_use = radeon_get_pll_use_mask(crtc);
1510 struct radeon_crtc *radeon_test_crtc; 1608 if (!(pll_in_use & (1 << ATOM_PPLL0)))
1511
1512 if (crtc == test_crtc)
1513 continue;
1514
1515 radeon_test_crtc = to_radeon_crtc(test_crtc);
1516 if ((radeon_test_crtc->pll_id == ATOM_PPLL0) ||
1517 (radeon_test_crtc->pll_id == ATOM_PPLL1))
1518 pll_in_use |= (1 << radeon_test_crtc->pll_id);
1519 }
1520 if (!(pll_in_use & 4))
1521 return ATOM_PPLL0; 1609 return ATOM_PPLL0;
1522 return ATOM_PPLL1; 1610 if (!(pll_in_use & (1 << ATOM_PPLL1)))
1611 return ATOM_PPLL1;
1612 DRM_ERROR("unable to allocate a PPLL\n");
1613 return ATOM_PPLL_INVALID;
1523 } else if (ASIC_IS_DCE4(rdev)) { 1614 } else if (ASIC_IS_DCE4(rdev)) {
1524 list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { 1615 list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
1525 if (test_encoder->crtc && (test_encoder->crtc == crtc)) { 1616 if (test_encoder->crtc && (test_encoder->crtc == crtc)) {
1526 /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock, 1617 /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock,
1527 * depending on the asic: 1618 * depending on the asic:
1528 * DCE4: PPLL or ext clock 1619 * DCE4: PPLL or ext clock
1529 * DCE5: DCPLL or ext clock 1620 * DCE5: PPLL, DCPLL, or ext clock
1621 * DCE6: PPLL, PPLL0, or ext clock
1530 * 1622 *
1531 * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip 1623 * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip
1532 * PPLL/DCPLL programming and only program the DP DTO for the 1624 * PPLL/DCPLL programming and only program the DP DTO for the
@@ -1534,31 +1626,34 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
1534 */ 1626 */
1535 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { 1627 if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
1536 if (rdev->clock.dp_extclk) 1628 if (rdev->clock.dp_extclk)
1629 /* skip PPLL programming if using ext clock */
1537 return ATOM_PPLL_INVALID; 1630 return ATOM_PPLL_INVALID;
1538 else if (ASIC_IS_DCE6(rdev)) 1631 else if (ASIC_IS_DCE6(rdev))
1632 /* use PPLL0 for all DP */
1539 return ATOM_PPLL0; 1633 return ATOM_PPLL0;
1540 else if (ASIC_IS_DCE5(rdev)) 1634 else if (ASIC_IS_DCE5(rdev))
1635 /* use DCPLL for all DP */
1541 return ATOM_DCPLL; 1636 return ATOM_DCPLL;
1637 else {
1638 /* use the same PPLL for all DP monitors */
1639 pll = radeon_get_shared_dp_ppll(crtc);
1640 if (pll != ATOM_PPLL_INVALID)
1641 return pll;
1642 }
1542 } 1643 }
1644 break;
1543 } 1645 }
1544 } 1646 }
1545 1647 /* all other cases */
1546 /* otherwise, pick one of the plls */ 1648 pll_in_use = radeon_get_pll_use_mask(crtc);
1547 list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { 1649 if (!(pll_in_use & (1 << ATOM_PPLL2)))
1548 struct radeon_crtc *radeon_test_crtc; 1650 return ATOM_PPLL2;
1549 1651 if (!(pll_in_use & (1 << ATOM_PPLL1)))
1550 if (crtc == test_crtc)
1551 continue;
1552
1553 radeon_test_crtc = to_radeon_crtc(test_crtc);
1554 if ((radeon_test_crtc->pll_id >= ATOM_PPLL1) &&
1555 (radeon_test_crtc->pll_id <= ATOM_PPLL2))
1556 pll_in_use |= (1 << radeon_test_crtc->pll_id);
1557 }
1558 if (!(pll_in_use & 1))
1559 return ATOM_PPLL1; 1652 return ATOM_PPLL1;
1560 return ATOM_PPLL2; 1653 DRM_ERROR("unable to allocate a PPLL\n");
1654 return ATOM_PPLL_INVALID;
1561 } else 1655 } else
1656 /* use PPLL1 or PPLL2 */
1562 return radeon_crtc->crtc_id; 1657 return radeon_crtc->crtc_id;
1563 1658
1564} 1659}
@@ -1700,7 +1795,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
1700 break; 1795 break;
1701 } 1796 }
1702done: 1797done:
1703 radeon_crtc->pll_id = -1; 1798 radeon_crtc->pll_id = ATOM_PPLL_INVALID;
1704} 1799}
1705 1800
1706static const struct drm_crtc_helper_funcs atombios_helper_funcs = { 1801static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
@@ -1749,6 +1844,6 @@ void radeon_atombios_init_crtc(struct drm_device *dev,
1749 else 1844 else
1750 radeon_crtc->crtc_offset = 0; 1845 radeon_crtc->crtc_offset = 0;
1751 } 1846 }
1752 radeon_crtc->pll_id = -1; 1847 radeon_crtc->pll_id = ATOM_PPLL_INVALID;
1753 drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); 1848 drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
1754} 1849}