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 HWMON
 	select BACKLIGHT_CLASS_DEVICE
 	select BACKLIGHT_CLASS_DEVICE
 	select INTERVAL_TREE
 	select INTERVAL_TREE
-	select MMU_NOTIFIER
 	help
 	help
 	  Choose this option if you have an ATI Radeon graphics card.  There
 	  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
 	  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 \
 	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 \
 	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 \
 	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
 # add async DMA block
 radeon-y += \
 radeon-y += \

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

@@ -27,6 +27,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/radeon_drm.h>
 #include <drm/radeon_drm.h>
 #include "radeon.h"
 #include "radeon.h"
+#include "radeon_audio.h"
 #include "atom.h"
 #include "atom.h"
 #include <linux/backlight.h>
 #include <linux/backlight.h>
 
 
@@ -664,6 +665,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
 int
 int
 atombios_get_encoder_mode(struct drm_encoder *encoder)
 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 radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct drm_connector *connector;
 	struct drm_connector *connector;
 	struct radeon_connector *radeon_connector;
 	struct radeon_connector *radeon_connector;
@@ -728,6 +731,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
 		dig_connector = radeon_connector->con_priv;
 		dig_connector = radeon_connector->con_priv;
 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
 		    (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;
 			return ATOM_ENCODER_MODE_DP;
 		} else if (radeon_audio != 0) {
 		} else if (radeon_audio != 0) {
 			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
 			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
@@ -742,6 +747,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
 		}
 		}
 		break;
 		break;
 	case DRM_MODE_CONNECTOR_eDP:
 	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;
 		return ATOM_ENCODER_MODE_DP;
 	case DRM_MODE_CONNECTOR_DVIA:
 	case DRM_MODE_CONNECTOR_DVIA:
 	case DRM_MODE_CONNECTOR_VGA:
 	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 *radeon_connector = NULL;
 	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
 	struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
 	bool travis_quirk = false;
 	bool travis_quirk = false;
+	int encoder_mode;
 
 
 	if (connector) {
 	if (connector) {
 		radeon_connector = to_radeon_connector(connector);
 		radeon_connector = to_radeon_connector(connector);
@@ -1710,6 +1718,11 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
 		}
 		}
 		break;
 		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
 static void
@@ -2123,6 +2136,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
 	struct drm_device *dev = encoder->dev;
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	int encoder_mode;
 
 
 	radeon_encoder->pixel_clock = adjusted_mode->clock;
 	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_UNIPHY3:
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
 		/* handled in dpms */
 		/* 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;
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
 	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
 	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);
 	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
 static bool
@@ -2442,10 +2453,6 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
 
 
 disable_done:
 disable_done:
 	if (radeon_encoder_is_digital(encoder)) {
 	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 = radeon_encoder->enc_priv;
 		dig->dig_encoder = -1;
 		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;
 	eg_pi->requested_rps.ps_priv = &eg_pi->requested_ps;
 }
 }
 
 
+#if 0
 void btc_dpm_reset_asic(struct radeon_device *rdev)
 void btc_dpm_reset_asic(struct radeon_device *rdev)
 {
 {
 	rv770_restrict_performance_levels_before_switch(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);
 	btc_set_boot_state_timing(rdev);
 	rv770_set_boot_state(rdev);
 	rv770_set_boot_state(rdev);
 }
 }
+#endif
 
 
 int btc_dpm_pre_set_power_state(struct radeon_device *rdev)
 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,
 static PPSMC_Result ci_send_msg_to_smc_with_parameter(struct radeon_device *rdev,
 						      PPSMC_Msg msg, u32 parameter);
 						      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)
 static struct ci_power_info *ci_get_pi(struct radeon_device *rdev)
 {
 {
         struct ci_power_info *pi = rdev->pm.dpm.priv;
         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;
 			return -EINVAL;
 	}
 	}
 
 
+	pi->fan_is_controlled_by_smc = true;
 	return 0;
 	return 0;
 }
 }
 
 
-#if 0
 static int ci_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev)
 static int ci_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev)
 {
 {
 	PPSMC_Result ret;
 	PPSMC_Result ret;
+	struct ci_power_info *pi = ci_get_pi(rdev);
 
 
 	ret = ci_send_msg_to_smc(rdev, PPSMC_StopFanControl);
 	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;
 		return 0;
-	else
+	} else
 		return -EINVAL;
 		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 *speed)
 {
 {
 	u32 duty, duty100;
 	u32 duty, duty100;
@@ -1083,21 +1088,22 @@ static int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
 	return 0;
 	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 speed)
 {
 {
 	u32 tmp;
 	u32 tmp;
 	u32 duty, duty100;
 	u32 duty, duty100;
 	u64 tmp64;
 	u64 tmp64;
+	struct ci_power_info *pi = ci_get_pi(rdev);
 
 
 	if (rdev->pm.no_fan)
 	if (rdev->pm.no_fan)
 		return -ENOENT;
 		return -ENOENT;
 
 
-	if (speed > 100)
+	if (pi->fan_is_controlled_by_smc)
 		return -EINVAL;
 		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;
 	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);
 	tmp |= FDO_STATIC_DUTY(duty);
 	WREG32_SMC(CG_FDO_CTRL0, tmp);
 	WREG32_SMC(CG_FDO_CTRL0, tmp);
 
 
-	ci_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC);
-
 	return 0;
 	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,
 static int ci_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev,
 					 u32 *speed)
 					 u32 *speed)
 {
 {
@@ -1698,10 +1731,12 @@ static int ci_set_overdrive_target_tdp(struct radeon_device *rdev,
 	return 0;
 	return 0;
 }
 }
 
 
+#if 0
 static int ci_set_boot_state(struct radeon_device *rdev)
 static int ci_set_boot_state(struct radeon_device *rdev)
 {
 {
 	return ci_enable_sclk_mclk_dpm(rdev, false);
 	return ci_enable_sclk_mclk_dpm(rdev, false);
 }
 }
+#endif
 
 
 static u32 ci_get_average_sclk_freq(struct radeon_device *rdev)
 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;
 	return 0;
 }
 }
 
 
+#if 0
 void ci_dpm_reset_asic(struct radeon_device *rdev)
 void ci_dpm_reset_asic(struct radeon_device *rdev)
 {
 {
 	ci_set_boot_state(rdev);
 	ci_set_boot_state(rdev);
 }
 }
+#endif
 
 
 void ci_dpm_display_configuration_changed(struct radeon_device *rdev)
 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;
 	struct ci_ps requested_ps;
 	/* fan control */
 	/* fan control */
 	bool fan_ctrl_is_in_default_mode;
 	bool fan_ctrl_is_in_default_mode;
+	bool fan_is_controlled_by_smc;
 	u32 t_min;
 	u32 t_min;
 	u32 fan_ctrl_default_mode;
 	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;
 	return (PPSMC_Result)tmp;
 }
 }
 
 
+#if 0
 PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev)
 PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev)
 {
 {
 	u32 tmp;
 	u32 tmp;
@@ -201,6 +202,7 @@ PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev)
 
 
 	return PPSMC_Result_OK;
 	return PPSMC_Result_OK;
 }
 }
+#endif
 
 
 int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
 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 "drmP.h"
 #include "radeon.h"
 #include "radeon.h"
 #include "radeon_asic.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include "cikd.h"
 #include "cikd.h"
 #include "atom.h"
 #include "atom.h"
 #include "cik_blit_shaders.h"
 #include "cik_blit_shaders.h"
@@ -8517,7 +8518,7 @@ static int cik_startup(struct radeon_device *rdev)
 		return r;
 		return r;
 	}
 	}
 
 
-	r = dce6_audio_init(rdev);
+	r = radeon_audio_init(rdev);
 	if (r)
 	if (r)
 		return r;
 		return r;
 
 
@@ -8575,7 +8576,7 @@ int cik_suspend(struct radeon_device *rdev)
 {
 {
 	radeon_kfd_suspend(rdev);
 	radeon_kfd_suspend(rdev);
 	radeon_pm_suspend(rdev);
 	radeon_pm_suspend(rdev);
-	dce6_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	radeon_vm_manager_fini(rdev);
 	radeon_vm_manager_fini(rdev);
 	cik_cp_enable(rdev, false);
 	cik_cp_enable(rdev, false);
 	cik_sdma_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;
 	return 0;
 }
 }
 
 
+#if 0
 void cypress_dpm_reset_asic(struct radeon_device *rdev)
 void cypress_dpm_reset_asic(struct radeon_device *rdev)
 {
 {
 	rv770_restrict_performance_levels_before_switch(rdev);
 	rv770_restrict_performance_levels_before_switch(rdev);
 	rv770_set_boot_state(rdev);
 	rv770_set_boot_state(rdev);
 }
 }
+#endif
 
 
 void cypress_dpm_display_configuration_changed(struct radeon_device *rdev)
 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 <drm/drmP.h>
 #include "radeon.h"
 #include "radeon.h"
 #include "radeon_asic.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include "r600d.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 radeon_device *rdev = encoder->dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
 	u32 tmp;
 	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 */
 	/* 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);
 	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
 	/* set HDMI mode */
 	/* set HDMI mode */
 	tmp |= HDMI_CONNECTION;
 	tmp |= HDMI_CONNECTION;
@@ -62,19 +42,32 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
 		tmp |= SPEAKER_ALLOCATION(sadb[0]);
 		tmp |= SPEAKER_ALLOCATION(sadb[0]);
 	else
 	else
 		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
 		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 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] = {
 	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_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
 		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
 		{ 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 },
 		{ 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++) {
 	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
 		u32 value = 0;
 		u32 value = 0;
 		u8 stereo_freqs = 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);
 		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;
 		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 {
 	} 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,
 	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 <linux/hdmi.h>
 #include <drm/drmP.h>
 #include <drm/drmP.h>
 #include "radeon.h"
 #include "radeon.h"
+#include "radeon_audio.h"
 #include "sid.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)
 			      u32 block_offset, u32 reg)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
@@ -39,7 +40,7 @@ static u32 dce6_endpoint_rreg(struct radeon_device *rdev,
 	return r;
 	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)
 			       u32 block_offset, u32 reg, u32 v)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
