diff options
| -rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 163 |
1 files changed, 34 insertions, 129 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index e721e3087b99..2817101fb167 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
| @@ -1479,98 +1479,14 @@ static void radeon_legacy_atom_fixup(struct drm_crtc *crtc) | |||
| 1479 | } | 1479 | } |
| 1480 | } | 1480 | } |
| 1481 | 1481 | ||
| 1482 | /** | ||
| 1483 | * radeon_get_pll_use_mask - look up a mask of which pplls are in use | ||
| 1484 | * | ||
| 1485 | * @crtc: drm crtc | ||
| 1486 | * | ||
| 1487 | * Returns the mask of which PPLLs (Pixel PLLs) are in use. | ||
| 1488 | */ | ||
| 1489 | static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc) | ||
| 1490 | { | ||
| 1491 | struct drm_device *dev = crtc->dev; | ||
| 1492 | struct drm_crtc *test_crtc; | ||
| 1493 | struct radeon_crtc *radeon_test_crtc; | ||
| 1494 | u32 pll_in_use = 0; | ||
| 1495 | |||
| 1496 | list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { | ||
| 1497 | if (crtc == test_crtc) | ||
| 1498 | continue; | ||
| 1499 | |||
| 1500 | radeon_test_crtc = to_radeon_crtc(test_crtc); | ||
| 1501 | if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID) | ||
| 1502 | pll_in_use |= (1 << radeon_test_crtc->pll_id); | ||
| 1503 | } | ||
| 1504 | return pll_in_use; | ||
| 1505 | } | ||
| 1506 | |||
| 1507 | /** | ||
| 1508 | * radeon_get_shared_dp_ppll - return the PPLL used by another crtc for DP | ||
| 1509 | * | ||
| 1510 | * @crtc: drm crtc | ||
| 1511 | * | ||
| 1512 | * Returns the PPLL (Pixel PLL) used by another crtc/encoder which is | ||
| 1513 | * also in DP mode. For DP, a single PPLL can be used for all DP | ||
| 1514 | * crtcs/encoders. | ||
| 1515 | */ | ||
| 1516 | static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc) | ||
| 1517 | { | ||
| 1518 | struct drm_device *dev = crtc->dev; | ||
| 1519 | struct drm_encoder *test_encoder; | ||
| 1520 | struct radeon_crtc *radeon_test_crtc; | ||
| 1521 | |||
| 1522 | list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { | ||
| 1523 | if (test_encoder->crtc && (test_encoder->crtc != crtc)) { | ||
| 1524 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { | ||
| 1525 | /* for DP use the same PLL for all */ | ||
| 1526 | radeon_test_crtc = to_radeon_crtc(test_encoder->crtc); | ||
| 1527 | if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID) | ||
| 1528 | return radeon_test_crtc->pll_id; | ||
| 1529 | } | ||
| 1530 | } | ||
| 1531 | } | ||
| 1532 | return ATOM_PPLL_INVALID; | ||
| 1533 | } | ||
| 1534 | |||
| 1535 | /** | ||
| 1536 | * radeon_atom_pick_pll - Allocate a PPLL for use by the crtc. | ||
| 1537 | * | ||
| 1538 | * @crtc: drm crtc | ||
| 1539 | * | ||
| 1540 | * Returns the PPLL (Pixel PLL) to be used by the crtc. For DP monitors | ||
| 1541 | * a single PPLL can be used for all DP crtcs/encoders. For non-DP | ||
| 1542 | * monitors a dedicated PPLL must be used. If a particular board has | ||
| 1543 | * an external DP PLL, return ATOM_PPLL_INVALID to skip PLL programming | ||
| 1544 | * as there is no need to program the PLL itself. If we are not able to | ||
| 1545 | * allocate a PLL, return ATOM_PPLL_INVALID to skip PLL programming to | ||
| 1546 | * avoid messing up an existing monitor. | ||
| 1547 | * | ||
| 1548 | * Asic specific PLL information | ||
| 1549 | * | ||
| 1550 | * DCE 6.1 | ||
| 1551 | * - PPLL2 is only available to UNIPHYA (both DP and non-DP) | ||
| 1552 | * - PPLL0, PPLL1 are available for UNIPHYB/C/D/E/F (both DP and non-DP) | ||
| 1553 | * | ||
| 1554 | * DCE 6.0 | ||
| 1555 | * - PPLL0 is available to all UNIPHY (DP only) | ||
| 1556 | * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC | ||
| 1557 | * | ||
| 1558 | * DCE 5.0 | ||
| 1559 | * - DCPLL is available to all UNIPHY (DP only) | ||
| 1560 | * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC | ||
| 1561 | * | ||
| 1562 | * DCE 3.0/4.0/4.1 | ||
| 1563 | * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC | ||
| 1564 | * | ||
| 1565 | */ | ||
| 1566 | static int radeon_atom_pick_pll(struct drm_crtc *crtc) | 1482 | static int radeon_atom_pick_pll(struct drm_crtc *crtc) |
| 1567 | { | 1483 | { |
| 1568 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 1484 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
| 1569 | struct drm_device *dev = crtc->dev; | 1485 | struct drm_device *dev = crtc->dev; |
| 1570 | struct radeon_device *rdev = dev->dev_private; | 1486 | struct radeon_device *rdev = dev->dev_private; |
| 1571 | struct drm_encoder *test_encoder; | 1487 | struct drm_encoder *test_encoder; |
| 1572 | u32 pll_in_use; | 1488 | struct drm_crtc *test_crtc; |
| 1573 | int pll; | 1489 | uint32_t pll_in_use = 0; |
| 1574 | 1490 | ||
| 1575 | if (ASIC_IS_DCE61(rdev)) { | 1491 | if (ASIC_IS_DCE61(rdev)) { |
| 1576 | list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { | 1492 | list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { |
| @@ -1582,40 +1498,32 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) | |||
| 1582 | 1498 | ||
| 1583 | if ((test_radeon_encoder->encoder_id == | 1499 | if ((test_radeon_encoder->encoder_id == |
| 1584 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY) && | 1500 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY) && |
| 1585 | (dig->linkb == false)) | 1501 | (dig->linkb == false)) /* UNIPHY A uses PPLL2 */ |
| 1586 | /* UNIPHY A uses PPLL2 */ | ||
| 1587 | return ATOM_PPLL2; | 1502 | return ATOM_PPLL2; |
| 1588 | else if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { | ||
| 1589 | /* UNIPHY B/C/D/E/F */ | ||
| 1590 | if (rdev->clock.dp_extclk) | ||
| 1591 | /* skip PPLL programming if using ext clock */ | ||
| 1592 | return ATOM_PPLL_INVALID; | ||
| 1593 | else { | ||
| 1594 | /* use the same PPLL for all DP monitors */ | ||
| 1595 | pll = radeon_get_shared_dp_ppll(crtc); | ||
| 1596 | if (pll != ATOM_PPLL_INVALID) | ||
| 1597 | return pll; | ||
| 1598 | } | ||
| 1599 | } | ||
| 1600 | break; | ||
| 1601 | } | 1503 | } |
| 1602 | } | 1504 | } |
| 1603 | /* UNIPHY B/C/D/E/F */ | 1505 | /* UNIPHY B/C/D/E/F */ |
| 1604 | pll_in_use = radeon_get_pll_use_mask(crtc); | 1506 | list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { |
| 1605 | if (!(pll_in_use & (1 << ATOM_PPLL0))) | 1507 | struct radeon_crtc *radeon_test_crtc; |
| 1508 | |||
| 1509 | if (crtc == test_crtc) | ||
| 1510 | continue; | ||
| 1511 | |||
| 1512 | radeon_test_crtc = to_radeon_crtc(test_crtc); | ||
| 1513 | if ((radeon_test_crtc->pll_id == ATOM_PPLL0) || | ||
| 1514 | (radeon_test_crtc->pll_id == ATOM_PPLL1)) | ||
| 1515 | pll_in_use |= (1 << radeon_test_crtc->pll_id); | ||
| 1516 | } | ||
| 1517 | if (!(pll_in_use & 4)) | ||
| 1606 | return ATOM_PPLL0; | 1518 | return ATOM_PPLL0; |
| 1607 | if (!(pll_in_use & (1 << ATOM_PPLL1))) | 1519 | return ATOM_PPLL1; |
| 1608 | return ATOM_PPLL1; | ||
| 1609 | DRM_ERROR("unable to allocate a PPLL\n"); | ||
| 1610 | return ATOM_PPLL_INVALID; | ||
| 1611 | } else if (ASIC_IS_DCE4(rdev)) { | 1520 | } else if (ASIC_IS_DCE4(rdev)) { |
| 1612 | list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { | 1521 | list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { |
| 1613 | if (test_encoder->crtc && (test_encoder->crtc == crtc)) { | 1522 | if (test_encoder->crtc && (test_encoder->crtc == crtc)) { |
| 1614 | /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock, | 1523 | /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock, |
| 1615 | * depending on the asic: | 1524 | * depending on the asic: |
| 1616 | * DCE4: PPLL or ext clock | 1525 | * DCE4: PPLL or ext clock |
| 1617 | * DCE5: PPLL, DCPLL, or ext clock | 1526 | * DCE5: DCPLL or ext clock |
| 1618 | * DCE6: PPLL, PPLL0, or ext clock | ||
| 1619 | * | 1527 | * |
| 1620 | * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip | 1528 | * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip |
| 1621 | * PPLL/DCPLL programming and only program the DP DTO for the | 1529 | * PPLL/DCPLL programming and only program the DP DTO for the |
| @@ -1623,34 +1531,31 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) | |||
| 1623 | */ | 1531 | */ |
| 1624 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { | 1532 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { |
| 1625 | if (rdev->clock.dp_extclk) | 1533 | if (rdev->clock.dp_extclk) |
| 1626 | /* skip PPLL programming if using ext clock */ | ||
| 1627 | return ATOM_PPLL_INVALID; | 1534 | return ATOM_PPLL_INVALID; |
| 1628 | else if (ASIC_IS_DCE6(rdev)) | 1535 | else if (ASIC_IS_DCE6(rdev)) |
| 1629 | /* use PPLL0 for all DP */ | ||
| 1630 | return ATOM_PPLL0; | 1536 | return ATOM_PPLL0; |
| 1631 | else if (ASIC_IS_DCE5(rdev)) | 1537 | else if (ASIC_IS_DCE5(rdev)) |
| 1632 | /* use DCPLL for all DP */ | ||
| 1633 | return ATOM_DCPLL; | 1538 | return ATOM_DCPLL; |
| 1634 | else { | ||
| 1635 | /* use the same PPLL for all DP monitors */ | ||
| 1636 | pll = radeon_get_shared_dp_ppll(crtc); | ||
| 1637 | if (pll != ATOM_PPLL_INVALID) | ||
| 1638 | return pll; | ||
| 1639 | } | ||
| 1640 | } | 1539 | } |
| 1641 | break; | ||
| 1642 | } | 1540 | } |
| 1643 | } | 1541 | } |
| 1644 | /* all other cases */ | 1542 | |
| 1645 | pll_in_use = radeon_get_pll_use_mask(crtc); | 1543 | /* otherwise, pick one of the plls */ |
| 1646 | if (!(pll_in_use & (1 << ATOM_PPLL2))) | 1544 | list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { |
| 1647 | return ATOM_PPLL2; | 1545 | struct radeon_crtc *radeon_test_crtc; |
| 1648 | if (!(pll_in_use & (1 << ATOM_PPLL1))) | 1546 | |
| 1547 | if (crtc == test_crtc) | ||
| 1548 | continue; | ||
| 1549 | |||
| 1550 | radeon_test_crtc = to_radeon_crtc(test_crtc); | ||
| 1551 | if ((radeon_test_crtc->pll_id >= ATOM_PPLL1) && | ||
| 1552 | (radeon_test_crtc->pll_id <= ATOM_PPLL2)) | ||
| 1553 | pll_in_use |= (1 << radeon_test_crtc->pll_id); | ||
| 1554 | } | ||
| 1555 | if (!(pll_in_use & 1)) | ||
| 1649 | return ATOM_PPLL1; | 1556 | return ATOM_PPLL1; |
| 1650 | DRM_ERROR("unable to allocate a PPLL\n"); | 1557 | return ATOM_PPLL2; |
| 1651 | return ATOM_PPLL_INVALID; | ||
| 1652 | } else | 1558 | } else |
| 1653 | /* use PPLL1 or PPLL2 */ | ||
| 1654 | return radeon_crtc->crtc_id; | 1559 | return radeon_crtc->crtc_id; |
| 1655 | 1560 | ||
| 1656 | } | 1561 | } |
| @@ -1792,7 +1697,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) | |||
| 1792 | break; | 1697 | break; |
| 1793 | } | 1698 | } |
| 1794 | done: | 1699 | done: |
| 1795 | radeon_crtc->pll_id = ATOM_PPLL_INVALID; | 1700 | radeon_crtc->pll_id = -1; |
| 1796 | } | 1701 | } |
| 1797 | 1702 | ||
| 1798 | static const struct drm_crtc_helper_funcs atombios_helper_funcs = { | 1703 | static const struct drm_crtc_helper_funcs atombios_helper_funcs = { |
| @@ -1841,6 +1746,6 @@ void radeon_atombios_init_crtc(struct drm_device *dev, | |||
| 1841 | else | 1746 | else |
| 1842 | radeon_crtc->crtc_offset = 0; | 1747 | radeon_crtc->crtc_offset = 0; |
| 1843 | } | 1748 | } |
| 1844 | radeon_crtc->pll_id = ATOM_PPLL_INVALID; | 1749 | radeon_crtc->pll_id = -1; |
| 1845 | drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); | 1750 | drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); |
| 1846 | } | 1751 | } |
