diff options
author | Xiaojie Yuan <Xiaojie.Yuan@amd.com> | 2017-02-20 22:41:40 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-05-24 17:39:59 -0400 |
commit | e6f7c765e70fadf9046cfa06159be722ecfb8bd4 (patch) | |
tree | dc250bbb9ed99deba999864cacef05d496f33bbe /drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | |
parent | 4caca70668b777649cf64c652bc1d506a74052c6 (diff) |
drm/amdgpu: add HDMI audio support for si dce6
Signed-off-by: Xiaojie Yuan <Xiaojie.Yuan@amd.com>
Reviewed-by: Edward O'Callaghan <funfunctor@folklore1984.net>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/dce_v6_0.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 130 |
1 files changed, 121 insertions, 9 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index ec18c3daf3c2..e2a56c9283df 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | |||
@@ -1532,12 +1532,58 @@ static void dce_v6_0_audio_fini(struct amdgpu_device *adev) | |||
1532 | adev->mode_info.audio.enabled = false; | 1532 | adev->mode_info.audio.enabled = false; |
1533 | } | 1533 | } |
1534 | 1534 | ||
1535 | /* | 1535 | static void dce_v6_0_audio_set_vbi_packet(struct drm_encoder *encoder) |
1536 | static void dce_v6_0_afmt_update_ACR(struct drm_encoder *encoder, uint32_t clock) | ||
1537 | { | 1536 | { |
1538 | DRM_INFO("xxxx: dce_v6_0_afmt_update_ACR---no imp!!!!!\n"); | 1537 | struct drm_device *dev = encoder->dev; |
1538 | struct amdgpu_device *adev = dev->dev_private; | ||
1539 | struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); | ||
1540 | struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; | ||
1541 | u32 tmp; | ||
1542 | |||
1543 | tmp = RREG32(mmHDMI_VBI_PACKET_CONTROL + dig->afmt->offset); | ||
1544 | tmp = REG_SET_FIELD(tmp, HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, 1); | ||
1545 | tmp = REG_SET_FIELD(tmp, HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, 1); | ||
1546 | tmp = REG_SET_FIELD(tmp, HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, 1); | ||
1547 | WREG32(mmHDMI_VBI_PACKET_CONTROL + dig->afmt->offset, tmp); | ||
1548 | } | ||
1549 | |||
1550 | static void dce_v6_0_audio_set_acr(struct drm_encoder *encoder, | ||
1551 | uint32_t clock, int bpc) | ||
1552 | { | ||
1553 | struct drm_device *dev = encoder->dev; | ||
1554 | struct amdgpu_device *adev = dev->dev_private; | ||
1555 | struct amdgpu_afmt_acr acr = amdgpu_afmt_acr(clock); | ||
1556 | struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); | ||
1557 | struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; | ||
1558 | u32 tmp; | ||
1559 | |||
1560 | tmp = RREG32(mmHDMI_ACR_PACKET_CONTROL + dig->afmt->offset); | ||
1561 | tmp = REG_SET_FIELD(tmp, HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, 1); | ||
1562 | tmp = REG_SET_FIELD(tmp, HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, | ||
1563 | bpc > 8 ? 0 : 1); | ||
1564 | WREG32(mmHDMI_ACR_PACKET_CONTROL + dig->afmt->offset, tmp); | ||
1565 | |||
1566 | tmp = RREG32(mmHDMI_ACR_32_0 + dig->afmt->offset); | ||
1567 | tmp = REG_SET_FIELD(tmp, HDMI_ACR_32_0, HDMI_ACR_CTS_32, acr.cts_32khz); | ||
1568 | WREG32(mmHDMI_ACR_32_0 + dig->afmt->offset, tmp); | ||
1569 | tmp = RREG32(mmHDMI_ACR_32_1 + dig->afmt->offset); | ||
1570 | tmp = REG_SET_FIELD(tmp, HDMI_ACR_32_1, HDMI_ACR_N_32, acr.n_32khz); | ||
1571 | WREG32(mmHDMI_ACR_32_1 + dig->afmt->offset, tmp); | ||
1572 | |||
1573 | tmp = RREG32(mmHDMI_ACR_44_0 + dig->afmt->offset); | ||
1574 | tmp = REG_SET_FIELD(tmp, HDMI_ACR_44_0, HDMI_ACR_CTS_44, acr.cts_44_1khz); | ||
1575 | WREG32(mmHDMI_ACR_44_0 + dig->afmt->offset, tmp); | ||
1576 | tmp = RREG32(mmHDMI_ACR_44_1 + dig->afmt->offset); | ||
1577 | tmp = REG_SET_FIELD(tmp, HDMI_ACR_44_1, HDMI_ACR_N_44, acr.n_44_1khz); | ||
1578 | WREG32(mmHDMI_ACR_44_1 + dig->afmt->offset, tmp); | ||
1579 | |||
1580 | tmp = RREG32(mmHDMI_ACR_48_0 + dig->afmt->offset); | ||
1581 | tmp = REG_SET_FIELD(tmp, HDMI_ACR_48_0, HDMI_ACR_CTS_48, acr.cts_48khz); | ||
1582 | WREG32(mmHDMI_ACR_48_0 + dig->afmt->offset, tmp); | ||
1583 | tmp = RREG32(mmHDMI_ACR_48_1 + dig->afmt->offset); | ||
1584 | tmp = REG_SET_FIELD(tmp, HDMI_ACR_48_1, HDMI_ACR_N_48, acr.n_48khz); | ||
1585 | WREG32(mmHDMI_ACR_48_1 + dig->afmt->offset, tmp); | ||
1539 | } | 1586 | } |
1540 | */ | ||
1541 | 1587 | ||
1542 | static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder, | 1588 | static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder, |
1543 | struct drm_display_mode *mode) | 1589 | struct drm_display_mode *mode) |
@@ -1586,6 +1632,7 @@ static void dce_v6_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) | |||
1586 | struct drm_device *dev = encoder->dev; | 1632 | struct drm_device *dev = encoder->dev; |
1587 | struct amdgpu_device *adev = dev->dev_private; | 1633 | struct amdgpu_device *adev = dev->dev_private; |
1588 | struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); | 1634 | struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); |
1635 | int em = amdgpu_atombios_encoder_get_encoder_mode(encoder); | ||
1589 | u32 tmp; | 1636 | u32 tmp; |
1590 | 1637 | ||
1591 | /* | 1638 | /* |
@@ -1597,10 +1644,21 @@ static void dce_v6_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) | |||
1597 | tmp = RREG32(mmDCCG_AUDIO_DTO_SOURCE); | 1644 | tmp = RREG32(mmDCCG_AUDIO_DTO_SOURCE); |
1598 | tmp = REG_SET_FIELD(tmp, DCCG_AUDIO_DTO_SOURCE, | 1645 | tmp = REG_SET_FIELD(tmp, DCCG_AUDIO_DTO_SOURCE, |
1599 | DCCG_AUDIO_DTO0_SOURCE_SEL, amdgpu_crtc->crtc_id); | 1646 | DCCG_AUDIO_DTO0_SOURCE_SEL, amdgpu_crtc->crtc_id); |
1600 | tmp = REG_SET_FIELD(tmp, DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, 1); | 1647 | if (em == ATOM_ENCODER_MODE_HDMI) { |
1648 | tmp = REG_SET_FIELD(tmp, DCCG_AUDIO_DTO_SOURCE, | ||
1649 | DCCG_AUDIO_DTO_SEL, 0); | ||
1650 | } else if (ENCODER_MODE_IS_DP(em)) { | ||
1651 | tmp = REG_SET_FIELD(tmp, DCCG_AUDIO_DTO_SOURCE, | ||
1652 | DCCG_AUDIO_DTO_SEL, 1); | ||
1653 | } | ||
1601 | WREG32(mmDCCG_AUDIO_DTO_SOURCE, tmp); | 1654 | WREG32(mmDCCG_AUDIO_DTO_SOURCE, tmp); |
1602 | WREG32(mmDCCG_AUDIO_DTO1_PHASE, 24000); | 1655 | if (em == ATOM_ENCODER_MODE_HDMI) { |
1603 | WREG32(mmDCCG_AUDIO_DTO1_MODULE, clock); | 1656 | WREG32(mmDCCG_AUDIO_DTO0_PHASE, 24000); |
1657 | WREG32(mmDCCG_AUDIO_DTO0_MODULE, clock); | ||
1658 | } else if (ENCODER_MODE_IS_DP(em)) { | ||
1659 | WREG32(mmDCCG_AUDIO_DTO1_PHASE, 24000); | ||
1660 | WREG32(mmDCCG_AUDIO_DTO1_MODULE, clock); | ||
1661 | } | ||
1604 | } | 1662 | } |
1605 | 1663 | ||
1606 | static void dce_v6_0_audio_set_packet(struct drm_encoder *encoder) | 1664 | static void dce_v6_0_audio_set_packet(struct drm_encoder *encoder) |
@@ -1660,6 +1718,43 @@ static void dce_v6_0_audio_set_mute(struct drm_encoder *encoder, bool mute) | |||
1660 | WREG32(mmHDMI_GC + dig->afmt->offset, tmp); | 1718 | WREG32(mmHDMI_GC + dig->afmt->offset, tmp); |
1661 | } | 1719 | } |
1662 | 1720 | ||
1721 | static void dce_v6_0_audio_hdmi_enable(struct drm_encoder *encoder, bool enable) | ||
1722 | { | ||
1723 | struct drm_device *dev = encoder->dev; | ||
1724 | struct amdgpu_device *adev = dev->dev_private; | ||
1725 | struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); | ||
1726 | struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; | ||
1727 | u32 tmp; | ||
1728 | |||
1729 | if (enable) { | ||
1730 | tmp = RREG32(mmHDMI_INFOFRAME_CONTROL0 + dig->afmt->offset); | ||
1731 | tmp = REG_SET_FIELD(tmp, HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_SEND, 1); | ||
1732 | tmp = REG_SET_FIELD(tmp, HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_CONT, 1); | ||
1733 | tmp = REG_SET_FIELD(tmp, HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); | ||
1734 | tmp = REG_SET_FIELD(tmp, HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_CONT, 1); | ||
1735 | WREG32(mmHDMI_INFOFRAME_CONTROL0 + dig->afmt->offset, tmp); | ||
1736 | |||
1737 | tmp = RREG32(mmHDMI_INFOFRAME_CONTROL1 + dig->afmt->offset); | ||
1738 | tmp = REG_SET_FIELD(tmp, HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE, 2); | ||
1739 | WREG32(mmHDMI_INFOFRAME_CONTROL1 + dig->afmt->offset, tmp); | ||
1740 | |||
1741 | tmp = RREG32(mmAFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset); | ||
1742 | tmp = REG_SET_FIELD(tmp, AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, 1); | ||
1743 | WREG32(mmAFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset, tmp); | ||
1744 | } else { | ||
1745 | tmp = RREG32(mmHDMI_INFOFRAME_CONTROL0 + dig->afmt->offset); | ||
1746 | tmp = REG_SET_FIELD(tmp, HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_SEND, 0); | ||
1747 | tmp = REG_SET_FIELD(tmp, HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_CONT, 0); | ||
1748 | tmp = REG_SET_FIELD(tmp, HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 0); | ||
1749 | tmp = REG_SET_FIELD(tmp, HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_CONT, 0); | ||
1750 | WREG32(mmHDMI_INFOFRAME_CONTROL0 + dig->afmt->offset, tmp); | ||
1751 | |||
1752 | tmp = RREG32(mmAFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset); | ||
1753 | tmp = REG_SET_FIELD(tmp, AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, 0); | ||
1754 | WREG32(mmAFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset, tmp); | ||
1755 | } | ||
1756 | } | ||
1757 | |||
1663 | static void dce_v6_0_audio_dp_enable(struct drm_encoder *encoder, bool enable) | 1758 | static void dce_v6_0_audio_dp_enable(struct drm_encoder *encoder, bool enable) |
1664 | { | 1759 | { |
1665 | struct drm_device *dev = encoder->dev; | 1760 | struct drm_device *dev = encoder->dev; |
@@ -1697,6 +1792,8 @@ static void dce_v6_0_afmt_setmode(struct drm_encoder *encoder, | |||
1697 | struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; | 1792 | struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; |
1698 | struct drm_connector *connector; | 1793 | struct drm_connector *connector; |
1699 | struct amdgpu_connector *amdgpu_connector = NULL; | 1794 | struct amdgpu_connector *amdgpu_connector = NULL; |
1795 | int em = amdgpu_atombios_encoder_get_encoder_mode(encoder); | ||
1796 | int bpc = 8; | ||
1700 | 1797 | ||
1701 | if (!dig || !dig->afmt) | 1798 | if (!dig || !dig->afmt) |
1702 | return; | 1799 | return; |
@@ -1720,6 +1817,11 @@ static void dce_v6_0_afmt_setmode(struct drm_encoder *encoder, | |||
1720 | if (!dig->afmt->pin) | 1817 | if (!dig->afmt->pin) |
1721 | return; | 1818 | return; |
1722 | 1819 | ||
1820 | if (encoder->crtc) { | ||
1821 | struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); | ||
1822 | bpc = amdgpu_crtc->bpc; | ||
1823 | } | ||
1824 | |||
1723 | /* disable audio before setting up hw */ | 1825 | /* disable audio before setting up hw */ |
1724 | dce_v6_0_audio_enable(adev, dig->afmt->pin, false); | 1826 | dce_v6_0_audio_enable(adev, dig->afmt->pin, false); |
1725 | 1827 | ||
@@ -1727,12 +1829,22 @@ static void dce_v6_0_afmt_setmode(struct drm_encoder *encoder, | |||
1727 | dce_v6_0_audio_write_speaker_allocation(encoder); | 1829 | dce_v6_0_audio_write_speaker_allocation(encoder); |
1728 | dce_v6_0_audio_write_sad_regs(encoder); | 1830 | dce_v6_0_audio_write_sad_regs(encoder); |
1729 | dce_v6_0_audio_write_latency_fields(encoder, mode); | 1831 | dce_v6_0_audio_write_latency_fields(encoder, mode); |
1730 | dce_v6_0_audio_set_dto(encoder, adev->clock.default_dispclk * 10); | 1832 | if (em == ATOM_ENCODER_MODE_HDMI) { |
1833 | dce_v6_0_audio_set_dto(encoder, mode->clock); | ||
1834 | dce_v6_0_audio_set_vbi_packet(encoder); | ||
1835 | dce_v6_0_audio_set_acr(encoder, mode->clock, bpc); | ||
1836 | } else if (ENCODER_MODE_IS_DP(em)) { | ||
1837 | dce_v6_0_audio_set_dto(encoder, adev->clock.default_dispclk * 10); | ||
1838 | } | ||
1731 | dce_v6_0_audio_set_packet(encoder); | 1839 | dce_v6_0_audio_set_packet(encoder); |
1732 | dce_v6_0_audio_select_pin(encoder); | 1840 | dce_v6_0_audio_select_pin(encoder); |
1733 | dce_v6_0_audio_set_avi_infoframe(encoder, mode); | 1841 | dce_v6_0_audio_set_avi_infoframe(encoder, mode); |
1734 | dce_v6_0_audio_set_mute(encoder, false); | 1842 | dce_v6_0_audio_set_mute(encoder, false); |
1735 | dce_v6_0_audio_dp_enable(encoder, 1); | 1843 | if (em == ATOM_ENCODER_MODE_HDMI) { |
1844 | dce_v6_0_audio_hdmi_enable(encoder, 1); | ||
1845 | } else if (ENCODER_MODE_IS_DP(em)) { | ||
1846 | dce_v6_0_audio_dp_enable(encoder, 1); | ||
1847 | } | ||
1736 | 1848 | ||
1737 | /* enable audio after setting up hw */ | 1849 | /* enable audio after setting up hw */ |
1738 | dce_v6_0_audio_enable(adev, dig->afmt->pin, true); | 1850 | dce_v6_0_audio_enable(adev, dig->afmt->pin, true); |