aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2012-09-12 18:54:14 -0400
committerAlex Deucher <alexander.deucher@amd.com>2012-09-20 13:10:44 -0400
commit2f454cf1261ba913e2f660b7555864b340502c60 (patch)
tree3582704f7e9e07c0036e597dca80394d10bcca18 /drivers
parent9dbbcfc6894957fdbb311ba92c85c026659878b5 (diff)
drm/radeon: allow PPLL sharing on non-DP displays
If several non-DP displays use the same pixel clock we can use the same PPLL for all of them. If all relevant displays have the same pixel clock, this allows the driver to: - use fewer PPLLs which saves power - support more than two non-DP displays on DCE4+ The current drm modesetting infrastructure doesn't really provide a good framework for validating combinations that work or won't work, so it's possible you could go from a working configuration to a non-working one by changing the mode a one of the displays. However, there this is better than what was there before. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c71
1 files changed, 65 insertions, 6 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index c5a040677d48..2f7cc9e3b175 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1536,6 +1536,49 @@ static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc)
1536} 1536}
1537 1537
1538/** 1538/**
1539 * radeon_get_shared_nondp_ppll - return the PPLL used by another non-DP crtc
1540 *
1541 * @crtc: drm crtc
1542 * @encoder: drm encoder
1543 *
1544 * Returns the PPLL (Pixel PLL) used by another non-DP crtc/encoder which can
1545 * be shared (i.e., same clock).
1546 */
1547static int radeon_get_shared_nondp_ppll(struct drm_crtc *crtc,
1548 struct drm_encoder *encoder)
1549{
1550 struct drm_device *dev = crtc->dev;
1551 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1552 struct drm_encoder *test_encoder;
1553 struct radeon_crtc *radeon_test_crtc;
1554 struct radeon_encoder *test_radeon_encoder;
1555 u32 target_clock, test_clock;
1556
1557 if (radeon_encoder->native_mode.clock)
1558 target_clock = radeon_encoder->native_mode.clock;
1559 else
1560 target_clock = crtc->mode.clock;
1561
1562 list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
1563 if (test_encoder->crtc && (test_encoder->crtc != crtc)) {
1564 if (!ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
1565 test_radeon_encoder = to_radeon_encoder(test_encoder);
1566 radeon_test_crtc = to_radeon_crtc(test_encoder->crtc);
1567 /* for non-DP check the clock */
1568 if (test_radeon_encoder->native_mode.clock)
1569 test_clock = test_radeon_encoder->native_mode.clock;
1570 else
1571 test_clock = test_encoder->crtc->mode.clock;
1572 if ((target_clock == test_clock) &&
1573 (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID))
1574 return radeon_test_crtc->pll_id;
1575 }
1576 }
1577 }
1578 return ATOM_PPLL_INVALID;
1579}
1580
1581/**
1539 * radeon_atom_pick_pll - Allocate a PPLL for use by the crtc. 1582 * radeon_atom_pick_pll - Allocate a PPLL for use by the crtc.
1540 * 1583 *
1541 * @crtc: drm crtc 1584 * @crtc: drm crtc
@@ -1568,7 +1611,6 @@ static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc)
1568 */ 1611 */
1569static int radeon_atom_pick_pll(struct drm_crtc *crtc) 1612static int radeon_atom_pick_pll(struct drm_crtc *crtc)
1570{ 1613{
1571 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1572 struct drm_device *dev = crtc->dev; 1614 struct drm_device *dev = crtc->dev;
1573 struct radeon_device *rdev = dev->dev_private; 1615 struct radeon_device *rdev = dev->dev_private;
1574 struct drm_encoder *test_encoder; 1616 struct drm_encoder *test_encoder;
@@ -1599,6 +1641,11 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
1599 if (pll != ATOM_PPLL_INVALID) 1641 if (pll != ATOM_PPLL_INVALID)
1600 return pll; 1642 return pll;
1601 } 1643 }
1644 } else {
1645 /* use the same PPLL for all monitors with the same clock */
1646 pll = radeon_get_shared_nondp_ppll(crtc, test_encoder);
1647 if (pll != ATOM_PPLL_INVALID)
1648 return pll;
1602 } 1649 }
1603 break; 1650 break;
1604 } 1651 }
@@ -1640,6 +1687,11 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
1640 if (pll != ATOM_PPLL_INVALID) 1687 if (pll != ATOM_PPLL_INVALID)
1641 return pll; 1688 return pll;
1642 } 1689 }
1690 } else {
1691 /* use the same PPLL for all monitors with the same clock */
1692 pll = radeon_get_shared_nondp_ppll(crtc, test_encoder);
1693 if (pll != ATOM_PPLL_INVALID)
1694 return pll;
1643 } 1695 }
1644 break; 1696 break;
1645 } 1697 }
@@ -1652,7 +1704,12 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
1652 return ATOM_PPLL1; 1704 return ATOM_PPLL1;
1653 DRM_ERROR("unable to allocate a PPLL\n"); 1705 DRM_ERROR("unable to allocate a PPLL\n");
1654 return ATOM_PPLL_INVALID; 1706 return ATOM_PPLL_INVALID;
1655 } else if (ASIC_IS_DCE3(rdev)) { 1707 } else {
1708 /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
1709 if (!ASIC_IS_AVIVO(rdev)) {
1710 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1711 return radeon_crtc->crtc_id;
1712 }
1656 list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { 1713 list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
1657 if (test_encoder->crtc && (test_encoder->crtc == crtc)) { 1714 if (test_encoder->crtc && (test_encoder->crtc == crtc)) {
1658 /* in DP mode, the DP ref clock can come from either PPLL 1715 /* in DP mode, the DP ref clock can come from either PPLL
@@ -1664,6 +1721,11 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
1664 pll = radeon_get_shared_dp_ppll(crtc); 1721 pll = radeon_get_shared_dp_ppll(crtc);
1665 if (pll != ATOM_PPLL_INVALID) 1722 if (pll != ATOM_PPLL_INVALID)
1666 return pll; 1723 return pll;
1724 } else {
1725 /* use the same PPLL for all monitors with the same clock */
1726 pll = radeon_get_shared_nondp_ppll(crtc, test_encoder);
1727 if (pll != ATOM_PPLL_INVALID)
1728 return pll;
1667 } 1729 }
1668 break; 1730 break;
1669 } 1731 }
@@ -1676,10 +1738,7 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
1676 return ATOM_PPLL1; 1738 return ATOM_PPLL1;
1677 DRM_ERROR("unable to allocate a PPLL\n"); 1739 DRM_ERROR("unable to allocate a PPLL\n");
1678 return ATOM_PPLL_INVALID; 1740 return ATOM_PPLL_INVALID;
1679 } else 1741 }
1680 /* use PPLL1 or PPLL2 */
1681 return radeon_crtc->crtc_id;
1682
1683} 1742}
1684 1743
1685void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev) 1744void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev)