Browse Source

Merge branch 'drm-next-3.20' of git://people.freedesktop.org/~agd5f/linux into drm-next

Radeon drm-next changes for 3.20.  Highlights:
- Indirect draw support for evergreen/NI hw
- SMC fan control support for SI/CI
- Manual fan control for SI/CI
- DP audio support
- Lots of code cleanup

* 'drm-next-3.20' of git://people.freedesktop.org/~agd5f/linux: (45 commits)
  drm/radeon: make MMU_NOTIFIER optional
  drm/radeon: use NULL rather then 0 in audio detect
  drm/radeon: whitespace clean up in radeon_audio.c
  radeon/audio: enable DP audio
  radeon/audio: moved audio caps programming to audio_hotplug() function
  radeon/audio: applied audio_dpms() and audio_mode_set() calls
  radeon/audio: consolidate audio_mode_set() functions
  radeon/audio: removed unnecessary debug settings
  radeon/audio: moved mute programming to a separate function
  radeon/audio: moved audio packet programming to a separate function
  radeon/audio: set_avi_packet() function cleanup
  radeon/audio: removed unnecessary CRC control programing
  radeon: moved HDMI color depth programming to a separate function
  radeon/audio: moved VBI packet programming to separate functions
  radeon/audio: consolidate update_acr() functions (v2)
  radeon/audio: consolidate update_avi_infoframe() functions
  radeon/audio: consolidate audio_set_dto() functions
  radeon/audio: consolidate audio_fini() functions
  radeon/audio: consolidate audio_enable() functions
  radeon/audio: consolidate select_pin() functions
  ...
Dave Airlie 10 years ago
parent
commit
cc0cc1aa27
46 changed files with 1837 additions and 971 deletions
  1. 0 1
      drivers/gpu/drm/Kconfig
  2. 4 2
      drivers/gpu/drm/radeon/Makefile
  3. 18 11
      drivers/gpu/drm/radeon/atombios_encoders.c
  4. 2 0
      drivers/gpu/drm/radeon/btc_dpm.c
  5. 47 10
      drivers/gpu/drm/radeon/ci_dpm.c
  6. 1 0
      drivers/gpu/drm/radeon/ci_dpm.h
  7. 2 0
      drivers/gpu/drm/radeon/ci_smc.c
  8. 3 2
      drivers/gpu/drm/radeon/cik.c
  9. 2 0
      drivers/gpu/drm/radeon/cypress_dpm.c
  10. 126 138
      drivers/gpu/drm/radeon/dce3_1_afmt.c
  11. 93 125
      drivers/gpu/drm/radeon/dce6_afmt.c
  12. 4 3
      drivers/gpu/drm/radeon/evergreen.c
  13. 76 0
      drivers/gpu/drm/radeon/evergreen_cs.c
  14. 214 264
      drivers/gpu/drm/radeon/evergreen_hdmi.c
  15. 15 0
      drivers/gpu/drm/radeon/evergreen_reg.h
  16. 1 0
      drivers/gpu/drm/radeon/evergreend.h
  17. 2 0
      drivers/gpu/drm/radeon/kv_dpm.c
  18. 5 13
      drivers/gpu/drm/radeon/ni.c
  19. 2 0
      drivers/gpu/drm/radeon/ni_dpm.c
  20. 4 3
      drivers/gpu/drm/radeon/r600.c
  21. 95 304
      drivers/gpu/drm/radeon/r600_hdmi.c
  22. 15 0
      drivers/gpu/drm/radeon/radeon.h
  23. 8 28
      drivers/gpu/drm/radeon/radeon_asic.c
  24. 13 8
      drivers/gpu/drm/radeon/radeon_asic.h
  25. 766 0
      drivers/gpu/drm/radeon/radeon_audio.c
  26. 84 0
      drivers/gpu/drm/radeon/radeon_audio.h
  27. 8 0
      drivers/gpu/drm/radeon/radeon_connectors.c
  28. 2 1
      drivers/gpu/drm/radeon/radeon_drv.c
  29. 0 10
      drivers/gpu/drm/radeon/radeon_fb.c
  30. 0 5
      drivers/gpu/drm/radeon/radeon_i2c.c
  31. 1 3
      drivers/gpu/drm/radeon/radeon_mode.h
  32. 0 6
      drivers/gpu/drm/radeon/radeon_object.c
  33. 0 2
      drivers/gpu/drm/radeon/radeon_object.h
  34. 130 1
      drivers/gpu/drm/radeon/radeon_pm.c
  35. 4 3
      drivers/gpu/drm/radeon/rs600.c
  36. 4 3
      drivers/gpu/drm/radeon/rs690.c
  37. 3 2
      drivers/gpu/drm/radeon/rv770.c
  38. 4 0
      drivers/gpu/drm/radeon/rv770_dpm.c
  39. 0 2
      drivers/gpu/drm/radeon/rv770_dpm.h
  40. 3 2
      drivers/gpu/drm/radeon/si.c
  41. 59 16
      drivers/gpu/drm/radeon/si_dpm.c
  42. 1 0
      drivers/gpu/drm/radeon/si_dpm.h
  43. 10 0
      drivers/gpu/drm/radeon/sid.h
  44. 4 0
      drivers/gpu/drm/radeon/sumo_dpm.c
  45. 0 3
      drivers/gpu/drm/radeon/sumo_dpm.h
  46. 2 0
      drivers/gpu/drm/radeon/trinity_dpm.c

+ 0 - 1
drivers/gpu/drm/Kconfig

@@ -110,7 +110,6 @@ config DRM_RADEON
 	select HWMON
 	select BACKLIGHT_CLASS_DEVICE
 	select INTERVAL_TREE
-	select MMU_NOTIFIER
 	help
 	  Choose this option if you have an ATI Radeon graphics card.  There
 	  are both PCI and AGP versions.  You don't need to choose this to

+ 4 - 2
drivers/gpu/drm/radeon/Makefile

@@ -80,8 +80,10 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
 	r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
 	rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
 	trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \
-	ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o radeon_mn.o \
-	radeon_sync.o
+	ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o \
+	radeon_sync.o radeon_audio.o
+
+radeon-$(CONFIG_MMU_NOTIFIER) += radeon_mn.o
 
 # add async DMA block
 radeon-y += \

+ 18 - 11
drivers/gpu/drm/radeon/atombios_encoders.c

@@ -27,6 +27,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/radeon_drm.h>
 #include "radeon.h"
+#include "radeon_audio.h"
 #include "atom.h"
 #include <linux/backlight.h>
 
@@ -664,6 +665,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
 int
 atombios_get_encoder_mode(struct drm_encoder *encoder)
 {
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct drm_connector *connector;
 	struct radeon_connector *radeon_connector;
@@ -728,6 +731,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
 		dig_connector = radeon_connector->con_priv;
 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
+			if (radeon_audio != 0 && ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
+				return ATOM_ENCODER_MODE_DP_AUDIO;
 			return ATOM_ENCODER_MODE_DP;
 		} else if (radeon_audio != 0) {
 			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
@@ -742,6 +747,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
 		}
 		break;
 	case DRM_MODE_CONNECTOR_eDP:
+		if (radeon_audio != 0 && ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
+			return ATOM_ENCODER_MODE_DP_AUDIO;
 		return ATOM_ENCODER_MODE_DP;
 	case DRM_MODE_CONNECTOR_DVIA:
 	case DRM_MODE_CONNECTOR_VGA:
@@ -1615,6 +1622,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
 	struct radeon_connector *radeon_connector = NULL;
 	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
 	bool travis_quirk = false;
+	int encoder_mode;
 
 	if (connector) {
 		radeon_connector = to_radeon_connector(connector);
@@ -1710,6 +1718,11 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
 		}
 		break;
 	}
+
+	encoder_mode = atombios_get_encoder_mode(encoder);
+	if (radeon_audio != 0 &&
+		(encoder_mode == ATOM_ENCODER_MODE_HDMI || ENCODER_MODE_IS_DP(encoder_mode)))
+		radeon_audio_dpms(encoder, mode);
 }
 
 static void
@@ -2123,6 +2136,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	int encoder_mode;
 
 	radeon_encoder->pixel_clock = adjusted_mode->clock;
 
@@ -2149,6 +2163,10 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
 		/* handled in dpms */
+		encoder_mode = atombios_get_encoder_mode(encoder);
+		if (radeon_audio != 0 &&
+			(encoder_mode == ATOM_ENCODER_MODE_HDMI || ENCODER_MODE_IS_DP(encoder_mode)))
+			radeon_audio_mode_set(encoder, adjusted_mode);
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
@@ -2170,13 +2188,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
 	}
 
 	atombios_apply_encoder_quirks(encoder, adjusted_mode);
-
-	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
-		if (rdev->asic->display.hdmi_enable)
-			radeon_hdmi_enable(rdev, encoder, true);
-		if (rdev->asic->display.hdmi_setmode)
-			radeon_hdmi_setmode(rdev, encoder, adjusted_mode);
-	}
 }
 
 static bool
@@ -2442,10 +2453,6 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
 
 disable_done:
 	if (radeon_encoder_is_digital(encoder)) {
-		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
-			if (rdev->asic->display.hdmi_enable)
-				radeon_hdmi_enable(rdev, encoder, false);
-		}
 		dig = radeon_encoder->enc_priv;
 		dig->dig_encoder = -1;
 	}

+ 2 - 0
drivers/gpu/drm/radeon/btc_dpm.c

@@ -2277,6 +2277,7 @@ static void btc_update_requested_ps(struct radeon_device *rdev,
 	eg_pi->requested_rps.ps_priv = &eg_pi->requested_ps;
 }
 
+#if 0
 void btc_dpm_reset_asic(struct radeon_device *rdev)
 {
 	rv770_restrict_performance_levels_before_switch(rdev);
@@ -2284,6 +2285,7 @@ void btc_dpm_reset_asic(struct radeon_device *rdev)
 	btc_set_boot_state_timing(rdev);
 	rv770_set_boot_state(rdev);
 }
+#endif
 
 int btc_dpm_pre_set_power_state(struct radeon_device *rdev)
 {

+ 47 - 10
drivers/gpu/drm/radeon/ci_dpm.c

@@ -187,6 +187,9 @@ static int ci_update_uvd_dpm(struct radeon_device *rdev, bool gate);
 static PPSMC_Result ci_send_msg_to_smc_with_parameter(struct radeon_device *rdev,
 						      PPSMC_Msg msg, u32 parameter);
 
+static void ci_thermal_start_smc_fan_control(struct radeon_device *rdev);
+static void ci_fan_ctrl_set_default_mode(struct radeon_device *rdev);
+
 static struct ci_power_info *ci_get_pi(struct radeon_device *rdev)
 {
         struct ci_power_info *pi = rdev->pm.dpm.priv;
@@ -1043,22 +1046,24 @@ static int ci_fan_ctrl_start_smc_fan_control(struct radeon_device *rdev)
 			return -EINVAL;
 	}
 
+	pi->fan_is_controlled_by_smc = true;
 	return 0;
 }
 
-#if 0
 static int ci_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev)
 {
 	PPSMC_Result ret;
+	struct ci_power_info *pi = ci_get_pi(rdev);
 
 	ret = ci_send_msg_to_smc(rdev, PPSMC_StopFanControl);
-	if (ret == PPSMC_Result_OK)
+	if (ret == PPSMC_Result_OK) {
+		pi->fan_is_controlled_by_smc = false;
 		return 0;
-	else
+	} else
 		return -EINVAL;
 }
 
-static int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
+int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
 					     u32 *speed)
 {
 	u32 duty, duty100;
@@ -1083,21 +1088,22 @@ static int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
 	return 0;
 }
 
-static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
+int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
 					     u32 speed)
 {
 	u32 tmp;
 	u32 duty, duty100;
 	u64 tmp64;
+	struct ci_power_info *pi = ci_get_pi(rdev);
 
 	if (rdev->pm.no_fan)
 		return -ENOENT;
 
-	if (speed > 100)
+	if (pi->fan_is_controlled_by_smc)
 		return -EINVAL;
 
-	if (rdev->pm.dpm.fan.ucode_fan_control)
-		ci_fan_ctrl_stop_smc_fan_control(rdev);
+	if (speed > 100)
+		return -EINVAL;
 
 	duty100 = (RREG32_SMC(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT;
 
@@ -1112,11 +1118,38 @@ static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
 	tmp |= FDO_STATIC_DUTY(duty);
 	WREG32_SMC(CG_FDO_CTRL0, tmp);
 
-	ci_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC);
-
 	return 0;
 }
 
+void ci_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode)
+{
+	if (mode) {
+		/* stop auto-manage */
+		if (rdev->pm.dpm.fan.ucode_fan_control)
+			ci_fan_ctrl_stop_smc_fan_control(rdev);
+		ci_fan_ctrl_set_static_mode(rdev, mode);
+	} else {
+		/* restart auto-manage */
+		if (rdev->pm.dpm.fan.ucode_fan_control)
+			ci_thermal_start_smc_fan_control(rdev);
+		else
+			ci_fan_ctrl_set_default_mode(rdev);
+	}
+}
+
+u32 ci_fan_ctrl_get_mode(struct radeon_device *rdev)
+{
+	struct ci_power_info *pi = ci_get_pi(rdev);
+	u32 tmp;
+
+	if (pi->fan_is_controlled_by_smc)
+		return 0;
+
+	tmp = RREG32_SMC(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK;
+	return (tmp >> FDO_PWM_MODE_SHIFT);
+}
+
+#if 0
 static int ci_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev,
 					 u32 *speed)
 {
@@ -1698,10 +1731,12 @@ static int ci_set_overdrive_target_tdp(struct radeon_device *rdev,
 	return 0;
 }
 
+#if 0
 static int ci_set_boot_state(struct radeon_device *rdev)
 {
 	return ci_enable_sclk_mclk_dpm(rdev, false);
 }
+#endif
 
 static u32 ci_get_average_sclk_freq(struct radeon_device *rdev)
 {
@@ -5343,10 +5378,12 @@ int ci_dpm_set_power_state(struct radeon_device *rdev)
 	return 0;
 }
 
+#if 0
 void ci_dpm_reset_asic(struct radeon_device *rdev)
 {
 	ci_set_boot_state(rdev);
 }
+#endif
 
 void ci_dpm_display_configuration_changed(struct radeon_device *rdev)
 {

+ 1 - 0
drivers/gpu/drm/radeon/ci_dpm.h

@@ -291,6 +291,7 @@ struct ci_power_info {
 	struct ci_ps requested_ps;
 	/* fan control */
 	bool fan_ctrl_is_in_default_mode;
+	bool fan_is_controlled_by_smc;
 	u32 t_min;
 	u32 fan_ctrl_default_mode;
 };

+ 2 - 0
drivers/gpu/drm/radeon/ci_smc.c

@@ -184,6 +184,7 @@ PPSMC_Result ci_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg)
 	return (PPSMC_Result)tmp;
 }
 
+#if 0
 PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev)
 {
 	u32 tmp;
@@ -201,6 +202,7 @@ PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev)
 
 	return PPSMC_Result_OK;
 }
+#endif
 
 int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
 {

+ 3 - 2
drivers/gpu/drm/radeon/cik.c

@@ -27,6 +27,7 @@
 #include "drmP.h"
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include "cikd.h"
 #include "atom.h"
 #include "cik_blit_shaders.h"
@@ -8517,7 +8518,7 @@ static int cik_startup(struct radeon_device *rdev)
 		return r;
 	}
 
-	r = dce6_audio_init(rdev);
+	r = radeon_audio_init(rdev);
 	if (r)
 		return r;
 
@@ -8575,7 +8576,7 @@ int cik_suspend(struct radeon_device *rdev)
 {
 	radeon_kfd_suspend(rdev);
 	radeon_pm_suspend(rdev);
-	dce6_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	radeon_vm_manager_fini(rdev);
 	cik_cp_enable(rdev, false);
 	cik_sdma_enable(rdev, false);

+ 2 - 0
drivers/gpu/drm/radeon/cypress_dpm.c

@@ -2005,11 +2005,13 @@ int cypress_dpm_set_power_state(struct radeon_device *rdev)
 	return 0;
 }
 
+#if 0
 void cypress_dpm_reset_asic(struct radeon_device *rdev)
 {
 	rv770_restrict_performance_levels_before_switch(rdev);
 	rv770_set_boot_state(rdev);
 }
+#endif
 
 void cypress_dpm_display_configuration_changed(struct radeon_device *rdev)
 {

+ 126 - 138
drivers/gpu/drm/radeon/dce3_1_afmt.c

@@ -24,37 +24,17 @@
 #include <drm/drmP.h>
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include "r600d.h"
 
-static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
+void dce3_2_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
+	u8 *sadb, int sad_count)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
 	u32 tmp;
-	u8 *sadb = NULL;
-	int sad_count;
-
-	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return;
-	}
-
-	sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
-	if (sad_count < 0) {
-		DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
-		sad_count = 0;
-	}
 
 	/* program the speaker allocation */
-	tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
+	tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
 	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
 	/* set HDMI mode */
 	tmp |= HDMI_CONNECTION;
@@ -62,19 +42,32 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
 		tmp |= SPEAKER_ALLOCATION(sadb[0]);
 	else
 		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
-	WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
-
-	kfree(sadb);
+	WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
 }
 
-static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder)
+void dce3_2_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
+	u8 *sadb, int sad_count)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
-	struct cea_sad *sads;
-	int i, sad_count;
+	u32 tmp;
+
+	/* program the speaker allocation */
+	tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
+	tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK);
+	/* set DP mode */
+	tmp |= DP_CONNECTION;
+	if (sad_count)
+		tmp |= SPEAKER_ALLOCATION(sadb[0]);
+	else
+		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
+	WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
+}
 
+void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder,
+	struct cea_sad *sads, int sad_count)
+{
+	int i;
+	struct radeon_device *rdev = encoder->dev->dev_private;
 	static const u16 eld_reg_to_type[][2] = {
 		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
 		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
@@ -90,25 +83,6 @@ static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder)
 		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
 	};
 
-	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return;
-	}
-
-	sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
-	if (sad_count <= 0) {
-		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
-		return;
-	}
-	BUG_ON(!sads);
-
 	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
 		u32 value = 0;
 		u8 stereo_freqs = 0;
@@ -135,110 +109,124 @@ static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder)
 
 		value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
 
-		WREG32(eld_reg_to_type[i][0], value);
+		WREG32_ENDPOINT(0, eld_reg_to_type[i][0], value);
 	}
-
-	kfree(sads);
 }
 
-/*
- * update the info frames with the data from the current display mode
- */
-void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
+void dce3_2_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock)
 {
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
-	struct hdmi_avi_infoframe frame;
-	uint32_t offset;
-	ssize_t err;
-
-	if (!dig || !dig->afmt)
-		return;
-
-	/* Silent, r600_hdmi_enable will raise WARN for us */
-	if (!dig->afmt->enabled)
+	struct radeon_encoder *radeon_encoder;
+	struct radeon_encoder_atom_dig *dig;
+	unsigned int max_ratio = clock / 24000;
+	u32 dto_phase;
+	u32 wallclock_ratio;
+	u32 dto_cntl;
+
+	if (!crtc)
 		return;
-	offset = dig->afmt->offset;
-
-	/* disable audio prior to setting up hw */
-	dig->afmt->pin = r600_audio_get_pin(rdev);
-	r600_audio_enable(rdev, dig->afmt->pin, 0);
 
-	r600_audio_set_dto(encoder, mode->clock);
+	radeon_encoder = to_radeon_encoder(crtc->encoder);
+	dig = radeon_encoder->enc_priv;
 
-	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
-	       HDMI0_NULL_SEND); /* send null packets when required */
-
-	WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
+	if (!dig)
+		return;
 
-	if (ASIC_IS_DCE32(rdev)) {
-		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
-		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
-		       HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
-		WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
-		       AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
-		       AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
+	if (max_ratio >= 8) {
+		dto_phase = 192 * 1000;
+		wallclock_ratio = 3;
+	} else if (max_ratio >= 4) {
+		dto_phase = 96 * 1000;
+		wallclock_ratio = 2;
+	} else if (max_ratio >= 2) {
+		dto_phase = 48 * 1000;
+		wallclock_ratio = 1;
 	} else {
-		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
-		       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
-		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
-		       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
-		       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
+		dto_phase = 24 * 1000;
+		wallclock_ratio = 0;
 	}
 
-	if (ASIC_IS_DCE32(rdev)) {
-		dce3_2_afmt_write_speaker_allocation(encoder);
-		dce3_2_afmt_write_sad_regs(encoder);
+	/* Express [24MHz / target pixel clock] as an exact rational
+	 * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
+	 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
+	 */
+	if (dig->dig_encoder == 0) {
+		dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
+		dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
+		WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl);
+		WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase);
+		WREG32(DCCG_AUDIO_DTO0_MODULE, clock);
+		WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
+	} else {
+		dto_cntl = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
+		dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
+		WREG32(DCCG_AUDIO_DTO1_CNTL, dto_cntl);
+		WREG32(DCCG_AUDIO_DTO1_PHASE, dto_phase);
+		WREG32(DCCG_AUDIO_DTO1_MODULE, clock);
+		WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
 	}
+}
+
+void dce3_2_hdmi_update_acr(struct drm_encoder *encoder, long offset,
+	const struct radeon_hdmi_acr *acr)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
 
 	WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
-	       HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
-	       HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
-
-	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
-	       HDMI0_NULL_SEND | /* send null packets when required */
-	       HDMI0_GC_SEND | /* send general control packets */
-	       HDMI0_GC_CONT); /* send general control packets every frame */
-
-	/* TODO: HDMI0_AUDIO_INFO_UPDATE */
-	WREG32(HDMI0_INFOFRAME_CONTROL0 + offset,
-	       HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
-	       HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
-	       HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
-	       HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */
-
-	WREG32(HDMI0_INFOFRAME_CONTROL1 + offset,
-	       HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
-	       HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */
-
-	WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */
-
-	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
-	if (err < 0) {
-		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
-		return;
-	}
+		HDMI0_ACR_SOURCE |		/* select SW CTS value */
+		HDMI0_ACR_AUTO_SEND);	/* allow hw to sent ACR packets when required */
+
+	WREG32_P(HDMI0_ACR_32_0 + offset,
+		HDMI0_ACR_CTS_32(acr->cts_32khz),
+		~HDMI0_ACR_CTS_32_MASK);
+	WREG32_P(HDMI0_ACR_32_1 + offset,
+		HDMI0_ACR_N_32(acr->n_32khz),
+		~HDMI0_ACR_N_32_MASK);
+
+	WREG32_P(HDMI0_ACR_44_0 + offset,
+		HDMI0_ACR_CTS_44(acr->cts_44_1khz),
+		~HDMI0_ACR_CTS_44_MASK);
+	WREG32_P(HDMI0_ACR_44_1 + offset,
+		HDMI0_ACR_N_44(acr->n_44_1khz),
+		~HDMI0_ACR_N_44_MASK);
+
+	WREG32_P(HDMI0_ACR_48_0 + offset,
+		HDMI0_ACR_CTS_48(acr->cts_48khz),
+		~HDMI0_ACR_CTS_48_MASK);
+	WREG32_P(HDMI0_ACR_48_1 + offset,
+		HDMI0_ACR_N_48(acr->n_48khz),
+		~HDMI0_ACR_N_48_MASK);
+}
 
-	err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
-	if (err < 0) {
-		DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
-		return;
-	}
+void dce3_2_set_audio_packet(struct drm_encoder *encoder, u32 offset)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
 
-	r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
-	r600_hdmi_update_ACR(encoder, mode->clock);
+	WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
+		HDMI0_AUDIO_DELAY_EN(1) |			/* default audio delay */
+		HDMI0_AUDIO_PACKETS_PER_LINE(3));	/* should be suffient for all audio modes and small enough for all hblanks */
 
-	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
-	WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF);
-	WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF);
-	WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001);
-	WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
+	WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
+		AFMT_AUDIO_SAMPLE_SEND |			/* send audio packets */
+		AFMT_60958_CS_UPDATE);				/* allow 60958 channel status fields to be updated */
 
-	r600_hdmi_audio_workaround(encoder);
+	WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset,
+		HDMI0_AUDIO_INFO_SEND |				/* enable audio info frames (frames won't be set until audio is enabled) */
+		HDMI0_AUDIO_INFO_CONT);				/* send audio info frames every frame/field */
 
-	/* enable audio after to setting up hw */
-	r600_audio_enable(rdev, dig->afmt->pin, 0xf);
+	WREG32_OR(HDMI0_INFOFRAME_CONTROL1 + offset,
+		HDMI0_AUDIO_INFO_LINE(2));			/* anything other than 0 */
+}
+
+void dce3_2_set_mute(struct drm_encoder *encoder, u32 offset, bool mute)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (mute)
+		WREG32_OR(HDMI0_GC + offset, HDMI0_GC_AVMUTE);
+	else
+		WREG32_AND(HDMI0_GC + offset, ~HDMI0_GC_AVMUTE);
 }

+ 93 - 125
drivers/gpu/drm/radeon/dce6_afmt.c

@@ -23,9 +23,10 @@
 #include <linux/hdmi.h>
 #include <drm/drmP.h>
 #include "radeon.h"
+#include "radeon_audio.h"
 #include "sid.h"
 
-static u32 dce6_endpoint_rreg(struct radeon_device *rdev,
+u32 dce6_endpoint_rreg(struct radeon_device *rdev,
 			      u32 block_offset, u32 reg)
 {
 	unsigned long flags;
@@ -39,7 +40,7 @@ static u32 dce6_endpoint_rreg(struct radeon_device *rdev,
 	return r;
 }
 
-static void dce6_endpoint_wreg(struct radeon_device *rdev,
+void dce6_endpoint_wreg(struct radeon_device *rdev,
 			       u32 block_offset, u32 reg, u32 v)
 {
 	unsigned long flags;
@@ -54,10 +55,6 @@ static void dce6_endpoint_wreg(struct radeon_device *rdev,
 	spin_unlock_irqrestore(&rdev->end_idx_lock, flags);
 }
 
-#define RREG32_ENDPOINT(block, reg) dce6_endpoint_rreg(rdev, (block), (reg))
-#define WREG32_ENDPOINT(block, reg, v) dce6_endpoint_wreg(rdev, (block), (reg), (v))
-
-
 static void dce6_afmt_get_connected_pins(struct radeon_device *rdev)
 {
 	int i;
@@ -105,13 +102,11 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder)
 }
 
 void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
-				    struct drm_display_mode *mode)
+		struct drm_connector *connector, struct drm_display_mode *mode)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
 	u32 tmp = 0, offset;
 
 	if (!dig || !dig->afmt || !dig->afmt->pin)
@@ -119,18 +114,6 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
 
 	offset = dig->afmt->pin->offset;
 
-	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return;
-	}
-
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
 		if (connector->latency_present[1])
 			tmp = VIDEO_LIPSYNC(connector->video_latency[1]) |
@@ -147,40 +130,19 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
 	WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp);
 }
 
-void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
+void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
+	u8 *sadb, int sad_count)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
 	u32 offset, tmp;
-	u8 *sadb = NULL;
-	int sad_count;
 
 	if (!dig || !dig->afmt || !dig->afmt->pin)
 		return;
 
 	offset = dig->afmt->pin->offset;
 
-	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return;
-	}
-
-	sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb);
-	if (sad_count < 0) {
-		DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
-		sad_count = 0;
-	}
-
 	/* program the speaker allocation */
 	tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
 	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
@@ -191,21 +153,41 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
 	else
 		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
 	WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
-
-	kfree(sadb);
 }
 
-void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
+void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
+	u8 *sadb, int sad_count)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	u32 offset;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
-	struct cea_sad *sads;
-	int i, sad_count;
+	u32 offset, tmp;
+
+	if (!dig || !dig->afmt || !dig->afmt->pin)
+		return;
 
+	offset = dig->afmt->pin->offset;
+
+	/* program the speaker allocation */
+	tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
+	tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK);
+	/* set DP mode */
+	tmp |= DP_CONNECTION;
+	if (sad_count)
+		tmp |= SPEAKER_ALLOCATION(sadb[0]);
+	else
+		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
+	WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
+}
+
+void dce6_afmt_write_sad_regs(struct drm_encoder *encoder,
+	struct cea_sad *sads, int sad_count)
+{
+	u32 offset;
+	int i;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	struct radeon_device *rdev = encoder->dev->dev_private;
 	static const u16 eld_reg_to_type[][2] = {
 		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
 		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
@@ -226,25 +208,6 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
 
 	offset = dig->afmt->pin->offset;
 
-	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return;
-	}
-
-	sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
-	if (sad_count <= 0) {
-		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
-		return;
-	}
-	BUG_ON(!sads);
-
 	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
 		u32 value = 0;
 		u8 stereo_freqs = 0;
@@ -273,13 +236,6 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
 
 		WREG32_ENDPOINT(offset, eld_reg_to_type[i][0], value);
 	}
-
-	kfree(sads);
-}
-
-static int dce6_audio_chipset_supported(struct radeon_device *rdev)
-{
-	return !ASIC_IS_NODCE(rdev);
 }
 
 void dce6_audio_enable(struct radeon_device *rdev,
@@ -293,64 +249,76 @@ void dce6_audio_enable(struct radeon_device *rdev,
 			enable_mask ? AUDIO_ENABLED : 0);
 }
 
-static const u32 pin_offsets[7] =
-{
-	(0x5e00 - 0x5e00),
-	(0x5e18 - 0x5e00),
-	(0x5e30 - 0x5e00),
-	(0x5e48 - 0x5e00),
-	(0x5e60 - 0x5e00),
-	(0x5e78 - 0x5e00),
-	(0x5e90 - 0x5e00),
-};
-
-int dce6_audio_init(struct radeon_device *rdev)
+void dce6_hdmi_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock)
 {
-	int i;
+    /* Two dtos; generally use dto0 for HDMI */
+	u32 value = 0;
 
-	if (!radeon_audio || !dce6_audio_chipset_supported(rdev))
-		return 0;
+    if (crtc)
+		value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id);
 
-	rdev->audio.enabled = true;
+	WREG32(DCCG_AUDIO_DTO_SOURCE, value);
 
-	if (ASIC_IS_DCE81(rdev)) /* KV: 4 streams, 7 endpoints */
-		rdev->audio.num_pins = 7;
-	else if (ASIC_IS_DCE83(rdev)) /* KB: 2 streams, 3 endpoints */
-		rdev->audio.num_pins = 3;
-	else if (ASIC_IS_DCE8(rdev)) /* BN/HW: 6 streams, 7 endpoints */
-		rdev->audio.num_pins = 7;
-	else if (ASIC_IS_DCE61(rdev)) /* TN: 4 streams, 6 endpoints */
-		rdev->audio.num_pins = 6;
-	else if (ASIC_IS_DCE64(rdev)) /* OL: 2 streams, 2 endpoints */
-		rdev->audio.num_pins = 2;
-	else /* SI: 6 streams, 6 endpoints */
-		rdev->audio.num_pins = 6;
+    /* Express [24MHz / target pixel clock] as an exact rational
+     * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
+     * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
+     */
+    WREG32(DCCG_AUDIO_DTO0_PHASE, 24000);
+    WREG32(DCCG_AUDIO_DTO0_MODULE, clock);
+}
 
-	for (i = 0; i < rdev->audio.num_pins; i++) {
-		rdev->audio.pin[i].channels = -1;
-		rdev->audio.pin[i].rate = -1;
-		rdev->audio.pin[i].bits_per_sample = -1;
-		rdev->audio.pin[i].status_bits = 0;
-		rdev->audio.pin[i].category_code = 0;
-		rdev->audio.pin[i].connected = false;
-		rdev->audio.pin[i].offset = pin_offsets[i];
-		rdev->audio.pin[i].id = i;
-		/* disable audio.  it will be set up later */
-		dce6_audio_enable(rdev, &rdev->audio.pin[i], false);
-	}
+void dce6_dp_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock)
+{
+    /* Two dtos; generally use dto1 for DP */
+	u32 value = 0;
+	value |= DCCG_AUDIO_DTO_SEL;
+
+    if (crtc)
+		value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id);
+
+	WREG32(DCCG_AUDIO_DTO_SOURCE, value);
 
-	return 0;
+    /* Express [24MHz / target pixel clock] as an exact rational
+     * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
+     * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
+     */
+    WREG32(DCCG_AUDIO_DTO1_PHASE, 24000);
+    WREG32(DCCG_AUDIO_DTO1_MODULE, clock);
 }
 
-void dce6_audio_fini(struct radeon_device *rdev)
+void dce6_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable)
 {
-	int i;
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	uint32_t offset;
 
-	if (!rdev->audio.enabled)
+	if (!dig || !dig->afmt)
 		return;
 
-	for (i = 0; i < rdev->audio.num_pins; i++)
-		dce6_audio_enable(rdev, &rdev->audio.pin[i], false);
+	offset = dig->afmt->offset;
+
+	if (enable) {
+        if (dig->afmt->enabled)
+            return;
+
+		WREG32(EVERGREEN_DP_SEC_TIMESTAMP + offset, EVERGREEN_DP_SEC_TIMESTAMP_MODE(1));
+		WREG32(EVERGREEN_DP_SEC_CNTL + offset,
+			EVERGREEN_DP_SEC_ASP_ENABLE |		/* Audio packet transmission */
+			EVERGREEN_DP_SEC_ATP_ENABLE |		/* Audio timestamp packet transmission */
+			EVERGREEN_DP_SEC_AIP_ENABLE |		/* Audio infoframe packet transmission */
+			EVERGREEN_DP_SEC_STREAM_ENABLE);	/* Master enable for secondary stream engine */
+		radeon_audio_enable(rdev, dig->afmt->pin, true);
+	} else {
+		if (!dig->afmt->enabled)
+			return;
+
+		WREG32(EVERGREEN_DP_SEC_CNTL + offset, 0);
+		radeon_audio_enable(rdev, dig->afmt->pin, false);
+	}
 
-	rdev->audio.enabled = false;
+	dig->afmt->enabled = enable;
 }

+ 4 - 3
drivers/gpu/drm/radeon/evergreen.c

@@ -26,6 +26,7 @@
 #include <drm/drmP.h>
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include <drm/radeon_drm.h>
 #include "evergreend.h"
 #include "atom.h"
@@ -5286,7 +5287,7 @@ static int evergreen_startup(struct radeon_device *rdev)
 		return r;
 	}
 
-	r = r600_audio_init(rdev);
+	r = radeon_audio_init(rdev);
 	if (r) {
 		DRM_ERROR("radeon: audio init failed\n");
 		return r;
@@ -5332,7 +5333,7 @@ int evergreen_resume(struct radeon_device *rdev)
 int evergreen_suspend(struct radeon_device *rdev)
 {
 	radeon_pm_suspend(rdev);
-	r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	uvd_v1_0_fini(rdev);
 	radeon_uvd_suspend(rdev);
 	r700_cp_stop(rdev);
@@ -5482,7 +5483,7 @@ int evergreen_init(struct radeon_device *rdev)
 void evergreen_fini(struct radeon_device *rdev)
 {
 	radeon_pm_fini(rdev);
-	r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	r700_cp_fini(rdev);
 	r600_dma_fini(rdev);
 	r600_irq_fini(rdev);

+ 76 - 0
drivers/gpu/drm/radeon/evergreen_cs.c

@@ -83,6 +83,7 @@ struct evergreen_cs_track {
 	u32			htile_offset;
 	u32			htile_surface;
 	struct radeon_bo	*htile_bo;
+	unsigned long		indirect_draw_buffer_size;
 };
 
 static u32 evergreen_cs_get_aray_mode(u32 tiling_flags)
@@ -1896,6 +1897,14 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
 		}
 		break;
 	}
+	case PACKET3_INDEX_BUFFER_SIZE:
+	{
+		if (pkt->count != 0) {
+			DRM_ERROR("bad INDEX_BUFFER_SIZE\n");
+			return -EINVAL;
+		}
+		break;
+	}
 	case PACKET3_DRAW_INDEX:
 	{
 		uint64_t offset;
@@ -2006,6 +2015,67 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
 			return r;
 		}
 		break;
+	case PACKET3_SET_BASE:
+	{
+		/*
+		DW 1 HEADER Header of the packet. Shader_Type in bit 1 of the Header will correspond to the shader type of the Load, see Type-3 Packet.
+		   2 BASE_INDEX Bits [3:0] BASE_INDEX - Base Index specifies which base address is specified in the last two DWs.
+		     0001: DX11 Draw_Index_Indirect Patch Table Base: Base address for Draw_Index_Indirect data.
+		   3 ADDRESS_LO Bits [31:3] - Lower bits of QWORD-Aligned Address. Bits [2:0] - Reserved
+		   4 ADDRESS_HI Bits [31:8] - Reserved. Bits [7:0] - Upper bits of Address [47:32]
+		*/
+		if (pkt->count != 2) {
+			DRM_ERROR("bad SET_BASE\n");
+			return -EINVAL;
+		}
+
+		/* currently only supporting setting indirect draw buffer base address */
+		if (idx_value != 1) {
+			DRM_ERROR("bad SET_BASE\n");
+			return -EINVAL;
+		}
+
+		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
+		if (r) {
+			DRM_ERROR("bad SET_BASE\n");
+			return -EINVAL;
+		}
+
+		track->indirect_draw_buffer_size = radeon_bo_size(reloc->robj);
+
+		ib[idx+1] = reloc->gpu_offset;
+		ib[idx+2] = upper_32_bits(reloc->gpu_offset) & 0xff;
+
+		break;
+	}
+	case PACKET3_DRAW_INDIRECT:
+	case PACKET3_DRAW_INDEX_INDIRECT:
+	{
+		u64 size = pkt->opcode == PACKET3_DRAW_INDIRECT ? 16 : 20;
+
+		/*
+		DW 1 HEADER
+		   2 DATA_OFFSET Bits [31:0] + byte aligned offset where the required data structure starts. Bits 1:0 are zero
+		   3 DRAW_INITIATOR Draw Initiator Register. Written to the VGT_DRAW_INITIATOR register for the assigned context
+		*/
+		if (pkt->count != 1) {
+			DRM_ERROR("bad DRAW_INDIRECT\n");
+			return -EINVAL;
+		}
+
+		if (idx_value + size > track->indirect_draw_buffer_size) {
+			dev_warn(p->dev, "DRAW_INDIRECT buffer too small %u + %llu > %lu\n",
+				idx_value, size, track->indirect_draw_buffer_size);
+			return -EINVAL;
+		}
+
+		r = evergreen_cs_track_check(p);
+		if (r) {
+			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+			return r;
+		}
+		break;
+	}
 	case PACKET3_DISPATCH_DIRECT:
 		if (pkt->count != 3) {
 			DRM_ERROR("bad DISPATCH_DIRECT\n");
@@ -3243,7 +3313,13 @@ static int evergreen_vm_packet3_check(struct radeon_device *rdev,
 
 	switch (pkt->opcode) {
 	case PACKET3_NOP:
+		break;
 	case PACKET3_SET_BASE:
+		if (idx_value != 1) {
+			DRM_ERROR("bad SET_BASE");
+			return -EINVAL;
+		}
+		break;
 	case PACKET3_CLEAR_STATE:
 	case PACKET3_INDEX_BUFFER_SIZE:
 	case PACKET3_DISPATCH_DIRECT:

+ 214 - 264
drivers/gpu/drm/radeon/evergreen_hdmi.c

@@ -29,17 +29,12 @@
 #include <drm/radeon_drm.h>
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include "evergreend.h"
 #include "atom.h"
 
-extern void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder);
-extern void dce6_afmt_write_sad_regs(struct drm_encoder *encoder);
-extern void dce6_afmt_select_pin(struct drm_encoder *encoder);
-extern void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
-					   struct drm_display_mode *mode);
-
 /* enable the audio stream */
-static void dce4_audio_enable(struct radeon_device *rdev,
+void dce4_audio_enable(struct radeon_device *rdev,
 			      struct r600_audio_pin *pin,
 			      u8 enable_mask)
 {
@@ -69,48 +64,42 @@ static void dce4_audio_enable(struct radeon_device *rdev,
 	WREG32(AZ_HOT_PLUG_CONTROL, tmp);
 }
 
-/*
- * update the N and CTS parameters for a given pixel clock rate
- */
-static void evergreen_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
+void evergreen_hdmi_update_acr(struct drm_encoder *encoder, long offset,
+	const struct radeon_hdmi_acr *acr)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_hdmi_acr acr = r600_hdmi_acr(clock);
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	uint32_t offset = dig->afmt->offset;
+	int bpc = 8;
 
-	WREG32(HDMI_ACR_32_0 + offset, HDMI_ACR_CTS_32(acr.cts_32khz));
-	WREG32(HDMI_ACR_32_1 + offset, acr.n_32khz);
+	if (encoder->crtc) {
+		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+		bpc = radeon_crtc->bpc;
+	}
 
-	WREG32(HDMI_ACR_44_0 + offset, HDMI_ACR_CTS_44(acr.cts_44_1khz));
-	WREG32(HDMI_ACR_44_1 + offset, acr.n_44_1khz);
+	if (bpc > 8)
+		WREG32(HDMI_ACR_PACKET_CONTROL + offset,
+			HDMI_ACR_AUTO_SEND);	/* allow hw to sent ACR packets when required */
+	else
+		WREG32(HDMI_ACR_PACKET_CONTROL + offset,
+			HDMI_ACR_SOURCE |		/* select SW CTS value */
+			HDMI_ACR_AUTO_SEND);	/* allow hw to sent ACR packets when required */
+
+	WREG32(HDMI_ACR_32_0 + offset, HDMI_ACR_CTS_32(acr->cts_32khz));
+	WREG32(HDMI_ACR_32_1 + offset, acr->n_32khz);
 
-	WREG32(HDMI_ACR_48_0 + offset, HDMI_ACR_CTS_48(acr.cts_48khz));
-	WREG32(HDMI_ACR_48_1 + offset, acr.n_48khz);
+	WREG32(HDMI_ACR_44_0 + offset, HDMI_ACR_CTS_44(acr->cts_44_1khz));
+	WREG32(HDMI_ACR_44_1 + offset, acr->n_44_1khz);
+
+	WREG32(HDMI_ACR_48_0 + offset, HDMI_ACR_CTS_48(acr->cts_48khz));
+	WREG32(HDMI_ACR_48_1 + offset, acr->n_48khz);
 }
 
-static void dce4_afmt_write_latency_fields(struct drm_encoder *encoder,
-					   struct drm_display_mode *mode)
+void dce4_afmt_write_latency_fields(struct drm_encoder *encoder,
+		struct drm_connector *connector, struct drm_display_mode *mode)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
 	u32 tmp = 0;
 
-	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return;
-	}
-
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
 		if (connector->latency_present[1])
 			tmp = VIDEO_LIPSYNC(connector->video_latency[1]) |
@@ -124,38 +113,17 @@ static void dce4_afmt_write_latency_fields(struct drm_encoder *encoder,
 		else
 			tmp = VIDEO_LIPSYNC(255) | AUDIO_LIPSYNC(255);
 	}
-	WREG32(AZ_F0_CODEC_PIN0_CONTROL_RESPONSE_LIPSYNC, tmp);
+	WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_RESPONSE_LIPSYNC, tmp);
 }
 
-static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
+void dce4_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
+	u8 *sadb, int sad_count)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
 	u32 tmp;
-	u8 *sadb = NULL;
-	int sad_count;
-
-	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return;
-	}
-
-	sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb);
-	if (sad_count < 0) {
-		DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
-		sad_count = 0;
-	}
 
 	/* program the speaker allocation */
-	tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
+	tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
 	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
 	/* set HDMI mode */
 	tmp |= HDMI_CONNECTION;
@@ -163,19 +131,32 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
 		tmp |= SPEAKER_ALLOCATION(sadb[0]);
 	else
 		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
-	WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
-
-	kfree(sadb);
+	WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
 }
 
-static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder)
+void dce4_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
+	u8 *sadb, int sad_count)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
-	struct cea_sad *sads;
-	int i, sad_count;
+	u32 tmp;
 
+	/* program the speaker allocation */
+	tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
+	tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK);
+	/* set DP mode */
+	tmp |= DP_CONNECTION;
+	if (sad_count)
+		tmp |= SPEAKER_ALLOCATION(sadb[0]);
+	else
+		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
+	WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
+}
+
+void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder,
+	struct cea_sad *sads, int sad_count)
+{
+	int i;
+	struct radeon_device *rdev = encoder->dev->dev_private;
 	static const u16 eld_reg_to_type[][2] = {
 		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
 		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
@@ -191,25 +172,6 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder)
 		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
 	};
 
-	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
-		if (connector->encoder == encoder) {
-			radeon_connector = to_radeon_connector(connector);
-			break;
-		}
-	}
-
-	if (!radeon_connector) {
-		DRM_ERROR("Couldn't find encoder's connector\n");
-		return;
-	}
-
-	sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
-	if (sad_count <= 0) {
-		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
-		return;
-	}
-	BUG_ON(!sads);
-
 	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
 		u32 value = 0;
 		u8 stereo_freqs = 0;
@@ -236,25 +198,17 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder)
 
 		value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
 
-		WREG32(eld_reg_to_type[i][0], value);
+		WREG32_ENDPOINT(0, eld_reg_to_type[i][0], value);
 	}
-
-	kfree(sads);
 }
 
 /*
- * build a HDMI Video Info Frame
+ * build a AVI Info Frame
  */
-static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
-						void *buffer, size_t size)
+void evergreen_set_avi_packet(struct radeon_device *rdev, u32 offset,
+    unsigned char *buffer, size_t size)
 {
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	uint32_t offset = dig->afmt->offset;
 	uint8_t *frame = buffer + 3;
-	uint8_t *header = buffer;
 
 	WREG32(AFMT_AVI_INFO0 + offset,
 		frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
@@ -263,104 +217,103 @@ static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
 	WREG32(AFMT_AVI_INFO2 + offset,
 		frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
 	WREG32(AFMT_AVI_INFO3 + offset,
-		frame[0xC] | (frame[0xD] << 8) | (header[1] << 24));
+		frame[0xC] | (frame[0xD] << 8) | (buffer[1] << 24));
+
+	WREG32_OR(HDMI_INFOFRAME_CONTROL0 + offset,
+		HDMI_AVI_INFO_SEND |	/* enable AVI info frames */
+		HDMI_AVI_INFO_CONT);	/* required for audio info values to be updated */
+
+	WREG32_P(HDMI_INFOFRAME_CONTROL1 + offset,
+		HDMI_AVI_INFO_LINE(2),	/* anything other than 0 */
+		~HDMI_AVI_INFO_LINE_MASK);
 }
 
-static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock)
+void dce4_hdmi_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock)
 {
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-	u32 base_rate = 24000;
-	u32 max_ratio = clock / base_rate;
+	unsigned int max_ratio = clock / 24000;
 	u32 dto_phase;
-	u32 dto_modulo = clock;
 	u32 wallclock_ratio;
-	u32 dto_cntl;
-
-	if (!dig || !dig->afmt)
-		return;
-
-	if (ASIC_IS_DCE6(rdev)) {
-		dto_phase = 24 * 1000;
+	u32 value;
+
+	if (max_ratio >= 8) {
+		dto_phase = 192 * 1000;
+		wallclock_ratio = 3;
+	} else if (max_ratio >= 4) {
+		dto_phase = 96 * 1000;
+		wallclock_ratio = 2;
+	} else if (max_ratio >= 2) {
+		dto_phase = 48 * 1000;
+		wallclock_ratio = 1;
 	} else {
-		if (max_ratio >= 8) {
-			dto_phase = 192 * 1000;
-			wallclock_ratio = 3;
-		} else if (max_ratio >= 4) {
-			dto_phase = 96 * 1000;
-			wallclock_ratio = 2;
-		} else if (max_ratio >= 2) {
-			dto_phase = 48 * 1000;
-			wallclock_ratio = 1;
-		} else {
-			dto_phase = 24 * 1000;
-			wallclock_ratio = 0;
-		}
-		dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
-		dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
-		WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl);
+		dto_phase = 24 * 1000;
+		wallclock_ratio = 0;
 	}
 
-	/* XXX two dtos; generally use dto0 for hdmi */
+	value = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
+	value |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
+	value &= ~DCCG_AUDIO_DTO1_USE_512FBR_DTO;
+	WREG32(DCCG_AUDIO_DTO0_CNTL, value);
+
+	/* Two dtos; generally use dto0 for HDMI */
+	value = 0;
+
+	if (crtc)
+		value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id);
+
+	WREG32(DCCG_AUDIO_DTO_SOURCE, value);
+
 	/* Express [24MHz / target pixel clock] as an exact rational
 	 * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
 	 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
 	 */
-	WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id));
 	WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase);
-	WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo);
+	WREG32(DCCG_AUDIO_DTO0_MODULE, clock);
 }
 
-
-/*
- * update the info frames with the data from the current display mode
- */
-void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
+void dce4_dp_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock)
 {
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
-	struct hdmi_avi_infoframe frame;
-	uint32_t offset;
-	ssize_t err;
-	uint32_t val;
-	int bpc = 8;
+	u32 value;
 
-	if (!dig || !dig->afmt)
-		return;
+	value = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
+	value |= DCCG_AUDIO_DTO1_USE_512FBR_DTO;
+	WREG32(DCCG_AUDIO_DTO1_CNTL, value);
 
-	/* Silent, r600_hdmi_enable will raise WARN for us */
-	if (!dig->afmt->enabled)
-		return;
-	offset = dig->afmt->offset;
+	/* Two dtos; generally use dto1 for DP */
+	value = 0;
+	value |= DCCG_AUDIO_DTO_SEL;
 
-	/* hdmi deep color mode general control packets setup, if bpc > 8 */
-	if (encoder->crtc) {
-		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-		bpc = radeon_crtc->bpc;
-	}
+	if (crtc)
+		value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id);
 
-	/* disable audio prior to setting up hw */
-	if (ASIC_IS_DCE6(rdev)) {
-		dig->afmt->pin = dce6_audio_get_pin(rdev);
-		dce6_audio_enable(rdev, dig->afmt->pin, 0);
-	} else {
-		dig->afmt->pin = r600_audio_get_pin(rdev);
-		dce4_audio_enable(rdev, dig->afmt->pin, 0);
-	}
+	WREG32(DCCG_AUDIO_DTO_SOURCE, value);
+
+	/* Express [24MHz / target pixel clock] as an exact rational
+	 * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
+	 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
+	 */
+	WREG32(DCCG_AUDIO_DTO1_PHASE, 24000);
+	WREG32(DCCG_AUDIO_DTO1_MODULE, rdev->clock.max_pixel_clock * 10);
+}
 
-	evergreen_audio_set_dto(encoder, mode->clock);
+void dce4_set_vbi_packet(struct drm_encoder *encoder, u32 offset)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
 
 	WREG32(HDMI_VBI_PACKET_CONTROL + offset,
-	       HDMI_NULL_SEND); /* send null packets when required */
+		HDMI_NULL_SEND |	/* send null packets when required */
+		HDMI_GC_SEND |		/* send general control packets */
+		HDMI_GC_CONT);		/* send general control packets every frame */
+}
 
-	WREG32(AFMT_AUDIO_CRC_CONTROL + offset, 0x1000);
+void dce4_hdmi_set_color_depth(struct drm_encoder *encoder, u32 offset, int bpc)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+	uint32_t val;
 
 	val = RREG32(HDMI_CONTROL + offset);
 	val &= ~HDMI_DEEP_COLOR_ENABLE;
@@ -390,113 +343,59 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
 	}
 
 	WREG32(HDMI_CONTROL + offset, val);
+}
 
-	WREG32(HDMI_VBI_PACKET_CONTROL + offset,
-	       HDMI_NULL_SEND | /* send null packets when required */
-	       HDMI_GC_SEND | /* send general control packets */
-	       HDMI_GC_CONT); /* send general control packets every frame */
+void dce4_set_audio_packet(struct drm_encoder *encoder, u32 offset)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
 
 	WREG32(HDMI_INFOFRAME_CONTROL0 + offset,
-	       HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
-	       HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */
+		HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
+		HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */
 
 	WREG32(AFMT_INFOFRAME_CONTROL0 + offset,
-	       AFMT_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */
+		AFMT_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */
 
 	WREG32(HDMI_INFOFRAME_CONTROL1 + offset,
-	       HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */
-
-	WREG32(HDMI_GC + offset, 0); /* unset HDMI_GC_AVMUTE */
+		HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */
 
 	WREG32(HDMI_AUDIO_PACKET_CONTROL + offset,
-	       HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */
-	       HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
-
-	WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
-	       AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
-
-	/* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */
-
-	if (bpc > 8)
-		WREG32(HDMI_ACR_PACKET_CONTROL + offset,
-		       HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
-	else
-		WREG32(HDMI_ACR_PACKET_CONTROL + offset,
-		       HDMI_ACR_SOURCE | /* select SW CTS value */
-		       HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
-
-	evergreen_hdmi_update_ACR(encoder, mode->clock);
+		HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */
+		HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
 
 	WREG32(AFMT_60958_0 + offset,
-	       AFMT_60958_CS_CHANNEL_NUMBER_L(1));
+		AFMT_60958_CS_CHANNEL_NUMBER_L(1));
 
 	WREG32(AFMT_60958_1 + offset,
-	       AFMT_60958_CS_CHANNEL_NUMBER_R(2));
+		AFMT_60958_CS_CHANNEL_NUMBER_R(2));
 
 	WREG32(AFMT_60958_2 + offset,
-	       AFMT_60958_CS_CHANNEL_NUMBER_2(3) |
-	       AFMT_60958_CS_CHANNEL_NUMBER_3(4) |
-	       AFMT_60958_CS_CHANNEL_NUMBER_4(5) |
-	       AFMT_60958_CS_CHANNEL_NUMBER_5(6) |
-	       AFMT_60958_CS_CHANNEL_NUMBER_6(7) |
-	       AFMT_60958_CS_CHANNEL_NUMBER_7(8));
-
-	if (ASIC_IS_DCE6(rdev)) {
-		dce6_afmt_write_speaker_allocation(encoder);
-	} else {
-		dce4_afmt_write_speaker_allocation(encoder);
-	}
+		AFMT_60958_CS_CHANNEL_NUMBER_2(3) |
+		AFMT_60958_CS_CHANNEL_NUMBER_3(4) |
+		AFMT_60958_CS_CHANNEL_NUMBER_4(5) |
+		AFMT_60958_CS_CHANNEL_NUMBER_5(6) |
+		AFMT_60958_CS_CHANNEL_NUMBER_6(7) |
+		AFMT_60958_CS_CHANNEL_NUMBER_7(8));
 
 	WREG32(AFMT_AUDIO_PACKET_CONTROL2 + offset,
-	       AFMT_AUDIO_CHANNEL_ENABLE(0xff));
-
-	/* fglrx sets 0x40 in 0x5f80 here */
-
-	if (ASIC_IS_DCE6(rdev)) {
-		dce6_afmt_select_pin(encoder);
-		dce6_afmt_write_sad_regs(encoder);
-		dce6_afmt_write_latency_fields(encoder, mode);
-	} else {
-		evergreen_hdmi_write_sad_regs(encoder);
-		dce4_afmt_write_latency_fields(encoder, mode);
-	}
-
-	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
-	if (err < 0) {
-		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
-		return;
-	}
-
-	err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
-	if (err < 0) {
-		DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
-		return;
-	}
-
-	evergreen_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
-
-	WREG32_OR(HDMI_INFOFRAME_CONTROL0 + offset,
-		  HDMI_AVI_INFO_SEND | /* enable AVI info frames */
-		  HDMI_AVI_INFO_CONT); /* required for audio info values to be updated */
+		AFMT_AUDIO_CHANNEL_ENABLE(0xff));
 
-	WREG32_P(HDMI_INFOFRAME_CONTROL1 + offset,
-		 HDMI_AVI_INFO_LINE(2), /* anything other than 0 */
-		 ~HDMI_AVI_INFO_LINE_MASK);
+	/* allow 60958 channel status and send audio packets fields to be updated */
+	WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
+		AFMT_AUDIO_SAMPLE_SEND | AFMT_RESET_FIFO_WHEN_AUDIO_DIS | AFMT_60958_CS_UPDATE);
+}
 
-	WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + offset,
-		  AFMT_AUDIO_SAMPLE_SEND); /* send audio packets */
 
-	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
-	WREG32(AFMT_RAMP_CONTROL0 + offset, 0x00FFFFFF);
-	WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF);
-	WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001);
-	WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001);
+void dce4_set_mute(struct drm_encoder *encoder, u32 offset, bool mute)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
 
-	/* enable audio after to setting up hw */
-	if (ASIC_IS_DCE6(rdev))
-		dce6_audio_enable(rdev, dig->afmt->pin, 1);
+	if (mute)
+		WREG32_OR(HDMI_GC + offset, HDMI_GC_AVMUTE);
 	else
-		dce4_audio_enable(rdev, dig->afmt->pin, 0xf);
+		WREG32_AND(HDMI_GC + offset, ~HDMI_GC_AVMUTE);
 }
 
 void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
@@ -516,10 +415,7 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
 		return;
 
 	if (!enable && dig->afmt->pin) {
-		if (ASIC_IS_DCE6(rdev))
-			dce6_audio_enable(rdev, dig->afmt->pin, 0);
-		else
-			dce4_audio_enable(rdev, dig->afmt->pin, 0);
+		radeon_audio_enable(rdev, dig->afmt->pin, 0);
 		dig->afmt->pin = NULL;
 	}
 
@@ -528,3 +424,57 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
 	DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n",
 		  enable ? "En" : "Dis", dig->afmt->offset, radeon_encoder->encoder_id);
 }
+
+void evergreen_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	uint32_t offset;
+
+	if (!dig || !dig->afmt)
+		return;
+
+	offset = dig->afmt->offset;
+
+	if (enable) {
+		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		struct radeon_connector_atom_dig *dig_connector;
+		uint32_t val;
+
+		if (dig->afmt->enabled)
+			return;
+
+		WREG32(EVERGREEN_DP_SEC_TIMESTAMP + offset, EVERGREEN_DP_SEC_TIMESTAMP_MODE(1));
+
+		if (radeon_connector->con_priv) {
+			dig_connector = radeon_connector->con_priv;
+			val = RREG32(EVERGREEN_DP_SEC_AUD_N + offset);
+			val &= ~EVERGREEN_DP_SEC_N_BASE_MULTIPLE(0xf);
+
+			if (dig_connector->dp_clock == 162000)
+				val |= EVERGREEN_DP_SEC_N_BASE_MULTIPLE(3);
+			else
+				val |= EVERGREEN_DP_SEC_N_BASE_MULTIPLE(5);
+
+			WREG32(EVERGREEN_DP_SEC_AUD_N + offset, val);
+		}
+
+		WREG32(EVERGREEN_DP_SEC_CNTL + offset,
+			EVERGREEN_DP_SEC_ASP_ENABLE |		/* Audio packet transmission */
+			EVERGREEN_DP_SEC_ATP_ENABLE |		/* Audio timestamp packet transmission */
+			EVERGREEN_DP_SEC_AIP_ENABLE |		/* Audio infoframe packet transmission */
+			EVERGREEN_DP_SEC_STREAM_ENABLE);	/* Master enable for secondary stream engine */
+		radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
+	} else {
+		if (!dig->afmt->enabled)
+			return;
+
+		WREG32(EVERGREEN_DP_SEC_CNTL + offset, 0);
+		radeon_audio_enable(rdev, dig->afmt->pin, 0);
+	}
+
+	dig->afmt->enabled = enable;
+}

+ 15 - 0
drivers/gpu/drm/radeon/evergreen_reg.h

@@ -251,4 +251,19 @@
 /* HDMI blocks at 0x7030, 0x7c30, 0x10830, 0x11430, 0x12030, 0x12c30 */
 #define EVERGREEN_HDMI_BASE				0x7030
 
+/* Display Port block */
+#define EVERGREEN_DP_SEC_CNTL                           0x7280
+#       define EVERGREEN_DP_SEC_STREAM_ENABLE           (1 << 0)
+#       define EVERGREEN_DP_SEC_ASP_ENABLE              (1 << 4)
+#       define EVERGREEN_DP_SEC_ATP_ENABLE              (1 << 8)
+#       define EVERGREEN_DP_SEC_AIP_ENABLE              (1 << 12)
+#       define EVERGREEN_DP_SEC_GSP_ENABLE              (1 << 20)
+#       define EVERGREEN_DP_SEC_AVI_ENABLE              (1 << 24)
+#       define EVERGREEN_DP_SEC_MPG_ENABLE              (1 << 28)
+#define EVERGREEN_DP_SEC_TIMESTAMP                      0x72a4
+#       define EVERGREEN_DP_SEC_TIMESTAMP_MODE(x)       (((x) & 0x3) << 0)
+#define EVERGREEN_DP_SEC_AUD_N                          0x7294
+#       define EVERGREEN_DP_SEC_N_BASE_MULTIPLE(x)      (((x) & 0xf) << 24)
+#       define EVERGREEN_DP_SEC_SS_EN                   (1 << 28)
+
 #endif

+ 1 - 0
drivers/gpu/drm/radeon/evergreend.h

@@ -509,6 +509,7 @@
 #define DCCG_AUDIO_DTO1_MODULE            0x05c4
 #define DCCG_AUDIO_DTO1_LOAD              0x05c8
 #define DCCG_AUDIO_DTO1_CNTL              0x05cc
+#       define DCCG_AUDIO_DTO1_USE_512FBR_DTO (1 << 3)
 
 /* DCE 4.0 AFMT */
 #define HDMI_CONTROL                         0x7030

+ 2 - 0
drivers/gpu/drm/radeon/kv_dpm.c

@@ -1925,6 +1925,7 @@ void kv_dpm_setup_asic(struct radeon_device *rdev)
 	kv_init_sclk_t(rdev);
 }
 
+#if 0
 void kv_dpm_reset_asic(struct radeon_device *rdev)
 {
 	struct kv_power_info *pi = kv_get_pi(rdev);
@@ -1945,6 +1946,7 @@ void kv_dpm_reset_asic(struct radeon_device *rdev)
 		kv_set_enabled_level(rdev, pi->graphics_boot_level);
 	}
 }
+#endif
 
 //XXX use sumo_dpm_display_configuration_changed
 

+ 5 - 13
drivers/gpu/drm/radeon/ni.c

@@ -27,6 +27,7 @@
 #include <drm/drmP.h>
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include <drm/radeon_drm.h>
 #include "nid.h"
 #include "atom.h"
@@ -2097,15 +2098,9 @@ static int cayman_startup(struct radeon_device *rdev)
 		return r;
 	}
 
-	if (ASIC_IS_DCE6(rdev)) {
-		r = dce6_audio_init(rdev);
-		if (r)
-			return r;
-	} else {
-		r = r600_audio_init(rdev);
-		if (r)
-			return r;
-	}
+	r = radeon_audio_init(rdev);
+	if (r)
+		return r;
 
 	return 0;
 }
@@ -2140,10 +2135,7 @@ int cayman_resume(struct radeon_device *rdev)
 int cayman_suspend(struct radeon_device *rdev)
 {
 	radeon_pm_suspend(rdev);
-	if (ASIC_IS_DCE6(rdev))
-		dce6_audio_fini(rdev);
-	else
-		r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	radeon_vm_manager_fini(rdev);
 	cayman_cp_enable(rdev, false);
 	cayman_dma_stop(rdev);

+ 2 - 0
drivers/gpu/drm/radeon/ni_dpm.c

@@ -3862,11 +3862,13 @@ void ni_dpm_post_set_power_state(struct radeon_device *rdev)
 	ni_update_current_ps(rdev, new_ps);
 }
 
+#if 0
 void ni_dpm_reset_asic(struct radeon_device *rdev)
 {
 	ni_restrict_performance_levels_before_switch(rdev);
 	rv770_set_boot_state(rdev);
 }
+#endif
 
 union power_info {
 	struct _ATOM_POWERPLAY_INFO info;

+ 4 - 3
drivers/gpu/drm/radeon/r600.c

@@ -33,6 +33,7 @@
 #include <drm/radeon_drm.h>
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include "radeon_mode.h"
 #include "r600d.h"
 #include "atom.h"
@@ -3054,7 +3055,7 @@ static int r600_startup(struct radeon_device *rdev)
 		return r;
 	}
 
-	r = r600_audio_init(rdev);
+	r = radeon_audio_init(rdev);
 	if (r) {
 		DRM_ERROR("radeon: audio init failed\n");
 		return r;
@@ -3105,7 +3106,7 @@ int r600_resume(struct radeon_device *rdev)
 int r600_suspend(struct radeon_device *rdev)
 {
 	radeon_pm_suspend(rdev);
-	r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	r600_cp_stop(rdev);
 	if (rdev->has_uvd) {
 		uvd_v1_0_fini(rdev);
@@ -3224,7 +3225,7 @@ int r600_init(struct radeon_device *rdev)
 void r600_fini(struct radeon_device *rdev)
 {
 	radeon_pm_fini(rdev);
-	r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	r600_cp_fini(rdev);
 	r600_irq_fini(rdev);
 	if (rdev->has_uvd) {

+ 95 - 304
drivers/gpu/drm/radeon/r600_hdmi.c

@@ -29,6 +29,7 @@
 #include <drm/radeon_drm.h>
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include "r600d.h"
 #include "atom.h"
 
@@ -55,30 +56,6 @@ enum r600_hdmi_iec_status_bits {
 	AUDIO_STATUS_LEVEL        = 0x80
 };
 
-static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = {
-    /*	     32kHz	  44.1kHz	48kHz    */
-    /* Clock      N     CTS      N     CTS      N     CTS */
-    {  25175,  4096,  25175, 28224, 125875,  6144,  25175 }, /*  25,20/1.001 MHz */
-    {  25200,  4096,  25200,  6272,  28000,  6144,  25200 }, /*  25.20       MHz */
-    {  27000,  4096,  27000,  6272,  30000,  6144,  27000 }, /*  27.00       MHz */
-    {  27027,  4096,  27027,  6272,  30030,  6144,  27027 }, /*  27.00*1.001 MHz */
-    {  54000,  4096,  54000,  6272,  60000,  6144,  54000 }, /*  54.00       MHz */
-    {  54054,  4096,  54054,  6272,  60060,  6144,  54054 }, /*  54.00*1.001 MHz */
-    {  74176,  4096,  74176,  5733,  75335,  6144,  74176 }, /*  74.25/1.001 MHz */
-    {  74250,  4096,  74250,  6272,  82500,  6144,  74250 }, /*  74.25       MHz */
-    { 148352,  4096, 148352,  5733, 150670,  6144, 148352 }, /* 148.50/1.001 MHz */
-    { 148500,  4096, 148500,  6272, 165000,  6144, 148500 }, /* 148.50       MHz */
-};
-
-
-/*
- * check if the chipset is supported
- */
-static int r600_audio_chipset_supported(struct radeon_device *rdev)
-{
-	return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev);
-}
-
 static struct r600_audio_pin r600_audio_status(struct radeon_device *rdev)
 {
 	struct r600_audio_pin status;
@@ -191,155 +168,56 @@ void r600_audio_enable(struct radeon_device *rdev,
 	WREG32(AZ_HOT_PLUG_CONTROL, tmp);
 }
 
-/*
- * initialize the audio vars
- */
-int r600_audio_init(struct radeon_device *rdev)
-{
-	if (!radeon_audio || !r600_audio_chipset_supported(rdev))
-		return 0;
-
-	rdev->audio.enabled = true;
-
-	rdev->audio.num_pins = 1;
-	rdev->audio.pin[0].channels = -1;
-	rdev->audio.pin[0].rate = -1;
-	rdev->audio.pin[0].bits_per_sample = -1;
-	rdev->audio.pin[0].status_bits = 0;
-	rdev->audio.pin[0].category_code = 0;
-	rdev->audio.pin[0].id = 0;
-	/* disable audio.  it will be set up later */
-	r600_audio_enable(rdev, &rdev->audio.pin[0], 0);
-
-	return 0;
-}
-
-/*
- * release the audio timer
- * TODO: How to do this correctly on SMP systems?
- */
-void r600_audio_fini(struct radeon_device *rdev)
-{
-	if (!rdev->audio.enabled)
-		return;
-
-	r600_audio_enable(rdev, &rdev->audio.pin[0], 0);
-
-	rdev->audio.enabled = false;
-}
-
 struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev)
 {
 	/* only one pin on 6xx-NI */
 	return &rdev->audio.pin[0];
 }
 
-/*
- * calculate CTS and N values if they are not found in the table
- */
-static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq)
-{
-	int n, cts;
-	unsigned long div, mul;
-
-	/* Safe, but overly large values */
-	n = 128 * freq;
-	cts = clock * 1000;
-
-	/* Smallest valid fraction */
-	div = gcd(n, cts);
-
-	n /= div;
-	cts /= div;
-
-	/*
-	 * The optimal N is 128*freq/1000. Calculate the closest larger
-	 * value that doesn't truncate any bits.
-	 */
-	mul = ((128*freq/1000) + (n-1))/n;
-
-	n *= mul;
-	cts *= mul;
-
-	/* Check that we are in spec (not always possible) */
-	if (n < (128*freq/1500))
-		printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n");
-	if (n > (128*freq/300))
-		printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n");
-
-	*N = n;
-	*CTS = cts;
-
-	DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n",
-		  *N, *CTS, freq);
-}
-
-struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock)
-{
-	struct radeon_hdmi_acr res;
-	u8 i;
-
-	/* Precalculated values for common clocks */
-	for (i = 0; i < ARRAY_SIZE(r600_hdmi_predefined_acr); i++) {
-		if (r600_hdmi_predefined_acr[i].clock == clock)
-			return r600_hdmi_predefined_acr[i];
-	}
-
-	/* And odd clocks get manually calculated */
-	r600_hdmi_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000);
-	r600_hdmi_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100);
-	r600_hdmi_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000);
-
-	return res;
-}
-
-/*
- * update the N and CTS parameters for a given pixel clock rate
- */
-void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
+void r600_hdmi_update_acr(struct drm_encoder *encoder, long offset,
+	const struct radeon_hdmi_acr *acr)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_hdmi_acr acr = r600_hdmi_acr(clock);
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	uint32_t offset = dig->afmt->offset;
+
+	/* DCE 3.0 uses register that's normally for CRC_CONTROL */
+	uint32_t acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL :
+				       HDMI0_ACR_PACKET_CONTROL;
+	WREG32_P(acr_ctl + offset,
+		HDMI0_ACR_SOURCE |		/* select SW CTS value */
+		HDMI0_ACR_AUTO_SEND,	/* allow hw to sent ACR packets when required */
+		~(HDMI0_ACR_SOURCE |
+		HDMI0_ACR_AUTO_SEND));
 
 	WREG32_P(HDMI0_ACR_32_0 + offset,
-		 HDMI0_ACR_CTS_32(acr.cts_32khz),
-		 ~HDMI0_ACR_CTS_32_MASK);
+		HDMI0_ACR_CTS_32(acr->cts_32khz),
+		~HDMI0_ACR_CTS_32_MASK);
 	WREG32_P(HDMI0_ACR_32_1 + offset,
-		 HDMI0_ACR_N_32(acr.n_32khz),
-		 ~HDMI0_ACR_N_32_MASK);
+		HDMI0_ACR_N_32(acr->n_32khz),
+		~HDMI0_ACR_N_32_MASK);
 
 	WREG32_P(HDMI0_ACR_44_0 + offset,
-		 HDMI0_ACR_CTS_44(acr.cts_44_1khz),
-		 ~HDMI0_ACR_CTS_44_MASK);
+		HDMI0_ACR_CTS_44(acr->cts_44_1khz),
+		~HDMI0_ACR_CTS_44_MASK);
 	WREG32_P(HDMI0_ACR_44_1 + offset,
-		 HDMI0_ACR_N_44(acr.n_44_1khz),
-		 ~HDMI0_ACR_N_44_MASK);
+		HDMI0_ACR_N_44(acr->n_44_1khz),
+		~HDMI0_ACR_N_44_MASK);
 
 	WREG32_P(HDMI0_ACR_48_0 + offset,
-		 HDMI0_ACR_CTS_48(acr.cts_48khz),
-		 ~HDMI0_ACR_CTS_48_MASK);
+		HDMI0_ACR_CTS_48(acr->cts_48khz),
+		~HDMI0_ACR_CTS_48_MASK);
 	WREG32_P(HDMI0_ACR_48_1 + offset,
-		 HDMI0_ACR_N_48(acr.n_48khz),
-		 ~HDMI0_ACR_N_48_MASK);
+		HDMI0_ACR_N_48(acr->n_48khz),
+		~HDMI0_ACR_N_48_MASK);
 }
 
 /*
  * build a HDMI Video Info Frame
  */
-void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,
-				    size_t size)
+void r600_set_avi_packet(struct radeon_device *rdev, u32 offset,
+    unsigned char *buffer, size_t size)
 {
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	uint32_t offset = dig->afmt->offset;
 	uint8_t *frame = buffer + 3;
-	uint8_t *header = buffer;
 
 	WREG32(HDMI0_AVI_INFO0 + offset,
 		frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
@@ -348,7 +226,14 @@ void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,
 	WREG32(HDMI0_AVI_INFO2 + offset,
 		frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
 	WREG32(HDMI0_AVI_INFO3 + offset,
-		frame[0xC] | (frame[0xD] << 8) | (header[1] << 24));
+		frame[0xC] | (frame[0xD] << 8) | (buffer[1] << 24));
+
+	WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset,
+		HDMI0_AVI_INFO_SEND |	/* enable AVI info frames */
+		HDMI0_AVI_INFO_CONT);	/* send AVI info frames every frame/field */
+
+	WREG32_OR(HDMI0_INFOFRAME_CONTROL1 + offset,
+		HDMI0_AVI_INFO_LINE(2));	/* anything other than 0 */
 }
 
 /*
@@ -425,188 +310,94 @@ void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
 		 value, ~HDMI0_AUDIO_TEST_EN);
 }
 
-void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
+void r600_hdmi_audio_set_dto(struct radeon_device *rdev,
+    struct radeon_crtc *crtc, unsigned int clock)
 {
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	u32 base_rate = 24000;
-	u32 max_ratio = clock / base_rate;
-	u32 dto_phase;
-	u32 dto_modulo = clock;
-	u32 wallclock_ratio;
-	u32 dto_cntl;
+	struct radeon_encoder *radeon_encoder;
+	struct radeon_encoder_atom_dig *dig;
 
-	if (!dig || !dig->afmt)
+	if (!crtc)
 		return;
 
-	if (max_ratio >= 8) {
-		dto_phase = 192 * 1000;
-		wallclock_ratio = 3;
-	} else if (max_ratio >= 4) {
-		dto_phase = 96 * 1000;
-		wallclock_ratio = 2;
-	} else if (max_ratio >= 2) {
-		dto_phase = 48 * 1000;
-		wallclock_ratio = 1;
-	} else {
-		dto_phase = 24 * 1000;
-		wallclock_ratio = 0;
-	}
+	radeon_encoder = to_radeon_encoder(crtc->encoder);
+	dig = radeon_encoder->enc_priv;
 
-	/* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT.
-	 * doesn't matter which one you use.  Just use the first one.
-	 */
-	/* XXX two dtos; generally use dto0 for hdmi */
-	/* Express [24MHz / target pixel clock] as an exact rational
-	 * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
-	 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
-	 */
-	if (ASIC_IS_DCE32(rdev)) {
-		if (dig->dig_encoder == 0) {
-			dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
-			dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
-			WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl);
-			WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase);
-			WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo);
-			WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
-		} else {
-			dto_cntl = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
-			dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
-			WREG32(DCCG_AUDIO_DTO1_CNTL, dto_cntl);
-			WREG32(DCCG_AUDIO_DTO1_PHASE, dto_phase);
-			WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo);
-			WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
-		}
+	if (!dig)
+		return;
+
+	if (dig->dig_encoder == 0) {
+		WREG32(DCCG_AUDIO_DTO0_PHASE, 24000 * 100);
+		WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
+		WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
 	} else {
-		/* according to the reg specs, this should DCE3.2 only, but in
-		 * practice it seems to cover DCE2.0/3.0/3.1 as well.
-		 */
-		if (dig->dig_encoder == 0) {
-			WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
-			WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
-			WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
-		} else {
-			WREG32(DCCG_AUDIO_DTO1_PHASE, base_rate * 100);
-			WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100);
-			WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
-		}
+		WREG32(DCCG_AUDIO_DTO1_PHASE, 24000 * 100);
+		WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100);
+		WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
 	}
 }
 
-/*
- * update the info frames with the data from the current display mode
- */
-void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
+void r600_set_vbi_packet(struct drm_encoder *encoder, u32 offset)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
-	struct hdmi_avi_infoframe frame;
-	uint32_t offset;
-	uint32_t acr_ctl;
-	ssize_t err;
-
-	if (!dig || !dig->afmt)
-		return;
-
-	/* Silent, r600_hdmi_enable will raise WARN for us */
-	if (!dig->afmt->enabled)
-		return;
-	offset = dig->afmt->offset;
 
-	/* disable audio prior to setting up hw */
-	dig->afmt->pin = r600_audio_get_pin(rdev);
-	r600_audio_enable(rdev, dig->afmt->pin, 0xf);
+	WREG32_OR(HDMI0_VBI_PACKET_CONTROL + offset,
+		HDMI0_NULL_SEND |	/* send null packets when required */
+		HDMI0_GC_SEND |		/* send general control packets */
+		HDMI0_GC_CONT);		/* send general control packets every frame */
+}
 
-	r600_audio_set_dto(encoder, mode->clock);
+void r600_set_audio_packet(struct drm_encoder *encoder, u32 offset)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
 
 	WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset,
-		 HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
-		 HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
-		 HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
-		 HDMI0_60958_CS_UPDATE, /* allow 60958 channel status fields to be updated */
-		 ~(HDMI0_AUDIO_SAMPLE_SEND |
-		   HDMI0_AUDIO_DELAY_EN_MASK |
-		   HDMI0_AUDIO_PACKETS_PER_LINE_MASK |
-		   HDMI0_60958_CS_UPDATE));
-
-	/* DCE 3.0 uses register that's normally for CRC_CONTROL */
-	acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL :
-				       HDMI0_ACR_PACKET_CONTROL;
-	WREG32_P(acr_ctl + offset,
-		 HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
-		 HDMI0_ACR_AUTO_SEND, /* allow hw to sent ACR packets when required */
-		 ~(HDMI0_ACR_SOURCE |
-		   HDMI0_ACR_AUTO_SEND));
-
-	WREG32_OR(HDMI0_VBI_PACKET_CONTROL + offset,
-		  HDMI0_NULL_SEND | /* send null packets when required */
-		  HDMI0_GC_SEND | /* send general control packets */
-		  HDMI0_GC_CONT); /* send general control packets every frame */
+		HDMI0_AUDIO_SAMPLE_SEND |			/* send audio packets */
+		HDMI0_AUDIO_DELAY_EN(1) |			/* default audio delay */
+		HDMI0_AUDIO_PACKETS_PER_LINE(3) |	/* should be suffient for all audio modes and small enough for all hblanks */
+		HDMI0_60958_CS_UPDATE,				/* allow 60958 channel status fields to be updated */
+		~(HDMI0_AUDIO_SAMPLE_SEND |
+		HDMI0_AUDIO_DELAY_EN_MASK |
+		HDMI0_AUDIO_PACKETS_PER_LINE_MASK |
+		HDMI0_60958_CS_UPDATE));
 
 	WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset,
-		  HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
-		  HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
-		  HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
-		  HDMI0_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */
+		HDMI0_AUDIO_INFO_SEND |		/* enable audio info frames (frames won't be set until audio is enabled) */
+		HDMI0_AUDIO_INFO_UPDATE);	/* required for audio info values to be updated */
 
 	WREG32_P(HDMI0_INFOFRAME_CONTROL1 + offset,
-		 HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
-		 HDMI0_AUDIO_INFO_LINE(2), /* anything other than 0 */
-		 ~(HDMI0_AVI_INFO_LINE_MASK |
-		   HDMI0_AUDIO_INFO_LINE_MASK));
-
-	WREG32_AND(HDMI0_GC + offset,
-		   ~HDMI0_GC_AVMUTE); /* unset HDMI0_GC_AVMUTE */
-
-	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
-	if (err < 0) {
-		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
-		return;
-	}
-
-	err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
-	if (err < 0) {
-		DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
-		return;
-	}
-
-	r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
-
-	/* fglrx duplicates INFOFRAME_CONTROL0 & INFOFRAME_CONTROL1 ops here */
+		HDMI0_AUDIO_INFO_LINE(2),	/* anything other than 0 */
+		~HDMI0_AUDIO_INFO_LINE_MASK);
 
 	WREG32_AND(HDMI0_GENERIC_PACKET_CONTROL + offset,
-		   ~(HDMI0_GENERIC0_SEND |
-		     HDMI0_GENERIC0_CONT |
-		     HDMI0_GENERIC0_UPDATE |
-		     HDMI0_GENERIC1_SEND |
-		     HDMI0_GENERIC1_CONT |
-		     HDMI0_GENERIC0_LINE_MASK |
-		     HDMI0_GENERIC1_LINE_MASK));
-
-	r600_hdmi_update_ACR(encoder, mode->clock);
+		~(HDMI0_GENERIC0_SEND |
+		HDMI0_GENERIC0_CONT |
+		HDMI0_GENERIC0_UPDATE |
+		HDMI0_GENERIC1_SEND |
+		HDMI0_GENERIC1_CONT |
+		HDMI0_GENERIC0_LINE_MASK |
+		HDMI0_GENERIC1_LINE_MASK));
 
 	WREG32_P(HDMI0_60958_0 + offset,
-		 HDMI0_60958_CS_CHANNEL_NUMBER_L(1),
-		 ~(HDMI0_60958_CS_CHANNEL_NUMBER_L_MASK |
-		   HDMI0_60958_CS_CLOCK_ACCURACY_MASK));
+		HDMI0_60958_CS_CHANNEL_NUMBER_L(1),
+		~(HDMI0_60958_CS_CHANNEL_NUMBER_L_MASK |
+		HDMI0_60958_CS_CLOCK_ACCURACY_MASK));
 
 	WREG32_P(HDMI0_60958_1 + offset,
-		 HDMI0_60958_CS_CHANNEL_NUMBER_R(2),
-		 ~HDMI0_60958_CS_CHANNEL_NUMBER_R_MASK);
+		HDMI0_60958_CS_CHANNEL_NUMBER_R(2),
+		~HDMI0_60958_CS_CHANNEL_NUMBER_R_MASK);
+}
 
-	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
-	WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF);
-	WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF);
-	WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001);
-	WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
+void r600_set_mute(struct drm_encoder *encoder, u32 offset, bool mute)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
 
-	/* enable audio after to setting up hw */
-	r600_audio_enable(rdev, dig->afmt->pin, 0xf);
+	if (mute)
+		WREG32_OR(HDMI0_GC + offset, HDMI0_GC_AVMUTE);
+	else
+		WREG32_AND(HDMI0_GC + offset, ~HDMI0_GC_AVMUTE);
 }
 
 /**
@@ -692,7 +483,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder, bool enable)
 		return;
 
 	if (!enable && dig->afmt->pin) {
-		r600_audio_enable(rdev, dig->afmt->pin, 0);
+		radeon_audio_enable(rdev, dig->afmt->pin, 0);
 		dig->afmt->pin = NULL;
 	}
 

+ 15 - 0
drivers/gpu/drm/radeon/radeon.h

@@ -1757,6 +1757,9 @@ struct r600_audio {
 	bool enabled;
 	struct r600_audio_pin pin[RADEON_MAX_AFMT_BLOCKS];
 	int num_pins;
+	struct radeon_audio_funcs *hdmi_funcs;
+	struct radeon_audio_funcs *dp_funcs;
+	struct radeon_audio_basic_funcs *funcs;
 };
 
 /*
@@ -1777,8 +1780,16 @@ void radeon_test_syncing(struct radeon_device *rdev);
 /*
  * MMU Notifier
  */
+#if defined(CONFIG_MMU_NOTIFIER)
 int radeon_mn_register(struct radeon_bo *bo, unsigned long addr);
 void radeon_mn_unregister(struct radeon_bo *bo);
+#else
+static inline int radeon_mn_register(struct radeon_bo *bo, unsigned long addr)
+{
+	return -ENODEV;
+}
+static inline void radeon_mn_unregister(struct radeon_bo *bo) {}
+#endif
 
 /*
  * Debugfs
@@ -1967,6 +1978,10 @@ struct radeon_asic {
 		bool (*vblank_too_short)(struct radeon_device *rdev);
 		void (*powergate_uvd)(struct radeon_device *rdev, bool gate);
 		void (*enable_bapm)(struct radeon_device *rdev, bool enable);
+		void (*fan_ctrl_set_mode)(struct radeon_device *rdev, u32 mode);
+		u32 (*fan_ctrl_get_mode)(struct radeon_device *rdev);
+		int (*set_fan_speed_percent)(struct radeon_device *rdev, u32 speed);
+		int (*get_fan_speed_percent)(struct radeon_device *rdev, u32 *speed);
 	} dpm;
 	/* pageflipping */
 	struct {

+ 8 - 28
drivers/gpu/drm/radeon/radeon_asic.c

@@ -638,8 +638,6 @@ static struct radeon_asic rs600_asic = {
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &r600_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r100_copy_blit,
@@ -706,8 +704,6 @@ static struct radeon_asic rs690_asic = {
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &r600_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r100_copy_blit,
@@ -935,8 +931,6 @@ static struct radeon_asic r600_asic = {
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &r600_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r600_copy_cpdma,
@@ -1021,8 +1015,6 @@ static struct radeon_asic rv6xx_asic = {
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &r600_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r600_copy_cpdma,
@@ -1112,8 +1104,6 @@ static struct radeon_asic rs780_asic = {
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &r600_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r600_copy_cpdma,
@@ -1216,8 +1206,6 @@ static struct radeon_asic rv770_asic = {
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &dce3_1_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r600_copy_cpdma,
@@ -1334,8 +1322,6 @@ static struct radeon_asic evergreen_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r600_copy_cpdma,
@@ -1426,8 +1412,6 @@ static struct radeon_asic sumo_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r600_copy_cpdma,
@@ -1517,8 +1501,6 @@ static struct radeon_asic btc_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r600_copy_cpdma,
@@ -1663,8 +1645,6 @@ static struct radeon_asic cayman_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r600_copy_cpdma,
@@ -1766,8 +1746,6 @@ static struct radeon_asic trinity_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r600_copy_cpdma,
@@ -1899,8 +1877,6 @@ static struct radeon_asic si_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &r600_copy_cpdma,
@@ -1953,6 +1929,10 @@ static struct radeon_asic si_asic = {
 		.debugfs_print_current_performance_level = &si_dpm_debugfs_print_current_performance_level,
 		.force_performance_level = &si_dpm_force_performance_level,
 		.vblank_too_short = &ni_dpm_vblank_too_short,
+		.fan_ctrl_set_mode = &si_fan_ctrl_set_mode,
+		.fan_ctrl_get_mode = &si_fan_ctrl_get_mode,
+		.get_fan_speed_percent = &si_fan_ctrl_get_fan_speed_percent,
+		.set_fan_speed_percent = &si_fan_ctrl_set_fan_speed_percent,
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
@@ -2062,8 +2042,6 @@ static struct radeon_asic ci_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &cik_copy_cpdma,
@@ -2118,6 +2096,10 @@ static struct radeon_asic ci_asic = {
 		.force_performance_level = &ci_dpm_force_performance_level,
 		.vblank_too_short = &ci_dpm_vblank_too_short,
 		.powergate_uvd = &ci_dpm_powergate_uvd,
+		.fan_ctrl_set_mode = &ci_fan_ctrl_set_mode,
+		.fan_ctrl_get_mode = &ci_fan_ctrl_get_mode,
+		.get_fan_speed_percent = &ci_fan_ctrl_get_fan_speed_percent,
+		.set_fan_speed_percent = &ci_fan_ctrl_set_fan_speed_percent,
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
@@ -2169,8 +2151,6 @@ static struct radeon_asic kv_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	.copy = {
 		.blit = &cik_copy_cpdma,

+ 13 - 8
drivers/gpu/drm/radeon/radeon_asic.h

@@ -390,7 +390,6 @@ void r600_irq_suspend(struct radeon_device *rdev);
 void r600_disable_interrupts(struct radeon_device *rdev);
 void r600_rlc_stop(struct radeon_device *rdev);
 /* r600 audio */
-int r600_audio_init(struct radeon_device *rdev);
 void r600_audio_fini(struct radeon_device *rdev);
 void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock);
 void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,
@@ -399,8 +398,6 @@ void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock);
 void r600_hdmi_audio_workaround(struct drm_encoder *encoder);
 int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
 void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
-void r600_hdmi_enable(struct drm_encoder *encoder, bool enable);
-void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
 int r600_mc_wait_for_idle(struct radeon_device *rdev);
 u32 r600_get_xclk(struct radeon_device *rdev);
 uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev);
@@ -469,8 +466,6 @@ struct radeon_fence *rv770_copy_dma(struct radeon_device *rdev,
 u32 rv770_get_xclk(struct radeon_device *rdev);
 int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int rv770_get_temp(struct radeon_device *rdev);
-/* hdmi */
-void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
 /* rv7xx pm */
 int rv770_dpm_init(struct radeon_device *rdev);
 int rv770_dpm_enable(struct radeon_device *rdev);
@@ -540,8 +535,6 @@ struct radeon_fence *evergreen_copy_dma(struct radeon_device *rdev,
 					uint64_t src_offset, uint64_t dst_offset,
 					unsigned num_gpu_pages,
 					struct reservation_object *resv);
-void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable);
-void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
 int evergreen_get_temp(struct radeon_device *rdev);
 int sumo_get_temp(struct radeon_device *rdev);
 int tn_get_temp(struct radeon_device *rdev);
@@ -680,7 +673,6 @@ void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable);
 
 /* DCE6 - SI */
 void dce6_bandwidth_update(struct radeon_device *rdev);
-int dce6_audio_init(struct radeon_device *rdev);
 void dce6_audio_fini(struct radeon_device *rdev);
 
 /*
@@ -744,6 +736,12 @@ void si_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
 						    struct seq_file *m);
 int si_dpm_force_performance_level(struct radeon_device *rdev,
 				   enum radeon_dpm_forced_level level);
+int si_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
+						 u32 *speed);
+int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
+						 u32 speed);
+u32 si_fan_ctrl_get_mode(struct radeon_device *rdev);
+void si_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode);
 
 /* DCE8 - CIK */
 void dce8_bandwidth_update(struct radeon_device *rdev);
@@ -861,6 +859,13 @@ int ci_dpm_force_performance_level(struct radeon_device *rdev,
 bool ci_dpm_vblank_too_short(struct radeon_device *rdev);
 void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate);
 
+int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
+						 u32 *speed);
+int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
+						 u32 speed);
+u32 ci_fan_ctrl_get_mode(struct radeon_device *rdev);
+void ci_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode);
+
 int kv_dpm_init(struct radeon_device *rdev);
 int kv_dpm_enable(struct radeon_device *rdev);
 int kv_dpm_late_enable(struct radeon_device *rdev);

+ 766 - 0
drivers/gpu/drm/radeon/radeon_audio.c

@@ -0,0 +1,766 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Slava Grigorev <slava.grigorev@amd.com>
+ */
+
+#include <linux/gcd.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include "radeon.h"
+#include "atom.h"
+#include "radeon_audio.h"
+
+void r600_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin,
+		u8 enable_mask);
+void dce4_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin,
+		u8 enable_mask);
+void dce6_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin,
+		u8 enable_mask);
+u32 dce6_endpoint_rreg(struct radeon_device *rdev, u32 offset, u32 reg);
+void dce6_endpoint_wreg(struct radeon_device *rdev,
+		u32 offset, u32 reg, u32 v);
+void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder,
+		struct cea_sad *sads, int sad_count);
+void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder,
+		struct cea_sad *sads, int sad_count);
+void dce6_afmt_write_sad_regs(struct drm_encoder *encoder,
+		struct cea_sad *sads, int sad_count);
+void dce3_2_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
+		u8 *sadb, int sad_count);
+void dce3_2_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
+		u8 *sadb, int sad_count);
+void dce4_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
+		u8 *sadb, int sad_count);
+void dce4_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
+		u8 *sadb, int sad_count);
+void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
+		u8 *sadb, int sad_count);
+void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
+		u8 *sadb, int sad_count);
+void dce4_afmt_write_latency_fields(struct drm_encoder *encoder,
+		struct drm_connector *connector, struct drm_display_mode *mode);
+void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
+		struct drm_connector *connector, struct drm_display_mode *mode);
+struct r600_audio_pin* r600_audio_get_pin(struct radeon_device *rdev);
+struct r600_audio_pin* dce6_audio_get_pin(struct radeon_device *rdev);
+void dce6_afmt_select_pin(struct drm_encoder *encoder);
+void r600_hdmi_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock);
+void dce3_2_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock);
+void dce4_hdmi_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock);
+void dce4_dp_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock);
+void dce6_hdmi_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock);
+void dce6_dp_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock);
+void r600_set_avi_packet(struct radeon_device *rdev, u32 offset,
+	unsigned char *buffer, size_t size);
+void evergreen_set_avi_packet(struct radeon_device *rdev, u32 offset,
+	unsigned char *buffer, size_t size);
+void r600_hdmi_update_acr(struct drm_encoder *encoder, long offset,
+	const struct radeon_hdmi_acr *acr);
+void dce3_2_hdmi_update_acr(struct drm_encoder *encoder, long offset,
+	const struct radeon_hdmi_acr *acr);
+void evergreen_hdmi_update_acr(struct drm_encoder *encoder, long offset,
+	const struct radeon_hdmi_acr *acr);
+void r600_set_vbi_packet(struct drm_encoder *encoder, u32 offset);
+void dce4_set_vbi_packet(struct drm_encoder *encoder, u32 offset);
+void dce4_hdmi_set_color_depth(struct drm_encoder *encoder,
+	u32 offset, int bpc);
+void r600_set_audio_packet(struct drm_encoder *encoder, u32 offset);
+void dce3_2_set_audio_packet(struct drm_encoder *encoder, u32 offset);
+void dce4_set_audio_packet(struct drm_encoder *encoder, u32 offset);
+void r600_set_mute(struct drm_encoder *encoder, u32 offset, bool mute);
+void dce3_2_set_mute(struct drm_encoder *encoder, u32 offset, bool mute);
+void dce4_set_mute(struct drm_encoder *encoder, u32 offset, bool mute);
+static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder,
+	struct drm_display_mode *mode);
+static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
+	struct drm_display_mode *mode);
+void r600_hdmi_enable(struct drm_encoder *encoder, bool enable);
+void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable);
+void evergreen_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable);
+void dce6_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable);
+
+static const u32 pin_offsets[7] =
+{
+	(0x5e00 - 0x5e00),
+	(0x5e18 - 0x5e00),
+	(0x5e30 - 0x5e00),
+	(0x5e48 - 0x5e00),
+	(0x5e60 - 0x5e00),
+	(0x5e78 - 0x5e00),
+	(0x5e90 - 0x5e00),
+};
+
+static u32 radeon_audio_rreg(struct radeon_device *rdev, u32 offset, u32 reg)
+{
+	return RREG32(reg);
+}
+
+static void radeon_audio_wreg(struct radeon_device *rdev, u32 offset,
+		u32 reg, u32 v)
+{
+	WREG32(reg, v);
+}
+
+static struct radeon_audio_basic_funcs r600_funcs = {
+	.endpoint_rreg = radeon_audio_rreg,
+	.endpoint_wreg = radeon_audio_wreg,
+	.enable = r600_audio_enable,
+};
+
+static struct radeon_audio_basic_funcs dce32_funcs = {
+	.endpoint_rreg = radeon_audio_rreg,
+	.endpoint_wreg = radeon_audio_wreg,
+	.enable = r600_audio_enable,
+};
+
+static struct radeon_audio_basic_funcs dce4_funcs = {
+	.endpoint_rreg = radeon_audio_rreg,
+	.endpoint_wreg = radeon_audio_wreg,
+	.enable = dce4_audio_enable,
+};
+
+static struct radeon_audio_basic_funcs dce6_funcs = {
+	.endpoint_rreg = dce6_endpoint_rreg,
+	.endpoint_wreg = dce6_endpoint_wreg,
+	.enable = dce6_audio_enable,
+};
+
+static struct radeon_audio_funcs r600_hdmi_funcs = {
+	.get_pin = r600_audio_get_pin,
+	.set_dto = r600_hdmi_audio_set_dto,
+	.update_acr = r600_hdmi_update_acr,
+	.set_vbi_packet = r600_set_vbi_packet,
+	.set_avi_packet = r600_set_avi_packet,
+	.set_audio_packet = r600_set_audio_packet,
+	.set_mute = r600_set_mute,
+	.mode_set = radeon_audio_hdmi_mode_set,
+	.dpms = r600_hdmi_enable,
+};
+
+static struct radeon_audio_funcs dce32_hdmi_funcs = {
+	.get_pin = r600_audio_get_pin,
+	.write_sad_regs = dce3_2_afmt_write_sad_regs,
+	.write_speaker_allocation = dce3_2_afmt_hdmi_write_speaker_allocation,
+	.set_dto = dce3_2_audio_set_dto,
+	.update_acr = dce3_2_hdmi_update_acr,
+	.set_vbi_packet = r600_set_vbi_packet,
+	.set_avi_packet = r600_set_avi_packet,
+	.set_audio_packet = dce3_2_set_audio_packet,
+	.set_mute = dce3_2_set_mute,
+	.mode_set = radeon_audio_hdmi_mode_set,
+	.dpms = r600_hdmi_enable,
+};
+
+static struct radeon_audio_funcs dce32_dp_funcs = {
+	.get_pin = r600_audio_get_pin,
+	.write_sad_regs = dce3_2_afmt_write_sad_regs,
+	.write_speaker_allocation = dce3_2_afmt_dp_write_speaker_allocation,
+	.set_dto = dce3_2_audio_set_dto,
+	.set_avi_packet = r600_set_avi_packet,
+	.set_audio_packet = dce3_2_set_audio_packet,
+};
+
+static struct radeon_audio_funcs dce4_hdmi_funcs = {
+	.get_pin = r600_audio_get_pin,
+	.write_sad_regs = evergreen_hdmi_write_sad_regs,
+	.write_speaker_allocation = dce4_afmt_hdmi_write_speaker_allocation,
+	.write_latency_fields = dce4_afmt_write_latency_fields,
+	.set_dto = dce4_hdmi_audio_set_dto,
+	.update_acr = evergreen_hdmi_update_acr,
+	.set_vbi_packet = dce4_set_vbi_packet,
+	.set_color_depth = dce4_hdmi_set_color_depth,
+	.set_avi_packet = evergreen_set_avi_packet,
+	.set_audio_packet = dce4_set_audio_packet,
+	.set_mute = dce4_set_mute,
+	.mode_set = radeon_audio_hdmi_mode_set,
+	.dpms = evergreen_hdmi_enable,
+};
+
+static struct radeon_audio_funcs dce4_dp_funcs = {
+	.get_pin = r600_audio_get_pin,
+	.write_sad_regs = evergreen_hdmi_write_sad_regs,
+	.write_speaker_allocation = dce4_afmt_dp_write_speaker_allocation,
+	.write_latency_fields = dce4_afmt_write_latency_fields,
+	.set_dto = dce4_dp_audio_set_dto,
+	.set_avi_packet = evergreen_set_avi_packet,
+	.set_audio_packet = dce4_set_audio_packet,
+	.mode_set = radeon_audio_dp_mode_set,
+	.dpms = evergreen_enable_dp_audio_packets,
+};
+
+static struct radeon_audio_funcs dce6_hdmi_funcs = {
+	.select_pin = dce6_afmt_select_pin,
+	.get_pin = dce6_audio_get_pin,
+	.write_sad_regs = dce6_afmt_write_sad_regs,
+	.write_speaker_allocation = dce6_afmt_hdmi_write_speaker_allocation,
+	.write_latency_fields = dce6_afmt_write_latency_fields,
+	.set_dto = dce6_hdmi_audio_set_dto,
+	.update_acr = evergreen_hdmi_update_acr,
+	.set_vbi_packet = dce4_set_vbi_packet,
+	.set_color_depth = dce4_hdmi_set_color_depth,
+	.set_avi_packet = evergreen_set_avi_packet,
+	.set_audio_packet = dce4_set_audio_packet,
+	.set_mute = dce4_set_mute,
+	.mode_set = radeon_audio_hdmi_mode_set,
+	.dpms = evergreen_hdmi_enable,
+};
+
+static struct radeon_audio_funcs dce6_dp_funcs = {
+	.select_pin = dce6_afmt_select_pin,
+	.get_pin = dce6_audio_get_pin,
+	.write_sad_regs = dce6_afmt_write_sad_regs,
+	.write_speaker_allocation = dce6_afmt_dp_write_speaker_allocation,
+	.write_latency_fields = dce6_afmt_write_latency_fields,
+	.set_dto = dce6_dp_audio_set_dto,
+	.set_avi_packet = evergreen_set_avi_packet,
+	.set_audio_packet = dce4_set_audio_packet,
+	.mode_set = radeon_audio_dp_mode_set,
+	.dpms = dce6_enable_dp_audio_packets,
+};
+
+static void radeon_audio_interface_init(struct radeon_device *rdev)
+{
+	if (ASIC_IS_DCE6(rdev)) {
+		rdev->audio.funcs = &dce6_funcs;
+		rdev->audio.hdmi_funcs = &dce6_hdmi_funcs;
+		rdev->audio.dp_funcs = &dce6_dp_funcs;
+	} else if (ASIC_IS_DCE4(rdev)) {
+		rdev->audio.funcs = &dce4_funcs;
+		rdev->audio.hdmi_funcs = &dce4_hdmi_funcs;
+		rdev->audio.dp_funcs = &dce4_dp_funcs;
+	} else if (ASIC_IS_DCE32(rdev)) {
+		rdev->audio.funcs = &dce32_funcs;
+		rdev->audio.hdmi_funcs = &dce32_hdmi_funcs;
+		rdev->audio.dp_funcs = &dce32_dp_funcs;
+	} else {
+		rdev->audio.funcs = &r600_funcs;
+		rdev->audio.hdmi_funcs = &r600_hdmi_funcs;
+		rdev->audio.dp_funcs = 0;
+	}
+}
+
+static int radeon_audio_chipset_supported(struct radeon_device *rdev)
+{
+	return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev);
+}
+
+int radeon_audio_init(struct radeon_device *rdev)
+{
+	int i;
+
+	if (!radeon_audio || !radeon_audio_chipset_supported(rdev))
+		return 0;
+
+	rdev->audio.enabled = true;
+
+	if (ASIC_IS_DCE83(rdev))		/* KB: 2 streams, 3 endpoints */
+		rdev->audio.num_pins = 3;
+	else if (ASIC_IS_DCE81(rdev))	/* KV: 4 streams, 7 endpoints */
+		rdev->audio.num_pins = 7;
+	else if (ASIC_IS_DCE8(rdev))	/* BN/HW: 6 streams, 7 endpoints */
+		rdev->audio.num_pins = 7;
+	else if (ASIC_IS_DCE64(rdev))	/* OL: 2 streams, 2 endpoints */
+		rdev->audio.num_pins = 2;
+	else if (ASIC_IS_DCE61(rdev))	/* TN: 4 streams, 6 endpoints */
+		rdev->audio.num_pins = 6;
+	else if (ASIC_IS_DCE6(rdev))	/* SI: 6 streams, 6 endpoints */
+		rdev->audio.num_pins = 6;
+	else
+		rdev->audio.num_pins = 1;
+
+	for (i = 0; i < rdev->audio.num_pins; i++) {
+		rdev->audio.pin[i].channels = -1;
+		rdev->audio.pin[i].rate = -1;
+		rdev->audio.pin[i].bits_per_sample = -1;
+		rdev->audio.pin[i].status_bits = 0;
+		rdev->audio.pin[i].category_code = 0;
+		rdev->audio.pin[i].connected = false;
+		rdev->audio.pin[i].offset = pin_offsets[i];
+		rdev->audio.pin[i].id = i;
+	}
+
+	radeon_audio_interface_init(rdev);
+
+	/* disable audio.  it will be set up later */
+	for (i = 0; i < rdev->audio.num_pins; i++)
+		radeon_audio_enable(rdev, &rdev->audio.pin[i], false);
+
+	return 0;
+}
+
+u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev, u32 offset, u32 reg)
+{
+	if (rdev->audio.funcs->endpoint_rreg)
+		return rdev->audio.funcs->endpoint_rreg(rdev, offset, reg);
+
+	return 0;
+}
+
+void radeon_audio_endpoint_wreg(struct radeon_device *rdev, u32 offset,
+	u32 reg, u32 v)
+{
+	if (rdev->audio.funcs->endpoint_wreg)
+		rdev->audio.funcs->endpoint_wreg(rdev, offset, reg, v);
+}
+
+static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector = NULL;
+	struct cea_sad *sads;
+	int sad_count;
+
+	list_for_each_entry(connector,
+		&encoder->dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			radeon_connector = to_radeon_connector(connector);
+			break;
+		}
+	}
+
+	if (!radeon_connector) {
+		DRM_ERROR("Couldn't find encoder's connector\n");
+		return;
+	}
+
+	sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
+	if (sad_count <= 0) {
+		DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
+		return;
+	}
+	BUG_ON(!sads);
+
+	radeon_encoder = to_radeon_encoder(encoder);
+
+	if (radeon_encoder->audio && radeon_encoder->audio->write_sad_regs)
+		radeon_encoder->audio->write_sad_regs(encoder, sads, sad_count);
+
+	kfree(sads);
+}
+
+static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector = NULL;
+	u8 *sadb = NULL;
+	int sad_count;
+
+	list_for_each_entry(connector,
+			    &encoder->dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			radeon_connector = to_radeon_connector(connector);
+			break;
+		}
+	}
+
+	if (!radeon_connector) {
+		DRM_ERROR("Couldn't find encoder's connector\n");
+		return;
+	}
+
+	sad_count = drm_edid_to_speaker_allocation(
+		radeon_connector_edid(connector), &sadb);
+	if (sad_count < 0) {
+		DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n",
+			  sad_count);
+		sad_count = 0;
+	}
+
+	if (radeon_encoder->audio && radeon_encoder->audio->write_speaker_allocation)
+		radeon_encoder->audio->write_speaker_allocation(encoder, sadb, sad_count);
+
+	kfree(sadb);
+}
+
+static void radeon_audio_write_latency_fields(struct drm_encoder *encoder,
+	struct drm_display_mode *mode)
+{
+	struct radeon_encoder *radeon_encoder;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector = 0;
+
+	list_for_each_entry(connector,
+		&encoder->dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			radeon_connector = to_radeon_connector(connector);
+			break;
+		}
+	}
+
+	if (!radeon_connector) {
+		DRM_ERROR("Couldn't find encoder's connector\n");
+		return;
+	}
+
+	radeon_encoder = to_radeon_encoder(encoder);
+
+	if (radeon_encoder->audio && radeon_encoder->audio->write_latency_fields)
+		radeon_encoder->audio->write_latency_fields(encoder, connector, mode);
+}
+
+struct r600_audio_pin* radeon_audio_get_pin(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	if (radeon_encoder->audio && radeon_encoder->audio->get_pin)
+		return radeon_encoder->audio->get_pin(rdev);
+
+	return NULL;
+}
+
+static void radeon_audio_select_pin(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	if (radeon_encoder->audio && radeon_encoder->audio->select_pin)
+		radeon_encoder->audio->select_pin(encoder);
+}
+
+void radeon_audio_enable(struct radeon_device *rdev,
+	struct r600_audio_pin *pin, u8 enable_mask)
+{
+	if (rdev->audio.funcs->enable)
+		rdev->audio.funcs->enable(rdev, pin, enable_mask);
+}
+
+void radeon_audio_detect(struct drm_connector *connector,
+	enum drm_connector_status status)
+{
+	struct radeon_device *rdev;
+	struct radeon_encoder *radeon_encoder;
+	struct radeon_encoder_atom_dig *dig;
+
+	if (!connector || !connector->encoder)
+		return;
+
+	rdev = connector->encoder->dev->dev_private;
+	radeon_encoder = to_radeon_encoder(connector->encoder);
+	dig = radeon_encoder->enc_priv;
+
+	if (status == connector_status_connected) {
+		struct radeon_connector *radeon_connector;
+		int sink_type;
+
+		if (!drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+			radeon_encoder->audio = NULL;
+			return;
+		}
+
+		radeon_connector = to_radeon_connector(connector);
+		sink_type = radeon_dp_getsinktype(radeon_connector);
+
+		if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort &&
+			sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
+			radeon_encoder->audio = rdev->audio.dp_funcs;
+		else
+			radeon_encoder->audio = rdev->audio.hdmi_funcs;
+
+		radeon_audio_write_speaker_allocation(connector->encoder);
+		radeon_audio_write_sad_regs(connector->encoder);
+		if (connector->encoder->crtc)
+			radeon_audio_write_latency_fields(connector->encoder,
+				&connector->encoder->crtc->mode);
+		radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
+	} else {
+		radeon_audio_enable(rdev, dig->afmt->pin, 0);
+	}
+}
+
+void radeon_audio_fini(struct radeon_device *rdev)
+{
+	int i;
+
+	if (!rdev->audio.enabled)
+		return;
+
+	for (i = 0; i < rdev->audio.num_pins; i++)
+		radeon_audio_enable(rdev, &rdev->audio.pin[i], false);
+
+	rdev->audio.enabled = false;
+}
+
+static void radeon_audio_set_dto(struct drm_encoder *encoder, unsigned int clock)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_crtc *crtc = to_radeon_crtc(encoder->crtc);
+
+	if (radeon_encoder->audio && radeon_encoder->audio->set_dto)
+		radeon_encoder->audio->set_dto(rdev, crtc, clock);
+}
+
+static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
+	struct drm_display_mode *mode)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
+	struct hdmi_avi_infoframe frame;
+	int err;
+
+	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+	if (err < 0) {
+		DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
+		return err;
+	}
+
+	err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
+	if (err < 0) {
+		DRM_ERROR("failed to pack AVI infoframe: %d\n", err);
+		return err;
+	}
+
+	if (dig && dig->afmt &&
+		radeon_encoder->audio && radeon_encoder->audio->set_avi_packet)
+		radeon_encoder->audio->set_avi_packet(rdev, dig->afmt->offset,
+			buffer, sizeof(buffer));
+
+	return 0;
+}
+
+/*
+ * calculate CTS and N values if they are not found in the table
+ */
+static void radeon_audio_calc_cts(unsigned int clock, int *CTS, int *N, int freq)
+{
+	int n, cts;
+	unsigned long div, mul;
+
+	/* Safe, but overly large values */
+	n = 128 * freq;
+	cts = clock * 1000;
+
+	/* Smallest valid fraction */
+	div = gcd(n, cts);
+
+	n /= div;
+	cts /= div;
+
+	/*
+	 * The optimal N is 128*freq/1000. Calculate the closest larger
+	 * value that doesn't truncate any bits.
+	 */
+	mul = ((128*freq/1000) + (n-1))/n;
+
+	n *= mul;
+	cts *= mul;
+
+	/* Check that we are in spec (not always possible) */
+	if (n < (128*freq/1500))
+		printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n");
+	if (n > (128*freq/300))
+		printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n");
+
+	*N = n;
+	*CTS = cts;
+
+	DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n",
+		*N, *CTS, freq);
+}
+
+static const struct radeon_hdmi_acr* radeon_audio_acr(unsigned int clock)
+{
+	static struct radeon_hdmi_acr res;
+	u8 i;
+
+	static const struct radeon_hdmi_acr hdmi_predefined_acr[] = {
+		/*       32kHz    44.1kHz   48kHz    */
+		/* Clock      N     CTS      N     CTS      N     CTS */
+		{  25175,  4096,  25175, 28224, 125875,  6144,  25175 }, /*  25,20/1.001 MHz */
+		{  25200,  4096,  25200,  6272,  28000,  6144,  25200 }, /*  25.20       MHz */
+		{  27000,  4096,  27000,  6272,  30000,  6144,  27000 }, /*  27.00       MHz */
+		{  27027,  4096,  27027,  6272,  30030,  6144,  27027 }, /*  27.00*1.001 MHz */
+		{  54000,  4096,  54000,  6272,  60000,  6144,  54000 }, /*  54.00       MHz */
+		{  54054,  4096,  54054,  6272,  60060,  6144,  54054 }, /*  54.00*1.001 MHz */
+		{  74176,  4096,  74176,  5733,  75335,  6144,  74176 }, /*  74.25/1.001 MHz */
+		{  74250,  4096,  74250,  6272,  82500,  6144,  74250 }, /*  74.25       MHz */
+		{ 148352,  4096, 148352,  5733, 150670,  6144, 148352 }, /* 148.50/1.001 MHz */
+		{ 148500,  4096, 148500,  6272, 165000,  6144, 148500 }, /* 148.50       MHz */
+	};
+
+	/* Precalculated values for common clocks */
+	for (i = 0; i < ARRAY_SIZE(hdmi_predefined_acr); i++)
+		if (hdmi_predefined_acr[i].clock == clock)
+			return &hdmi_predefined_acr[i];
+
+	/* And odd clocks get manually calculated */
+	radeon_audio_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000);
+	radeon_audio_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100);
+	radeon_audio_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000);
+
+	return &res;
+}
+
+/*
+ * update the N and CTS parameters for a given pixel clock rate
+ */
+static void radeon_audio_update_acr(struct drm_encoder *encoder, unsigned int clock)
+{
+	const struct radeon_hdmi_acr *acr = radeon_audio_acr(clock);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+	if (!dig || !dig->afmt)
+		return;
+
+	if (radeon_encoder->audio && radeon_encoder->audio->update_acr)
+		radeon_encoder->audio->update_acr(encoder, dig->afmt->offset, acr);
+}
+
+static void radeon_audio_set_vbi_packet(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+	if (!dig || !dig->afmt)
+		return;
+
+	if (radeon_encoder->audio && radeon_encoder->audio->set_vbi_packet)
+		radeon_encoder->audio->set_vbi_packet(encoder, dig->afmt->offset);
+}
+
+static void radeon_hdmi_set_color_depth(struct drm_encoder *encoder)
+{
+	int bpc = 8;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+	if (!dig || !dig->afmt)
+		return;
+
+	if (encoder->crtc) {
+		struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+		bpc = radeon_crtc->bpc;
+	}
+
+	if (radeon_encoder->audio && radeon_encoder->audio->set_color_depth)
+		radeon_encoder->audio->set_color_depth(encoder, dig->afmt->offset, bpc);
+}
+
+static void radeon_audio_set_audio_packet(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+	if (!dig || !dig->afmt)
+		return;
+
+	if (radeon_encoder->audio && radeon_encoder->audio->set_audio_packet)
+		radeon_encoder->audio->set_audio_packet(encoder, dig->afmt->offset);
+}
+
+static void radeon_audio_set_mute(struct drm_encoder *encoder, bool mute)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+	if (!dig || !dig->afmt)
+		return;
+
+	if (radeon_encoder->audio && radeon_encoder->audio->set_mute)
+		radeon_encoder->audio->set_mute(encoder, dig->afmt->offset, mute);
+}
+
+/*
+ * update the info frames with the data from the current display mode
+ */
+static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder,
+	struct drm_display_mode *mode)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+	if (!dig || !dig->afmt)
+		return;
+
+	/* disable audio prior to setting up hw */
+	dig->afmt->pin = radeon_audio_get_pin(encoder);
+	radeon_audio_enable(rdev, dig->afmt->pin, 0);
+
+	radeon_audio_set_dto(encoder, mode->clock);
+	radeon_audio_set_vbi_packet(encoder);
+	radeon_hdmi_set_color_depth(encoder);
+	radeon_audio_set_mute(encoder, false);
+	radeon_audio_update_acr(encoder, mode->clock);
+	radeon_audio_set_audio_packet(encoder);
+	radeon_audio_select_pin(encoder);
+
+	if (radeon_audio_set_avi_packet(encoder, mode) < 0)
+		return;
+
+	/* enable audio after to setting up hw */
+	radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
+}
+
+static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
+	struct drm_display_mode *mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+	if (!dig || !dig->afmt)
+		return;
+
+	/* disable audio prior to setting up hw */
+	dig->afmt->pin = radeon_audio_get_pin(encoder);
+	radeon_audio_enable(rdev, dig->afmt->pin, 0);
+
+	radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10);
+	radeon_audio_set_audio_packet(encoder);
+	radeon_audio_select_pin(encoder);
+
+	if (radeon_audio_set_avi_packet(encoder, mode) < 0)
+		return;
+
+	/* enable audio after to setting up hw */
+	radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
+}
+
+void radeon_audio_mode_set(struct drm_encoder *encoder,
+	struct drm_display_mode *mode)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	if (radeon_encoder->audio && radeon_encoder->audio->mode_set)
+		radeon_encoder->audio->mode_set(encoder, mode);
+}
+
+void radeon_audio_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	if (radeon_encoder->audio && radeon_encoder->audio->dpms)
+		radeon_encoder->audio->dpms(encoder, mode == DRM_MODE_DPMS_ON);
+}