@@ -54,10 +55,6 @@ static void dce6_endpoint_wreg(struct radeon_device *rdev,
 	spin_unlock_irqrestore(&rdev->end_idx_lock, flags);
 	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)
 static void dce6_afmt_get_connected_pins(struct radeon_device *rdev)
 {
 {
 	int i;
 	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,
 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_device *rdev = encoder->dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
 	u32 tmp = 0, offset;
 	u32 tmp = 0, offset;
 
 
 	if (!dig || !dig->afmt || !dig->afmt->pin)
 	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;
 	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 (mode->flags & DRM_MODE_FLAG_INTERLACE) {
 		if (connector->latency_present[1])
 		if (connector->latency_present[1])
 			tmp = VIDEO_LIPSYNC(connector->video_latency[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);
 	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_device *rdev = encoder->dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
 	u32 offset, tmp;
 	u32 offset, tmp;
-	u8 *sadb = NULL;
-	int sad_count;
 
 
 	if (!dig || !dig->afmt || !dig->afmt->pin)
 	if (!dig || !dig->afmt || !dig->afmt->pin)
 		return;
 		return;
 
 
 	offset = dig->afmt->pin->offset;
 	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 */
 	/* program the speaker allocation */
 	tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
 	tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
 	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
 	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
@@ -191,21 +153,41 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
 	else
 	else
 		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
 		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
 	WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
 	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_device *rdev = encoder->dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	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] = {
 	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_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
 		{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
 		{ 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;
 	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++) {
 	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
 		u32 value = 0;
 		u32 value = 0;
 		u8 stereo_freqs = 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);
 		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,
 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);
 			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;
 		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 <drm/drmP.h>
 #include "radeon.h"
 #include "radeon.h"
 #include "radeon_asic.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include <drm/radeon_drm.h>
 #include <drm/radeon_drm.h>
 #include "evergreend.h"
 #include "evergreend.h"
 #include "atom.h"
 #include "atom.h"
@@ -5286,7 +5287,7 @@ static int evergreen_startup(struct radeon_device *rdev)
 		return r;
 		return r;
 	}
 	}
 
 
-	r = r600_audio_init(rdev);
+	r = radeon_audio_init(rdev);
 	if (r) {
 	if (r) {
 		DRM_ERROR("radeon: audio init failed\n");
 		DRM_ERROR("radeon: audio init failed\n");
 		return r;
 		return r;
@@ -5332,7 +5333,7 @@ int evergreen_resume(struct radeon_device *rdev)
 int evergreen_suspend(struct radeon_device *rdev)
 int evergreen_suspend(struct radeon_device *rdev)
 {
 {
 	radeon_pm_suspend(rdev);
 	radeon_pm_suspend(rdev);
-	r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	uvd_v1_0_fini(rdev);
 	uvd_v1_0_fini(rdev);
 	radeon_uvd_suspend(rdev);
 	radeon_uvd_suspend(rdev);
 	r700_cp_stop(rdev);
 	r700_cp_stop(rdev);
@@ -5482,7 +5483,7 @@ int evergreen_init(struct radeon_device *rdev)
 void evergreen_fini(struct radeon_device *rdev)
 void evergreen_fini(struct radeon_device *rdev)
 {
 {
 	radeon_pm_fini(rdev);
 	radeon_pm_fini(rdev);
-	r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	r700_cp_fini(rdev);
 	r700_cp_fini(rdev);
 	r600_dma_fini(rdev);
 	r600_dma_fini(rdev);
 	r600_irq_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_offset;
 	u32			htile_surface;
 	u32			htile_surface;
 	struct radeon_bo	*htile_bo;
 	struct radeon_bo	*htile_bo;
+	unsigned long		indirect_draw_buffer_size;
 };
 };
 
 
 static u32 evergreen_cs_get_aray_mode(u32 tiling_flags)
 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;
 		break;
 	}
 	}
+	case PACKET3_INDEX_BUFFER_SIZE:
+	{
+		if (pkt->count != 0) {
+			DRM_ERROR("bad INDEX_BUFFER_SIZE\n");
+			return -EINVAL;
+		}
+		break;
+	}
 	case PACKET3_DRAW_INDEX:
 	case PACKET3_DRAW_INDEX:
 	{
 	{
 		uint64_t offset;
 		uint64_t offset;
@@ -2006,6 +2015,67 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
 			return r;
 			return r;
 		}
 		}
 		break;
 		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:
 	case PACKET3_DISPATCH_DIRECT:
 		if (pkt->count != 3) {
 		if (pkt->count != 3) {
 			DRM_ERROR("bad DISPATCH_DIRECT\n");
 			DRM_ERROR("bad DISPATCH_DIRECT\n");
@@ -3243,7 +3313,13 @@ static int evergreen_vm_packet3_check(struct radeon_device *rdev,
 
 
 	switch (pkt->opcode) {
 	switch (pkt->opcode) {
 	case PACKET3_NOP:
 	case PACKET3_NOP:
+		break;
 	case PACKET3_SET_BASE:
 	case PACKET3_SET_BASE:
+		if (idx_value != 1) {
+			DRM_ERROR("bad SET_BASE");
+			return -EINVAL;
+		}
+		break;
 	case PACKET3_CLEAR_STATE:
 	case PACKET3_CLEAR_STATE:
 	case PACKET3_INDEX_BUFFER_SIZE:
 	case PACKET3_INDEX_BUFFER_SIZE:
 	case PACKET3_DISPATCH_DIRECT:
 	case PACKET3_DISPATCH_DIRECT:

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

@@ -29,17 +29,12 @@
 #include <drm/radeon_drm.h>
 #include <drm/radeon_drm.h>
 #include "radeon.h"
 #include "radeon.h"
 #include "radeon_asic.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include "evergreend.h"
 #include "evergreend.h"
 #include "atom.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 */
 /* 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,
 			      struct r600_audio_pin *pin,
 			      u8 enable_mask)
 			      u8 enable_mask)
 {
 {
@@ -69,48 +64,42 @@ static void dce4_audio_enable(struct radeon_device *rdev,
 	WREG32(AZ_HOT_PLUG_CONTROL, tmp);
 	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 drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	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 radeon_device *rdev = encoder->dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
 	u32 tmp = 0;
 	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 (mode->flags & DRM_MODE_FLAG_INTERLACE) {
 		if (connector->latency_present[1])
 		if (connector->latency_present[1])
 			tmp = VIDEO_LIPSYNC(connector->video_latency[1]) |
 			tmp = VIDEO_LIPSYNC(connector->video_latency[1]) |
@@ -124,38 +113,17 @@ static void dce4_afmt_write_latency_fields(struct drm_encoder *encoder,
 		else
 		else
 			tmp = VIDEO_LIPSYNC(255) | AUDIO_LIPSYNC(255);
 			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 radeon_device *rdev = encoder->dev->dev_private;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector = NULL;
 	u32 tmp;
 	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 */
 	/* 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);
 	tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
 	/* set HDMI mode */
 	/* set HDMI mode */
 	tmp |= HDMI_CONNECTION;
 	tmp |= HDMI_CONNECTION;
@@ -163,19 +131,32 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
 		tmp |= SPEAKER_ALLOCATION(sadb[0]);
 		tmp |= SPEAKER_ALLOCATION(sadb[0]);
 	else
 	else
 		tmp |= SPEAKER_ALLOCATION(5); /* stereo */
 		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 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] = {
 	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_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM },
 		{ AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 },
 		{ 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 },
 		{ 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++) {
 	for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
 		u32 value = 0;
 		u32 value = 0;
 		u8 stereo_freqs = 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);
 		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 *frame = buffer + 3;
-	uint8_t *header = buffer;
 
 
 	WREG32(AFMT_AVI_INFO0 + offset,
 	WREG32(AFMT_AVI_INFO0 + offset,
 		frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
 		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,
 	WREG32(AFMT_AVI_INFO2 + offset,
 		frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
 		frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
 	WREG32(AFMT_AVI_INFO3 + offset,
 	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_phase;
-	u32 dto_modulo = clock;
 	u32 wallclock_ratio;
 	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 {
 	} 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
 	/* Express [24MHz / target pixel clock] as an exact rational
 	 * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
 	 * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
 	 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
 	 * 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_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,
 	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 = RREG32(HDMI_CONTROL + offset);
 	val &= ~HDMI_DEEP_COLOR_ENABLE;
 	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_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,
 	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,
 	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,
 	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,
 	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,
 	WREG32(AFMT_60958_0 + offset,
-	       AFMT_60958_CS_CHANNEL_NUMBER_L(1));
+		AFMT_60958_CS_CHANNEL_NUMBER_L(1));
 
 
 	WREG32(AFMT_60958_1 + offset,
 	WREG32(AFMT_60958_1 + offset,
-	       AFMT_60958_CS_CHANNEL_NUMBER_R(2));
+		AFMT_60958_CS_CHANNEL_NUMBER_R(2));
 
 
 	WREG32(AFMT_60958_2 + offset,
 	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,
 	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
 	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)
 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;
 		return;
 
 
 	if (!enable && dig->afmt->pin) {
 	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;
 		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",
 	DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n",
 		  enable ? "En" : "Dis", dig->afmt->offset, radeon_encoder->encoder_id);
 		  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 */
 /* HDMI blocks at 0x7030, 0x7c30, 0x10830, 0x11430, 0x12030, 0x12c30 */
 #define EVERGREEN_HDMI_BASE				0x7030
 #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
 #endif

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

@@ -509,6 +509,7 @@
 #define DCCG_AUDIO_DTO1_MODULE            0x05c4
 #define DCCG_AUDIO_DTO1_MODULE            0x05c4
 #define DCCG_AUDIO_DTO1_LOAD              0x05c8
 #define DCCG_AUDIO_DTO1_LOAD              0x05c8
 #define DCCG_AUDIO_DTO1_CNTL              0x05cc
 #define DCCG_AUDIO_DTO1_CNTL              0x05cc
+#       define DCCG_AUDIO_DTO1_USE_512FBR_DTO (1 << 3)
 
 
 /* DCE 4.0 AFMT */
 /* DCE 4.0 AFMT */
 #define HDMI_CONTROL                         0x7030
 #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);
 	kv_init_sclk_t(rdev);
 }
 }
 
 
+#if 0
 void kv_dpm_reset_asic(struct radeon_device *rdev)
 void kv_dpm_reset_asic(struct radeon_device *rdev)
 {
 {
 	struct kv_power_info *pi = kv_get_pi(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);
 		kv_set_enabled_level(rdev, pi->graphics_boot_level);
 	}
 	}
 }
 }
+#endif
 
 
 //XXX use sumo_dpm_display_configuration_changed
 //XXX use sumo_dpm_display_configuration_changed
 
 

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

@@ -27,6 +27,7 @@
 #include <drm/drmP.h>
 #include <drm/drmP.h>
 #include "radeon.h"
 #include "radeon.h"
 #include "radeon_asic.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include <drm/radeon_drm.h>
 #include <drm/radeon_drm.h>
 #include "nid.h"
 #include "nid.h"
 #include "atom.h"
 #include "atom.h"
@@ -2097,15 +2098,9 @@ static int cayman_startup(struct radeon_device *rdev)
 		return r;
 		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;
 	return 0;
 }
 }
@@ -2140,10 +2135,7 @@ int cayman_resume(struct radeon_device *rdev)
 int cayman_suspend(struct radeon_device *rdev)
 int cayman_suspend(struct radeon_device *rdev)
 {
 {
 	radeon_pm_suspend(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);
 	radeon_vm_manager_fini(rdev);
 	cayman_cp_enable(rdev, false);
 	cayman_cp_enable(rdev, false);
 	cayman_dma_stop(rdev);
 	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);
 	ni_update_current_ps(rdev, new_ps);
 }
 }
 
 
+#if 0
 void ni_dpm_reset_asic(struct radeon_device *rdev)
 void ni_dpm_reset_asic(struct radeon_device *rdev)
 {
 {
 	ni_restrict_performance_levels_before_switch(rdev);
 	ni_restrict_performance_levels_before_switch(rdev);
 	rv770_set_boot_state(rdev);
 	rv770_set_boot_state(rdev);
 }
 }
+#endif
 
 
 union power_info {
 union power_info {
 	struct _ATOM_POWERPLAY_INFO info;
 	struct _ATOM_POWERPLAY_INFO info;

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

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

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

@@ -29,6 +29,7 @@
 #include <drm/radeon_drm.h>
 #include <drm/radeon_drm.h>
 #include "radeon.h"
 #include "radeon.h"
 #include "radeon_asic.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include "r600d.h"
 #include "r600d.h"
 #include "atom.h"
 #include "atom.h"
 
 
@@ -55,30 +56,6 @@ enum r600_hdmi_iec_status_bits {
 	AUDIO_STATUS_LEVEL        = 0x80
 	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)
 static struct r600_audio_pin r600_audio_status(struct radeon_device *rdev)
 {
 {
 	struct r600_audio_pin status;
 	struct r600_audio_pin status;
@@ -191,155 +168,56 @@ void r600_audio_enable(struct radeon_device *rdev,
 	WREG32(AZ_HOT_PLUG_CONTROL, tmp);
 	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)
 struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev)
 {
 {
 	/* only one pin on 6xx-NI */
 	/* only one pin on 6xx-NI */
 	return &rdev->audio.pin[0];
 	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 drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	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,
 	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,
 	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,
 	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,
 	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,
 	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,
 	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
  * 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 *frame = buffer + 3;
-	uint8_t *header = buffer;
 
 
 	WREG32(HDMI0_AVI_INFO0 + offset,
 	WREG32(HDMI0_AVI_INFO0 + offset,
 		frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
 		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,
 	WREG32(HDMI0_AVI_INFO2 + offset,
 		frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
 		frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
 	WREG32(HDMI0_AVI_INFO3 + offset,
 	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);
 		 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;
 		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 {
 	} 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 drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	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,
 	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,
 	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,
 	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,
 	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,
 	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,
 	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;
 		return;
 
 
 	if (!enable && dig->afmt->pin) {
 	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;
 		dig->afmt->pin = NULL;
 	}
 	}
 
 

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

@@ -1757,6 +1757,9 @@ struct r600_audio {
 	bool enabled;
 	bool enabled;
 	struct r600_audio_pin pin[RADEON_MAX_AFMT_BLOCKS];
 	struct r600_audio_pin pin[RADEON_MAX_AFMT_BLOCKS];
 	int num_pins;
 	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
  * MMU Notifier
  */
  */
+#if defined(CONFIG_MMU_NOTIFIER)
 int radeon_mn_register(struct radeon_bo *bo, unsigned long addr);
 int radeon_mn_register(struct radeon_bo *bo, unsigned long addr);
 void radeon_mn_unregister(struct radeon_bo *bo);
 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
  * Debugfs
@@ -1967,6 +1978,10 @@ struct radeon_asic {
 		bool (*vblank_too_short)(struct radeon_device *rdev);
 		bool (*vblank_too_short)(struct radeon_device *rdev);
 		void (*powergate_uvd)(struct radeon_device *rdev, bool gate);
 		void (*powergate_uvd)(struct radeon_device *rdev, bool gate);
 		void (*enable_bapm)(struct radeon_device *rdev, bool enable);
 		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;
 	} dpm;
 	/* pageflipping */
 	/* pageflipping */
 	struct {
 	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,
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &r600_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &r100_copy_blit,
 		.blit = &r100_copy_blit,
@@ -706,8 +704,6 @@ static struct radeon_asic rs690_asic = {
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &r600_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &r100_copy_blit,
 		.blit = &r100_copy_blit,
@@ -935,8 +931,6 @@ static struct radeon_asic r600_asic = {
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &r600_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &r600_copy_cpdma,
 		.blit = &r600_copy_cpdma,
@@ -1021,8 +1015,6 @@ static struct radeon_asic rv6xx_asic = {
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &r600_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &r600_copy_cpdma,
 		.blit = &r600_copy_cpdma,
@@ -1112,8 +1104,6 @@ static struct radeon_asic rs780_asic = {
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &r600_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &r600_copy_cpdma,
 		.blit = &r600_copy_cpdma,
@@ -1216,8 +1206,6 @@ static struct radeon_asic rv770_asic = {
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.wait_for_vblank = &avivo_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &r600_hdmi_enable,
-		.hdmi_setmode = &dce3_1_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &r600_copy_cpdma,
 		.blit = &r600_copy_cpdma,
@@ -1334,8 +1322,6 @@ static struct radeon_asic evergreen_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &r600_copy_cpdma,
 		.blit = &r600_copy_cpdma,
@@ -1426,8 +1412,6 @@ static struct radeon_asic sumo_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &r600_copy_cpdma,
 		.blit = &r600_copy_cpdma,
@@ -1517,8 +1501,6 @@ static struct radeon_asic btc_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &r600_copy_cpdma,
 		.blit = &r600_copy_cpdma,
@@ -1663,8 +1645,6 @@ static struct radeon_asic cayman_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &r600_copy_cpdma,
 		.blit = &r600_copy_cpdma,
@@ -1766,8 +1746,6 @@ static struct radeon_asic trinity_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &r600_copy_cpdma,
 		.blit = &r600_copy_cpdma,
@@ -1899,8 +1877,6 @@ static struct radeon_asic si_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &r600_copy_cpdma,
 		.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,
 		.debugfs_print_current_performance_level = &si_dpm_debugfs_print_current_performance_level,
 		.force_performance_level = &si_dpm_force_performance_level,
 		.force_performance_level = &si_dpm_force_performance_level,
 		.vblank_too_short = &ni_dpm_vblank_too_short,
 		.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 = {
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
 		.page_flip = &evergreen_page_flip,
@@ -2062,8 +2042,6 @@ static struct radeon_asic ci_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &cik_copy_cpdma,
 		.blit = &cik_copy_cpdma,
@@ -2118,6 +2096,10 @@ static struct radeon_asic ci_asic = {
 		.force_performance_level = &ci_dpm_force_performance_level,
 		.force_performance_level = &ci_dpm_force_performance_level,
 		.vblank_too_short = &ci_dpm_vblank_too_short,
 		.vblank_too_short = &ci_dpm_vblank_too_short,
 		.powergate_uvd = &ci_dpm_powergate_uvd,
 		.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 = {
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
 		.page_flip = &evergreen_page_flip,
@@ -2169,8 +2151,6 @@ static struct radeon_asic kv_asic = {
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.wait_for_vblank = &dce4_wait_for_vblank,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.set_backlight_level = &atombios_set_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
 		.get_backlight_level = &atombios_get_backlight_level,
-		.hdmi_enable = &evergreen_hdmi_enable,
-		.hdmi_setmode = &evergreen_hdmi_setmode,
 	},
 	},
 	.copy = {
 	.copy = {
 		.blit = &cik_copy_cpdma,
 		.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_disable_interrupts(struct radeon_device *rdev);
 void r600_rlc_stop(struct radeon_device *rdev);
 void r600_rlc_stop(struct radeon_device *rdev);
 /* r600 audio */
 /* r600 audio */
-int r600_audio_init(struct radeon_device *rdev);
 void r600_audio_fini(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_audio_set_dto(struct drm_encoder *encoder, u32 clock);
 void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer,
 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);
 void r600_hdmi_audio_workaround(struct drm_encoder *encoder);
 int r600_hdmi_buffer_status_changed(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_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);
 int r600_mc_wait_for_idle(struct radeon_device *rdev);
 u32 r600_get_xclk(struct radeon_device *rdev);
 u32 r600_get_xclk(struct radeon_device *rdev);
 uint64_t r600_get_gpu_clock_counter(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);
 u32 rv770_get_xclk(struct radeon_device *rdev);
 int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int rv770_get_temp(struct radeon_device *rdev);
 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 */
 /* rv7xx pm */
 int rv770_dpm_init(struct radeon_device *rdev);
 int rv770_dpm_init(struct radeon_device *rdev);
 int rv770_dpm_enable(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,
 					uint64_t src_offset, uint64_t dst_offset,
 					unsigned num_gpu_pages,
 					unsigned num_gpu_pages,
 					struct reservation_object *resv);
 					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 evergreen_get_temp(struct radeon_device *rdev);
 int sumo_get_temp(struct radeon_device *rdev);
 int sumo_get_temp(struct radeon_device *rdev);
 int tn_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 */
 /* DCE6 - SI */
 void dce6_bandwidth_update(struct radeon_device *rdev);
 void dce6_bandwidth_update(struct radeon_device *rdev);
-int dce6_audio_init(struct radeon_device *rdev);
 void dce6_audio_fini(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);
 						    struct seq_file *m);
 int si_dpm_force_performance_level(struct radeon_device *rdev,
 int si_dpm_force_performance_level(struct radeon_device *rdev,
 				   enum radeon_dpm_forced_level level);
 				   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 */
 /* DCE8 - CIK */
 void dce8_bandwidth_update(struct radeon_device *rdev);
 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);
 bool ci_dpm_vblank_too_short(struct radeon_device *rdev);
 void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate);
 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_init(struct radeon_device *rdev);
 int kv_dpm_enable(struct radeon_device *rdev);
 int kv_dpm_enable(struct radeon_device *rdev);
 int kv_dpm_late_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/drm_fb_helper.h>
 #include <drm/radeon_drm.h>
 #include <drm/radeon_drm.h>
 #include "radeon.h"
 #include "radeon.h"
+#include "radeon_audio.h"
 #include "atom.h"
 #include "atom.h"
 
 
 #include <linux/pm_runtime.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 */
 	/* updated in get modes as well since we need to know if it's analog or digital */
 	radeon_connector_update_scratch_regs(connector, ret);
 	radeon_connector_update_scratch_regs(connector, ret);
 
 
+	if (radeon_audio != 0)
+		radeon_audio_detect(connector, ret);
+
 exit:
 exit:
 	pm_runtime_mark_last_busy(connector->dev->dev);
 	pm_runtime_mark_last_busy(connector->dev->dev);
 	pm_runtime_put_autosuspend(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);
 	radeon_connector_update_scratch_regs(connector, ret);
+
+	if (radeon_audio != 0)
+		radeon_audio_detect(connector, ret);
+
 out:
 out:
 	pm_runtime_mark_last_busy(connector->dev->dev);
 	pm_runtime_mark_last_busy(connector->dev->dev);
 	pm_runtime_put_autosuspend(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.39.0 - Add INFO query for number of active CUs
  *   2.40.0 - Add RADEON_GEM_GTT_WC/UC, flush HDP cache before submitting
  *   2.40.0 - Add RADEON_GEM_GTT_WC/UC, flush HDP cache before submitting
  *            CS to GPU on >= r600
  *            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_MAJOR	2
-#define KMS_DRIVER_MINOR	40
+#define KMS_DRIVER_MINOR	41
 #define KMS_DRIVER_PATCHLEVEL	0
 #define KMS_DRIVER_PATCHLEVEL	0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
 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);
 	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)
 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))
 	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;
 	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,
 void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus,
 			 u8 slave_addr,
 			 u8 slave_addr,
 			 u8 addr,
 			 u8 addr,

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

@@ -449,6 +449,7 @@ struct radeon_encoder {
 	int audio_polling_active;
 	int audio_polling_active;
 	bool is_ext_encoder;
 	bool is_ext_encoder;
 	u16 caps;
 	u16 caps;
+	struct radeon_audio_funcs *audio;
 };
 };
 
 
 struct radeon_connector_atom_dig {
 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 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 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,
 extern bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev,
 					     struct radeon_atom_ss *ss,
 					     struct radeon_atom_ss *ss,
 					     int id);
 					     int id);
@@ -925,7 +924,6 @@ void dce8_program_fmt(struct drm_encoder *encoder);
 int radeon_fbdev_init(struct radeon_device *rdev);
 int radeon_fbdev_init(struct radeon_device *rdev);
 void radeon_fbdev_fini(struct radeon_device *rdev);
 void radeon_fbdev_fini(struct radeon_device *rdev);
 void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state);
 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);
 bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj);
 
 
 void radeon_fb_output_poll_changed(struct radeon_device *rdev);
 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;
 	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)
 int radeon_bo_get_surface_reg(struct radeon_bo *bo)
 {
 {
 	struct radeon_device *rdev = bo->rdev;
 	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,
 extern int radeon_bo_list_validate(struct radeon_device *rdev,
 				   struct ww_acquire_ctx *ticket,
 				   struct ww_acquire_ctx *ticket,
 				   struct list_head *head, int ring);
 				   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,
 extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
 				u32 tiling_flags, u32 pitch);
 				u32 tiling_flags, u32 pitch);
 extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo,
 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 "radeon.h"
 #include "avivod.h"
 #include "avivod.h"
 #include "atom.h"
 #include "atom.h"
+#include "r600_dpm.h"
 #include <linux/power_supply.h>
 #include <linux/power_supply.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-sysfs.h>
@@ -554,6 +555,96 @@ fail:
 	return count;
 	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_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_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);
 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_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, 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(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[] = {
 static struct attribute *hwmon_attributes[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
 	&sensor_dev_attr_temp1_crit_hyst.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
 	NULL
 };
 };
 
 
@@ -614,6 +714,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
 {
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct radeon_device *rdev = dev_get_drvdata(dev);
 	struct radeon_device *rdev = dev_get_drvdata(dev);
+	umode_t effective_mode = attr->mode;
 
 
 	/* Skip limit attributes if DPM is not enabled */
 	/* Skip limit attributes if DPM is not enabled */
 	if (rdev->pm.pm_method != PM_METHOD_DPM &&
 	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))
 	     attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
 		return 0;
 		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 = {
 static const struct attribute_group hwmon_attrgroup = {

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

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

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

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

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

@@ -30,6 +30,7 @@
 #include <drm/drmP.h>
 #include <drm/drmP.h>
 #include "radeon.h"
 #include "radeon.h"
 #include "radeon_asic.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include <drm/radeon_drm.h>
 #include <drm/radeon_drm.h>
 #include "rv770d.h"
 #include "rv770d.h"
 #include "atom.h"
 #include "atom.h"
@@ -1788,7 +1789,7 @@ static int rv770_startup(struct radeon_device *rdev)
 		return r;
 		return r;
 	}
 	}
 
 
-	r = r600_audio_init(rdev);
+	r = radeon_audio_init(rdev);
 	if (r) {
 	if (r) {
 		DRM_ERROR("radeon: audio init failed\n");
 		DRM_ERROR("radeon: audio init failed\n");
 		return r;
 		return r;
@@ -1829,7 +1830,7 @@ int rv770_resume(struct radeon_device *rdev)
 int rv770_suspend(struct radeon_device *rdev)
 int rv770_suspend(struct radeon_device *rdev)
 {
 {
 	radeon_pm_suspend(rdev);
 	radeon_pm_suspend(rdev);
-	r600_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	uvd_v1_0_fini(rdev);
 	uvd_v1_0_fini(rdev);
 	radeon_uvd_suspend(rdev);
 	radeon_uvd_suspend(rdev);
 	r700_cp_stop(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;
 		MC_CG_SEQ_DRAMCONF_S0 : MC_CG_SEQ_DRAMCONF_S1;
 }
 }
 
 
+#if 0
 int rv770_read_smc_soft_register(struct radeon_device *rdev,
 int rv770_read_smc_soft_register(struct radeon_device *rdev,
 				 u16 reg_offset, u32 *value)
 				 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,
 					 pi->soft_regs_start + reg_offset,
 					 value, pi->sram_end);
 					 value, pi->sram_end);
 }
 }
+#endif
 
 
 int rv770_write_smc_soft_register(struct radeon_device *rdev,
 int rv770_write_smc_soft_register(struct radeon_device *rdev,
 				  u16 reg_offset, u32 value)
 				  u16 reg_offset, u32 value)
@@ -2075,6 +2077,7 @@ int rv770_dpm_set_power_state(struct radeon_device *rdev)
 	return 0;
 	return 0;
 }
 }
 
 
+#if 0
 void rv770_dpm_reset_asic(struct radeon_device *rdev)
 void rv770_dpm_reset_asic(struct radeon_device *rdev)
 {
 {
 	struct rv7xx_power_info *pi = rv770_get_pi(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)
 	if (pi->dcodt)
 		rv770_program_dcodt_after_state_switch(rdev, boot_ps, boot_ps);
 		rv770_program_dcodt_after_state_switch(rdev, boot_ps, boot_ps);
 }
 }
+#endif
 
 
 void rv770_dpm_setup_asic(struct radeon_device *rdev)
 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);
 void rv770_get_engine_memory_ss(struct radeon_device *rdev);
 
 
 /* smc */
 /* 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,
 int rv770_write_smc_soft_register(struct radeon_device *rdev,
 				  u16 reg_offset, u32 value);
 				  u16 reg_offset, u32 value);
 
 

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

@@ -27,6 +27,7 @@
 #include <drm/drmP.h>
 #include <drm/drmP.h>
 #include "radeon.h"
 #include "radeon.h"
 #include "radeon_asic.h"
 #include "radeon_asic.h"
+#include "radeon_audio.h"
 #include <drm/radeon_drm.h>
 #include <drm/radeon_drm.h>
 #include "sid.h"
 #include "sid.h"
 #include "atom.h"
 #include "atom.h"
@@ -6869,7 +6870,7 @@ static int si_startup(struct radeon_device *rdev)
 		return r;
 		return r;
 	}
 	}
 
 
-	r = dce6_audio_init(rdev);
+	r = radeon_audio_init(rdev);
 	if (r)
 	if (r)
 		return r;
 		return r;
 
 
@@ -6908,7 +6909,7 @@ int si_resume(struct radeon_device *rdev)
 int si_suspend(struct radeon_device *rdev)
 int si_suspend(struct radeon_device *rdev)
 {
 {
 	radeon_pm_suspend(rdev);
 	radeon_pm_suspend(rdev);
-	dce6_audio_fini(rdev);
+	radeon_audio_fini(rdev);
 	radeon_vm_manager_fini(rdev);
 	radeon_vm_manager_fini(rdev);
 	si_cp_enable(rdev, false);
 	si_cp_enable(rdev, false);
 	cayman_dma_stop(rdev);
 	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,
 				    u32 engine_clock,
 				    SISLANDS_SMC_SCLK_VALUE *sclk);
 				    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)
 static struct si_power_info *si_get_pi(struct radeon_device *rdev)
 {
 {
         struct si_power_info *pi = rdev->pm.dpm.priv;
         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;
 	return 0;
 }
 }
 
 
+#if 0
 static int si_set_boot_state(struct radeon_device *rdev)
 static int si_set_boot_state(struct radeon_device *rdev)
 {
 {
 	return (si_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ?
 	return (si_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ?
 		0 : -EINVAL;
 		0 : -EINVAL;
 }
 }
+#endif
 
 
 static int si_set_sw_state(struct radeon_device *rdev)
 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);
 	slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
 	slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 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.slope1 = cpu_to_be16(slope1);
 	fan_table.slope2 = cpu_to_be16(slope2);
 	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)
 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;
 	PPSMC_Result ret;
 
 
 	ret = si_send_msg_to_smc(rdev, PPSMC_StartFanControl);
 	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;
 		return 0;
-	else
+	} else {
 		return -EINVAL;
 		return -EINVAL;
+	}
 }
 }
 
 
 static int si_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev)
 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;
 	PPSMC_Result ret;
 
 
 	ret = si_send_msg_to_smc(rdev, PPSMC_StopFanControl);
 	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;
 		return 0;
-	else
+	} else {
 		return -EINVAL;
 		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;
 	u32 duty, duty100;
 	u64 tmp64;
 	u64 tmp64;
@@ -6058,9 +6073,10 @@ static int si_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
 	return 0;
 	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 tmp;
 	u32 duty, duty100;
 	u32 duty, duty100;
 	u64 tmp64;
 	u64 tmp64;
@@ -6068,11 +6084,11 @@ static int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
 	if (rdev->pm.no_fan)
 	if (rdev->pm.no_fan)
 		return -ENOENT;
 		return -ENOENT;
 
 
-	if (speed > 100)
+	if (si_pi->fan_is_controlled_by_smc)
 		return -EINVAL;
 		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;
 	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);
 	tmp |= FDO_STATIC_DUTY(duty);
 	WREG32(CG_FDO_CTRL0, tmp);
 	WREG32(CG_FDO_CTRL0, tmp);
 
 
-	si_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC);
-
 	return 0;
 	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,
 static int si_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev,
 					 u32 *speed)
 					 u32 *speed)
 {
 {
@@ -6538,13 +6581,14 @@ void si_dpm_post_set_power_state(struct radeon_device *rdev)
 	ni_update_current_ps(rdev, new_ps);
 	ni_update_current_ps(rdev, new_ps);
 }
 }
 
 
-
+#if 0
 void si_dpm_reset_asic(struct radeon_device *rdev)
 void si_dpm_reset_asic(struct radeon_device *rdev)
 {
 {
 	si_restrict_performance_levels_before_switch(rdev);
 	si_restrict_performance_levels_before_switch(rdev);
 	si_disable_ulv(rdev);
 	si_disable_ulv(rdev);
 	si_set_boot_state(rdev);
 	si_set_boot_state(rdev);
 }
 }
+#endif
 
 
 void si_dpm_display_configuration_changed(struct radeon_device *rdev)
 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;
 			rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
 
 
 	si_pi->fan_ctrl_is_in_default_mode = true;
 	si_pi->fan_ctrl_is_in_default_mode = true;
-	rdev->pm.dpm.fan.ucode_fan_control = false;
 
 
 	return 0;
 	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;
 	bool fan_ctrl_is_in_default_mode;
 	u32 t_min;
 	u32 t_min;
 	u32 fan_ctrl_default_mode;
 	u32 fan_ctrl_default_mode;
+	bool fan_is_controlled_by_smc;
 };
 };
 
 
 #define SISLANDS_INITIAL_STATE_ARB_INDEX    0
 #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 */
 /* 0x6e98, 0x7a98, 0x10698, 0x11298, 0x11e98, 0x12a98 */
 #define CRTC_STATUS_FRAME_COUNT                         0x6e98
 #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_CONTROL                          0x713c
 #define		AFMT_AUDIO_SRC_SELECT(x)		(((x) & 7) << 0)
 #define		AFMT_AUDIO_SRC_SELECT(x)		(((x) & 7) << 0)
 /* AFMT_AUDIO_SRC_SELECT
 /* 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);
 	sumo_update_current_ps(rdev, new_ps);
 }
 }
 
 
+#if 0
 void sumo_dpm_reset_asic(struct radeon_device *rdev)
 void sumo_dpm_reset_asic(struct radeon_device *rdev)
 {
 {
 	sumo_program_bootup_state(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_enabled(rdev);
 	sumo_set_forced_mode_disabled(rdev);
 	sumo_set_forced_mode_disabled(rdev);
 }
 }
+#endif
 
 
 void sumo_dpm_setup_asic(struct radeon_device *rdev)
 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;
 	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,
 u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev,
 			      struct sumo_vid_mapping_table *vid_mapping_table,
 			      struct sumo_vid_mapping_table *vid_mapping_table,
 			      u32 vid_7bit)
 			      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;
 	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,
 static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev,
 					       u32 vid_2bit)
 					       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,
 u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev,
 			      struct sumo_vid_mapping_table *vid_mapping_table,
 			      struct sumo_vid_mapping_table *vid_mapping_table,
 			      u32 vid_2bit);
 			      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_from_id(u32 id);
 u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
 u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
 					 u32 sclk,
 					 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);
 	trinity_release_mutex(rdev);
 }
 }
 
 
+#if 0
 void trinity_dpm_reset_asic(struct radeon_device *rdev)
 void trinity_dpm_reset_asic(struct radeon_device *rdev)
 {
 {
 	struct trinity_power_info *pi = trinity_get_pi(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);
 	trinity_release_mutex(rdev);
 }
 }
+#endif
 
 
 static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
 static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
 						  u32 vid_2bit)
 						  u32 vid_2bit)