Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe6fc1f1 authored by Slava Grigorev's avatar Slava Grigorev Committed by Alex Deucher
Browse files

drm/radeon: fix DP audio support for APU with DCE4.1 display engine



Properly setup the DFS divider for DP audio for DCE4.1.

Signed-off-by: default avatarSlava Grigorev <slava.grigorev@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
parent a64c9dab
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -289,6 +289,16 @@ void dce4_dp_audio_set_dto(struct radeon_device *rdev,
	 * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
	 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
	 */
	if (ASIC_IS_DCE41(rdev)) {
		unsigned int div = (RREG32(DCE41_DENTIST_DISPCLK_CNTL) &
			DENTIST_DPREFCLK_WDIVIDER_MASK) >>
			DENTIST_DPREFCLK_WDIVIDER_SHIFT;
		div = radeon_audio_decode_dfs_div(div);

		if (div)
			clock = 100 * clock / div;
	}

	WREG32(DCCG_AUDIO_DTO1_PHASE, 24000);
	WREG32(DCCG_AUDIO_DTO1_MODULE, clock);
}
+5 −0
Original line number Diff line number Diff line
@@ -511,6 +511,11 @@
#define DCCG_AUDIO_DTO1_CNTL              0x05cc
#       define DCCG_AUDIO_DTO1_USE_512FBR_DTO (1 << 3)

#define DCE41_DENTIST_DISPCLK_CNTL			0x049c
#       define DENTIST_DPREFCLK_WDIVIDER(x)		(((x) & 0x7f) << 24)
#       define DENTIST_DPREFCLK_WDIVIDER_MASK		(0x7f << 24)
#       define DENTIST_DPREFCLK_WDIVIDER_SHIFT		24

/* DCE 4.0 AFMT */
#define HDMI_CONTROL                         0x7030
#       define HDMI_KEEPOUT_MODE             (1 << 0)
+29 −8
Original line number Diff line number Diff line
@@ -1106,6 +1106,31 @@ union firmware_info {
	ATOM_FIRMWARE_INFO_V2_2 info_22;
};

union igp_info {
	struct _ATOM_INTEGRATED_SYSTEM_INFO info;
	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
	struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
	struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8;
};

static void radeon_atombios_get_dentist_vco_freq(struct radeon_device *rdev)
{
	struct radeon_mode_info *mode_info = &rdev->mode_info;
	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
	union igp_info *igp_info;
	u8 frev, crev;
	u16 data_offset;

	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
			&frev, &crev, &data_offset)) {
		igp_info = (union igp_info *)(mode_info->atom_context->bios +
			data_offset);
		rdev->clock.vco_freq =
			le32_to_cpu(igp_info->info_6.ulDentistVCOFreq);
	}
}

bool radeon_atom_get_clock_info(struct drm_device *dev)
{
	struct radeon_device *rdev = dev->dev_private;
@@ -1260,6 +1285,10 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
		if (ASIC_IS_DCE8(rdev))
			rdev->clock.vco_freq =
				le32_to_cpu(firmware_info->info_22.ulGPUPLL_OutputFreq);
		else if (ASIC_IS_DCE5(rdev))
			rdev->clock.vco_freq = rdev->clock.current_dispclk;
		else if (ASIC_IS_DCE41(rdev))
			radeon_atombios_get_dentist_vco_freq(rdev);
		else
			rdev->clock.vco_freq = rdev->clock.current_dispclk;

@@ -1272,14 +1301,6 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
	return false;
}

union igp_info {
	struct _ATOM_INTEGRATED_SYSTEM_INFO info;
	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
	struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
	struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8;
};

bool radeon_atombios_sideport_present(struct radeon_device *rdev)
{
	struct radeon_mode_info *mode_info = &rdev->mode_info;