+ 84 - 0
drivers/gpu/drm/radeon/radeon_audio.h

@@ -0,0 +1,84 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Slava Grigorev <slava.grigorev@amd.com>
+ */
+
+#ifndef __RADEON_AUDIO_H__
+#define __RADEON_AUDIO_H__
+
+#include <linux/types.h>
+
+#define RREG32_ENDPOINT(block, reg)		\
+	radeon_audio_endpoint_rreg(rdev, (block), (reg))
+#define WREG32_ENDPOINT(block, reg, v)	\
+	radeon_audio_endpoint_wreg(rdev, (block), (reg), (v))
+
+struct radeon_audio_basic_funcs
+{
+	u32  (*endpoint_rreg)(struct radeon_device *rdev, u32 offset, u32 reg);
+	void (*endpoint_wreg)(struct radeon_device *rdev,
+		u32 offset, u32 reg, u32 v);
+	void (*enable)(struct radeon_device *rdev,
+		struct r600_audio_pin *pin, u8 enable_mask);
+};
+
+struct radeon_audio_funcs
+{
+	void (*select_pin)(struct drm_encoder *encoder);
+	struct r600_audio_pin* (*get_pin)(struct radeon_device *rdev);
+	void (*write_latency_fields)(struct drm_encoder *encoder,
+		struct drm_connector *connector, struct drm_display_mode *mode);
+	void (*write_sad_regs)(struct drm_encoder *encoder,
+		struct cea_sad *sads, int sad_count);
+	void (*write_speaker_allocation)(struct drm_encoder *encoder,
+		u8 *sadb, int sad_count);
+	void (*set_dto)(struct radeon_device *rdev,
+		struct radeon_crtc *crtc, unsigned int clock);
+	void (*update_acr)(struct drm_encoder *encoder, long offset,
+		const struct radeon_hdmi_acr *acr);
+	void (*set_vbi_packet)(struct drm_encoder *encoder, u32 offset);
+	void (*set_color_depth)(struct drm_encoder *encoder, u32 offset, int bpc);
+	void (*set_avi_packet)(struct radeon_device *rdev, u32 offset,
+		unsigned char *buffer, size_t size);
+	void (*set_audio_packet)(struct drm_encoder *encoder, u32 offset);
+	void (*set_mute)(struct drm_encoder *encoder, u32 offset, bool mute);
+	void (*mode_set)(struct drm_encoder *encoder,
+		struct drm_display_mode *mode);
+	void (*dpms)(struct drm_encoder *encoder, bool mode);
+};
+
+int radeon_audio_init(struct radeon_device *rdev);
+void radeon_audio_detect(struct drm_connector *connector,
+	enum drm_connector_status status);
+u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev,
+	u32 offset, u32 reg);
+void radeon_audio_endpoint_wreg(struct radeon_device *rdev,
+	u32 offset,	u32 reg, u32 v);
+struct r600_audio_pin *radeon_audio_get_pin(struct drm_encoder *encoder);
+void radeon_audio_enable(struct radeon_device *rdev,
+	struct r600_audio_pin *pin, u8 enable_mask);
+void radeon_audio_fini(struct radeon_device *rdev);
+void radeon_audio_mode_set(struct drm_encoder *encoder,
+	struct drm_display_mode *mode);
+void radeon_audio_dpms(struct drm_encoder *encoder, int mode);
+
+#endif

+ 8 - 0
drivers/gpu/drm/radeon/radeon_connectors.c

@@ -29,6 +29,7 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/radeon_drm.h>
 #include "radeon.h"
+#include "radeon_audio.h"
 #include "atom.h"
 
 #include <linux/pm_runtime.h>
@@ -1332,6 +1333,9 @@ out:
 	/* updated in get modes as well since we need to know if it's analog or digital */
 	radeon_connector_update_scratch_regs(connector, ret);
 
+	if (radeon_audio != 0)
+		radeon_audio_detect(connector, ret);
+
 exit:
 	pm_runtime_mark_last_busy(connector->dev->dev);
 	pm_runtime_put_autosuspend(connector->dev->dev);
@@ -1654,6 +1658,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
 	}
 
 	radeon_connector_update_scratch_regs(connector, ret);
+
+	if (radeon_audio != 0)
+		radeon_audio_detect(connector, ret);
+
 out:
 	pm_runtime_mark_last_busy(connector->dev->dev);
 	pm_runtime_put_autosuspend(connector->dev->dev);

+ 2 - 1
drivers/gpu/drm/radeon/radeon_drv.c

@@ -88,9 +88,10 @@
  *   2.39.0 - Add INFO query for number of active CUs
  *   2.40.0 - Add RADEON_GEM_GTT_WC/UC, flush HDP cache before submitting
  *            CS to GPU on >= r600
+ *   2.41.0 - evergreen/cayman: Add SET_BASE/DRAW_INDIRECT command parsing support
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	40
+#define KMS_DRIVER_MINOR	41
 #define KMS_DRIVER_PATCHLEVEL	0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);

+ 0 - 10
drivers/gpu/drm/radeon/radeon_fb.c

@@ -428,16 +428,6 @@ void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state)
 	fb_set_suspend(rdev->mode_info.rfbdev->helper.fbdev, state);
 }
 
-int radeon_fbdev_total_size(struct radeon_device *rdev)
-{
-	struct radeon_bo *robj;
-	int size = 0;
-
-	robj = gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj);
-	size += radeon_bo_size(robj);
-	return size;
-}
-
 bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
 {
 	if (robj == gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj))

+ 0 - 5
drivers/gpu/drm/radeon/radeon_i2c.c

@@ -1048,11 +1048,6 @@ struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev,
 	return NULL;
 }
 
-struct drm_encoder *radeon_best_encoder(struct drm_connector *connector)
-{
-	return NULL;
-}
-
 void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus,
 			 u8 slave_addr,
 			 u8 addr,

+ 1 - 3
drivers/gpu/drm/radeon/radeon_mode.h

@@ -449,6 +449,7 @@ struct radeon_encoder {
 	int audio_polling_active;
 	bool is_ext_encoder;
 	u16 caps;
+	struct radeon_audio_funcs *audio;
 };
 
 struct radeon_connector_atom_dig {
@@ -745,8 +746,6 @@ extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connec
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
 extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux);
 
-extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
-
 extern bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev,
 					     struct radeon_atom_ss *ss,
 					     int id);
@@ -925,7 +924,6 @@ void dce8_program_fmt(struct drm_encoder *encoder);
 int radeon_fbdev_init(struct radeon_device *rdev);
 void radeon_fbdev_fini(struct radeon_device *rdev);
 void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state);
-int radeon_fbdev_total_size(struct radeon_device *rdev);
 bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj);
 
 void radeon_fb_output_poll_changed(struct radeon_device *rdev);

+ 0 - 6
drivers/gpu/drm/radeon/radeon_object.c

@@ -576,12 +576,6 @@ int radeon_bo_list_validate(struct radeon_device *rdev,
 	return 0;
 }
 
-int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
-			     struct vm_area_struct *vma)
-{
-	return ttm_fbdev_mmap(vma, &bo->tbo);
-}
-
 int radeon_bo_get_surface_reg(struct radeon_bo *bo)
 {
 	struct radeon_device *rdev = bo->rdev;

+ 0 - 2
drivers/gpu/drm/radeon/radeon_object.h

@@ -143,8 +143,6 @@ extern void radeon_bo_fini(struct radeon_device *rdev);
 extern int radeon_bo_list_validate(struct radeon_device *rdev,
 				   struct ww_acquire_ctx *ticket,
 				   struct list_head *head, int ring);
-extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
-				struct vm_area_struct *vma);
 extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
 				u32 tiling_flags, u32 pitch);
 extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo,

+ 130 - 1
drivers/gpu/drm/radeon/radeon_pm.c

@@ -24,6 +24,7 @@
 #include "radeon.h"
 #include "avivod.h"
 #include "atom.h"
+#include "r600_dpm.h"
 #include <linux/power_supply.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
@@ -554,6 +555,96 @@ fail:
 	return count;
 }
 
+static ssize_t radeon_hwmon_get_pwm1_enable(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct radeon_device *rdev = dev_get_drvdata(dev);
+	u32 pwm_mode = 0;
+
+	if (rdev->asic->dpm.fan_ctrl_get_mode)
+		pwm_mode = rdev->asic->dpm.fan_ctrl_get_mode(rdev);
+
+	/* never 0 (full-speed), fuse or smc-controlled always */
+	return sprintf(buf, "%i\n", pwm_mode == FDO_PWM_MODE_STATIC ? 1 : 2);
+}
+
+static ssize_t radeon_hwmon_set_pwm1_enable(struct device *dev,
+					    struct device_attribute *attr,
+					    const char *buf,
+					    size_t count)
+{
+	struct radeon_device *rdev = dev_get_drvdata(dev);
+	int err;
+	int value;
+
+	if(!rdev->asic->dpm.fan_ctrl_set_mode)
+		return -EINVAL;
+
+	err = kstrtoint(buf, 10, &value);
+	if (err)
+		return err;
+
+	switch(value) {
+	case 1: /* manual, percent-based */
+		rdev->asic->dpm.fan_ctrl_set_mode(rdev, FDO_PWM_MODE_STATIC);
+		break;
+	default: /* disable */
+		rdev->asic->dpm.fan_ctrl_set_mode(rdev, 0);
+		break;
+	}
+
+	return count;
+}
+
+static ssize_t radeon_hwmon_get_pwm1_min(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	return sprintf(buf, "%i\n", 0);
+}
+
+static ssize_t radeon_hwmon_get_pwm1_max(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	return sprintf(buf, "%i\n", 100); /* pwm uses percent-based fan-control */
+}
+
+static ssize_t radeon_hwmon_set_pwm1(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct radeon_device *rdev = dev_get_drvdata(dev);
+	int err;
+	u32 value;
+
+	err = kstrtou32(buf, 10, &value);
+	if (err)
+		return err;
+
+	err = rdev->asic->dpm.set_fan_speed_percent(rdev, value);
+	if (err)
+		return err;
+
+	return count;
+}
+
+static ssize_t radeon_hwmon_get_pwm1(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct radeon_device *rdev = dev_get_drvdata(dev);
+	int err;
+	u32 speed;
+
+	err = rdev->asic->dpm.get_fan_speed_percent(rdev, &speed);
+	if (err)
+		return err;
+
+	return sprintf(buf, "%i\n", speed);
+}
+
 static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile);
 static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method);
 static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, radeon_get_dpm_state, radeon_set_dpm_state);
@@ -601,11 +692,20 @@ static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev,
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, radeon_hwmon_show_temp, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 1);
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, radeon_hwmon_get_pwm1, radeon_hwmon_set_pwm1, 0);
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, radeon_hwmon_get_pwm1_enable, radeon_hwmon_set_pwm1_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, radeon_hwmon_get_pwm1_min, NULL, 0);
+static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, radeon_hwmon_get_pwm1_max, NULL, 0);
+
 
 static struct attribute *hwmon_attributes[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
 	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm1_min.dev_attr.attr,
+	&sensor_dev_attr_pwm1_max.dev_attr.attr,
 	NULL
 };
 
@@ -614,6 +714,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct radeon_device *rdev = dev_get_drvdata(dev);
+	umode_t effective_mode = attr->mode;
 
 	/* Skip limit attributes if DPM is not enabled */
 	if (rdev->pm.pm_method != PM_METHOD_DPM &&
@@ -621,7 +722,35 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
 	     attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
 		return 0;
 
-	return attr->mode;
+	/* Skip fan attributes if fan is not present */
+	if (rdev->pm.no_fan &&
+	    (attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
+	     attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
+	     attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
+	     attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
+		return 0;
+
+	/* mask fan attributes if we have no bindings for this asic to expose */
+	if ((!rdev->asic->dpm.get_fan_speed_percent &&
+	     attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */
+	    (!rdev->asic->dpm.fan_ctrl_get_mode &&
+	     attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't query state */
+		effective_mode &= ~S_IRUGO;
+
+	if ((!rdev->asic->dpm.set_fan_speed_percent &&
+	     attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't manage fan */
+	    (!rdev->asic->dpm.fan_ctrl_set_mode &&
+	     attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */
+		effective_mode &= ~S_IWUSR;
+
+	/* hide max/min values if we can't both query and manage the fan */
+	if ((!rdev->asic->dpm.set_fan_speed_percent &&
+	     !rdev->asic->dpm.get_fan_speed_percent) &&
+	    (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
+	     attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
+		return 0;
+
+	return effective_mode;
 }
 
 static const struct attribute_group hwmon_attrgroup = {

+ 4 - 3
drivers/gpu/drm/radeon/rs600.c

@@ -38,6 +38,7 @@
 #include <drm/drmP.h>
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include "atom.h"
 #include "rs600d.h"
 
@@ -1012,7 +1013,7 @@ static int rs600_startup(struct radeon_device *rdev)
 		return r;
 	}
 
-	r = r600_audio_init(rdev);
+	r = radeon_audio_init(rdev);
 	if (r) {
 		dev_err(rdev->dev, "failed initializing audio\n");
 		return r;
@@ -1053,7 +1054,7 @@ int rs600_resume(struct radeon_device *rdev)
 int rs600_suspend(struct radeon_device *rdev)
 {
 	radeon_pm_suspend(rdev);
-	r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	r100_cp_disable(rdev);
 	radeon_wb_disable(rdev);
 	rs600_irq_disable(rdev);
@@ -1064,7 +1065,7 @@ int rs600_suspend(struct radeon_device *rdev)
 void rs600_fini(struct radeon_device *rdev)
 {
 	radeon_pm_fini(rdev);
-	r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	r100_cp_fini(rdev);
 	radeon_wb_fini(rdev);
 	radeon_ib_pool_fini(rdev);

+ 4 - 3
drivers/gpu/drm/radeon/rs690.c

@@ -28,6 +28,7 @@
 #include <drm/drmP.h>
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include "atom.h"
 #include "rs690d.h"
 
@@ -729,7 +730,7 @@ static int rs690_startup(struct radeon_device *rdev)
 		return r;
 	}
 
-	r = r600_audio_init(rdev);
+	r = radeon_audio_init(rdev);
 	if (r) {
 		dev_err(rdev->dev, "failed initializing audio\n");
 		return r;
@@ -770,7 +771,7 @@ int rs690_resume(struct radeon_device *rdev)
 int rs690_suspend(struct radeon_device *rdev)
 {
 	radeon_pm_suspend(rdev);
-	r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	r100_cp_disable(rdev);
 	radeon_wb_disable(rdev);
 	rs600_irq_disable(rdev);
@@ -781,7 +782,7 @@ int rs690_suspend(struct radeon_device *rdev)
 void rs690_fini(struct radeon_device *rdev)
 {
 	radeon_pm_fini(rdev);
-	r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	r100_cp_fini(rdev);
 	radeon_wb_fini(rdev);
 	radeon_ib_pool_fini(rdev);

+ 3 - 2
drivers/gpu/drm/radeon/rv770.c

@@ -30,6 +30,7 @@
 #include <drm/drmP.h>
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include <drm/radeon_drm.h>
 #include "rv770d.h"
 #include "atom.h"
@@ -1788,7 +1789,7 @@ static int rv770_startup(struct radeon_device *rdev)
 		return r;
 	}
 
-	r = r600_audio_init(rdev);
+	r = radeon_audio_init(rdev);
 	if (r) {
 		DRM_ERROR("radeon: audio init failed\n");
 		return r;
@@ -1829,7 +1830,7 @@ int rv770_resume(struct radeon_device *rdev)
 int rv770_suspend(struct radeon_device *rdev)
 {
 	radeon_pm_suspend(rdev);
-	r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	uvd_v1_0_fini(rdev);
 	radeon_uvd_suspend(rdev);
 	r700_cp_stop(rdev);

+ 4 - 0
drivers/gpu/drm/radeon/rv770_dpm.c

@@ -231,6 +231,7 @@ u8 rv770_get_seq_value(struct radeon_device *rdev,
 		MC_CG_SEQ_DRAMCONF_S0 : MC_CG_SEQ_DRAMCONF_S1;
 }
 
+#if 0
 int rv770_read_smc_soft_register(struct radeon_device *rdev,
 				 u16 reg_offset, u32 *value)
 {
@@ -240,6 +241,7 @@ int rv770_read_smc_soft_register(struct radeon_device *rdev,
 					 pi->soft_regs_start + reg_offset,
 					 value, pi->sram_end);
 }
+#endif
 
 int rv770_write_smc_soft_register(struct radeon_device *rdev,
 				  u16 reg_offset, u32 value)
@@ -2075,6 +2077,7 @@ int rv770_dpm_set_power_state(struct radeon_device *rdev)
 	return 0;
 }
 
+#if 0
 void rv770_dpm_reset_asic(struct radeon_device *rdev)
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
@@ -2087,6 +2090,7 @@ void rv770_dpm_reset_asic(struct radeon_device *rdev)
 	if (pi->dcodt)
 		rv770_program_dcodt_after_state_switch(rdev, boot_ps, boot_ps);
 }
+#endif
 
 void rv770_dpm_setup_asic(struct radeon_device *rdev)
 {

+ 0 - 2
drivers/gpu/drm/radeon/rv770_dpm.h

@@ -278,8 +278,6 @@ void rv770_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
 void rv770_get_engine_memory_ss(struct radeon_device *rdev);
 
 /* smc */
-int rv770_read_smc_soft_register(struct radeon_device *rdev,
-				 u16 reg_offset, u32 *value);
 int rv770_write_smc_soft_register(struct radeon_device *rdev,
 				  u16 reg_offset, u32 value);
 

+ 3 - 2
drivers/gpu/drm/radeon/si.c

@@ -27,6 +27,7 @@
 #include <drm/drmP.h>
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include <drm/radeon_drm.h>
 #include "sid.h"
 #include "atom.h"
@@ -6869,7 +6870,7 @@ static int si_startup(struct radeon_device *rdev)
 		return r;
 	}
 
-	r = dce6_audio_init(rdev);
+	r = radeon_audio_init(rdev);
 	if (r)
 		return r;
 
@@ -6908,7 +6909,7 @@ int si_resume(struct radeon_device *rdev)
 int si_suspend(struct radeon_device *rdev)
 {
 	radeon_pm_suspend(rdev);
-	dce6_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	radeon_vm_manager_fini(rdev);
 	si_cp_enable(rdev, false);
 	cayman_dma_stop(rdev);

+ 59 - 16
drivers/gpu/drm/radeon/si_dpm.c

@@ -1756,6 +1756,9 @@ static int si_calculate_sclk_params(struct radeon_device *rdev,
 				    u32 engine_clock,
 				    SISLANDS_SMC_SCLK_VALUE *sclk);
 
+static void si_thermal_start_smc_fan_control(struct radeon_device *rdev);
+static void si_fan_ctrl_set_default_mode(struct radeon_device *rdev);
+
 static struct si_power_info *si_get_pi(struct radeon_device *rdev)
 {
         struct si_power_info *pi = rdev->pm.dpm.priv;
@@ -3359,11 +3362,13 @@ int si_dpm_force_performance_level(struct radeon_device *rdev,
 	return 0;
 }
 
+#if 0
 static int si_set_boot_state(struct radeon_device *rdev)
 {
 	return (si_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ?
 		0 : -EINVAL;
 }
+#endif
 
 static int si_set_sw_state(struct radeon_device *rdev)
 {
@@ -5973,6 +5978,10 @@ static int si_thermal_setup_fan_table(struct radeon_device *rdev)
 	slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
 	slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
 
+	fan_table.temp_min = cpu_to_be16((50 + rdev->pm.dpm.fan.t_min) / 100);
+	fan_table.temp_med = cpu_to_be16((50 + rdev->pm.dpm.fan.t_med) / 100);
+	fan_table.temp_max = cpu_to_be16((50 + rdev->pm.dpm.fan.t_max) / 100);
+
 	fan_table.slope1 = cpu_to_be16(slope1);
 	fan_table.slope2 = cpu_to_be16(slope2);
 
@@ -6012,29 +6021,35 @@ static int si_thermal_setup_fan_table(struct radeon_device *rdev)
 
 static int si_fan_ctrl_start_smc_fan_control(struct radeon_device *rdev)
 {
+	struct si_power_info *si_pi = si_get_pi(rdev);
 	PPSMC_Result ret;
 
 	ret = si_send_msg_to_smc(rdev, PPSMC_StartFanControl);
-	if (ret == PPSMC_Result_OK)
+	if (ret == PPSMC_Result_OK) {
+		si_pi->fan_is_controlled_by_smc = true;
 		return 0;
-	else
+	} else {
 		return -EINVAL;
+	}
 }
 
 static int si_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev)
 {
+	struct si_power_info *si_pi = si_get_pi(rdev);
 	PPSMC_Result ret;
 
 	ret = si_send_msg_to_smc(rdev, PPSMC_StopFanControl);
-	if (ret == PPSMC_Result_OK)
+
+	if (ret == PPSMC_Result_OK) {
+		si_pi->fan_is_controlled_by_smc = false;
 		return 0;
-	else
+	} else {
 		return -EINVAL;
+	}
 }
 
-#if 0
-static int si_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
-					     u32 *speed)
+int si_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
+				      u32 *speed)
 {
 	u32 duty, duty100;
 	u64 tmp64;
@@ -6058,9 +6073,10 @@ static int si_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
 	return 0;
 }
 
-static int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
-					     u32 speed)
+int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
+				      u32 speed)
 {
+	struct si_power_info *si_pi = si_get_pi(rdev);
 	u32 tmp;
 	u32 duty, duty100;
 	u64 tmp64;
@@ -6068,11 +6084,11 @@ static int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
 	if (rdev->pm.no_fan)
 		return -ENOENT;
 
-	if (speed > 100)
+	if (si_pi->fan_is_controlled_by_smc)
 		return -EINVAL;
 
-	if (rdev->pm.dpm.fan.ucode_fan_control)
-		si_fan_ctrl_stop_smc_fan_control(rdev);
+	if (speed > 100)
+		return -EINVAL;
 
 	duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT;
 
@@ -6087,11 +6103,38 @@ static int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
 	tmp |= FDO_STATIC_DUTY(duty);
 	WREG32(CG_FDO_CTRL0, tmp);
 
-	si_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC);
-
 	return 0;
 }
 
+void si_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode)
+{
+	if (mode) {
+		/* stop auto-manage */
+		if (rdev->pm.dpm.fan.ucode_fan_control)
+			si_fan_ctrl_stop_smc_fan_control(rdev);
+		si_fan_ctrl_set_static_mode(rdev, mode);
+	} else {
+		/* restart auto-manage */
+		if (rdev->pm.dpm.fan.ucode_fan_control)
+			si_thermal_start_smc_fan_control(rdev);
+		else
+			si_fan_ctrl_set_default_mode(rdev);
+	}
+}
+
+u32 si_fan_ctrl_get_mode(struct radeon_device *rdev)
+{
+	struct si_power_info *si_pi = si_get_pi(rdev);
+	u32 tmp;
+
+	if (si_pi->fan_is_controlled_by_smc)
+		return 0;
+
+	tmp = RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK;
+	return (tmp >> FDO_PWM_MODE_SHIFT);
+}
+
+#if 0
 static int si_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev,
 					 u32 *speed)
 {
@@ -6538,13 +6581,14 @@ void si_dpm_post_set_power_state(struct radeon_device *rdev)
 	ni_update_current_ps(rdev, new_ps);
 }
 
-
+#if 0
 void si_dpm_reset_asic(struct radeon_device *rdev)
 {
 	si_restrict_performance_levels_before_switch(rdev);
 	si_disable_ulv(rdev);
 	si_set_boot_state(rdev);
 }
+#endif
 
 void si_dpm_display_configuration_changed(struct radeon_device *rdev)
 {
@@ -6912,7 +6956,6 @@ int si_dpm_init(struct radeon_device *rdev)
 			rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
 
 	si_pi->fan_ctrl_is_in_default_mode = true;
-	rdev->pm.dpm.fan.ucode_fan_control = false;
 
 	return 0;
 }

+ 1 - 0
drivers/gpu/drm/radeon/si_dpm.h

@@ -202,6 +202,7 @@ struct si_power_info {
 	bool fan_ctrl_is_in_default_mode;
 	u32 t_min;
 	u32 fan_ctrl_default_mode;
+	bool fan_is_controlled_by_smc;
 };
 
 #define SISLANDS_INITIAL_STATE_ARB_INDEX    0

+ 10 - 0
drivers/gpu/drm/radeon/sid.h

@@ -901,6 +901,16 @@
 /* 0x6e98, 0x7a98, 0x10698, 0x11298, 0x11e98, 0x12a98 */
 #define CRTC_STATUS_FRAME_COUNT                         0x6e98
 
+/* Audio clocks */
+#define DCCG_AUDIO_DTO_SOURCE                           0x05ac
+#       define DCCG_AUDIO_DTO0_SOURCE_SEL(x) ((x) << 0) /* crtc0 - crtc5 */
+#       define DCCG_AUDIO_DTO_SEL            (1 << 4)   /* 0=dto0 1=dto1 */
+
+#define DCCG_AUDIO_DTO0_PHASE                           0x05b0
+#define DCCG_AUDIO_DTO0_MODULE                          0x05b4
+#define DCCG_AUDIO_DTO1_PHASE                           0x05b8
+#define DCCG_AUDIO_DTO1_MODULE                          0x05bc
+
 #define AFMT_AUDIO_SRC_CONTROL                          0x713c
 #define		AFMT_AUDIO_SRC_SELECT(x)		(((x) & 7) << 0)
 /* AFMT_AUDIO_SRC_SELECT

+ 4 - 0
drivers/gpu/drm/radeon/sumo_dpm.c

@@ -1338,6 +1338,7 @@ void sumo_dpm_post_set_power_state(struct radeon_device *rdev)
 	sumo_update_current_ps(rdev, new_ps);
 }
 
+#if 0
 void sumo_dpm_reset_asic(struct radeon_device *rdev)
 {
 	sumo_program_bootup_state(rdev);
@@ -1349,6 +1350,7 @@ void sumo_dpm_reset_asic(struct radeon_device *rdev)
 	sumo_set_forced_mode_enabled(rdev);
 	sumo_set_forced_mode_disabled(rdev);
 }
+#endif
 
 void sumo_dpm_setup_asic(struct radeon_device *rdev)
 {
@@ -1537,6 +1539,7 @@ u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev,
 	return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit;
 }
 
+#if 0
 u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev,
 			      struct sumo_vid_mapping_table *vid_mapping_table,
 			      u32 vid_7bit)
@@ -1550,6 +1553,7 @@ u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev,
 
 	return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit;
 }
+#endif
 
 static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev,
 					       u32 vid_2bit)

+ 0 - 3
drivers/gpu/drm/radeon/sumo_dpm.h

@@ -202,9 +202,6 @@ void sumo_construct_vid_mapping_table(struct radeon_device *rdev,
 u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev,
 			      struct sumo_vid_mapping_table *vid_mapping_table,
 			      u32 vid_2bit);
-u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev,
-			      struct sumo_vid_mapping_table *vid_mapping_table,
-			      u32 vid_7bit);
 u32 sumo_get_sleep_divider_from_id(u32 id);
 u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
 					 u32 sclk,

+ 2 - 0
drivers/gpu/drm/radeon/trinity_dpm.c

@@ -1269,6 +1269,7 @@ void trinity_dpm_setup_asic(struct radeon_device *rdev)
 	trinity_release_mutex(rdev);
 }
 
+#if 0
 void trinity_dpm_reset_asic(struct radeon_device *rdev)
 {
 	struct trinity_power_info *pi = trinity_get_pi(rdev);
@@ -1284,6 +1285,7 @@ void trinity_dpm_reset_asic(struct radeon_device *rdev)
 	}
 	trinity_release_mutex(rdev);
 }
+#endif
 
 static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
 						  u32 vid_2bit)