diff options
46 files changed, 1837 insertions, 971 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index ea283894a12a..308c104ccdbd 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
| @@ -110,7 +110,6 @@ config DRM_RADEON | |||
| 110 | select HWMON | 110 | select HWMON |
| 111 | select BACKLIGHT_CLASS_DEVICE | 111 | select BACKLIGHT_CLASS_DEVICE |
| 112 | select INTERVAL_TREE | 112 | select INTERVAL_TREE |
| 113 | select MMU_NOTIFIER | ||
| 114 | help | 113 | help |
| 115 | Choose this option if you have an ATI Radeon graphics card. There | 114 | Choose this option if you have an ATI Radeon graphics card. There |
| 116 | are both PCI and AGP versions. You don't need to choose this to | 115 | are both PCI and AGP versions. You don't need to choose this to |
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index c58cfd3c3917..4605633e253b 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile | |||
| @@ -80,8 +80,10 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ | |||
| 80 | r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \ | 80 | r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \ |
| 81 | rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \ | 81 | rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \ |
| 82 | trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \ | 82 | trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \ |
| 83 | ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o radeon_mn.o \ | 83 | ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o \ |
| 84 | radeon_sync.o | 84 | radeon_sync.o radeon_audio.o |
| 85 | |||
| 86 | radeon-$(CONFIG_MMU_NOTIFIER) += radeon_mn.o | ||
| 85 | 87 | ||
| 86 | # add async DMA block | 88 | # add async DMA block |
| 87 | radeon-y += \ | 89 | radeon-y += \ |
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index b8cd7975f797..7c9df1eac065 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <drm/drm_crtc_helper.h> | 27 | #include <drm/drm_crtc_helper.h> |
| 28 | #include <drm/radeon_drm.h> | 28 | #include <drm/radeon_drm.h> |
| 29 | #include "radeon.h" | 29 | #include "radeon.h" |
| 30 | #include "radeon_audio.h" | ||
| 30 | #include "atom.h" | 31 | #include "atom.h" |
| 31 | #include <linux/backlight.h> | 32 | #include <linux/backlight.h> |
| 32 | 33 | ||
| @@ -664,6 +665,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) | |||
| 664 | int | 665 | int |
| 665 | atombios_get_encoder_mode(struct drm_encoder *encoder) | 666 | atombios_get_encoder_mode(struct drm_encoder *encoder) |
| 666 | { | 667 | { |
| 668 | struct drm_device *dev = encoder->dev; | ||
| 669 | struct radeon_device *rdev = dev->dev_private; | ||
| 667 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 670 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 668 | struct drm_connector *connector; | 671 | struct drm_connector *connector; |
| 669 | struct radeon_connector *radeon_connector; | 672 | struct radeon_connector *radeon_connector; |
| @@ -728,6 +731,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) | |||
| 728 | dig_connector = radeon_connector->con_priv; | 731 | dig_connector = radeon_connector->con_priv; |
| 729 | if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || | 732 | if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
| 730 | (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { | 733 | (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { |
| 734 | if (radeon_audio != 0 && ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev)) | ||
| 735 | return ATOM_ENCODER_MODE_DP_AUDIO; | ||
| 731 | return ATOM_ENCODER_MODE_DP; | 736 | return ATOM_ENCODER_MODE_DP; |
| 732 | } else if (radeon_audio != 0) { | 737 | } else if (radeon_audio != 0) { |
| 733 | if (radeon_connector->audio == RADEON_AUDIO_ENABLE) | 738 | if (radeon_connector->audio == RADEON_AUDIO_ENABLE) |
| @@ -742,6 +747,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) | |||
| 742 | } | 747 | } |
| 743 | break; | 748 | break; |
| 744 | case DRM_MODE_CONNECTOR_eDP: | 749 | case DRM_MODE_CONNECTOR_eDP: |
| 750 | if (radeon_audio != 0 && ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev)) | ||
| 751 | return ATOM_ENCODER_MODE_DP_AUDIO; | ||
| 745 | return ATOM_ENCODER_MODE_DP; | 752 | return ATOM_ENCODER_MODE_DP; |
| 746 | case DRM_MODE_CONNECTOR_DVIA: | 753 | case DRM_MODE_CONNECTOR_DVIA: |
| 747 | case DRM_MODE_CONNECTOR_VGA: | 754 | case DRM_MODE_CONNECTOR_VGA: |
| @@ -1615,6 +1622,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) | |||
| 1615 | struct radeon_connector *radeon_connector = NULL; | 1622 | struct radeon_connector *radeon_connector = NULL; |
| 1616 | struct radeon_connector_atom_dig *radeon_dig_connector = NULL; | 1623 | struct radeon_connector_atom_dig *radeon_dig_connector = NULL; |
| 1617 | bool travis_quirk = false; | 1624 | bool travis_quirk = false; |
| 1625 | int encoder_mode; | ||
| 1618 | 1626 | ||
| 1619 | if (connector) { | 1627 | if (connector) { |
| 1620 | radeon_connector = to_radeon_connector(connector); | 1628 | radeon_connector = to_radeon_connector(connector); |
| @@ -1710,6 +1718,11 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) | |||
| 1710 | } | 1718 | } |
| 1711 | break; | 1719 | break; |
| 1712 | } | 1720 | } |
| 1721 | |||
| 1722 | encoder_mode = atombios_get_encoder_mode(encoder); | ||
| 1723 | if (radeon_audio != 0 && | ||
| 1724 | (encoder_mode == ATOM_ENCODER_MODE_HDMI || ENCODER_MODE_IS_DP(encoder_mode))) | ||
| 1725 | radeon_audio_dpms(encoder, mode); | ||
| 1713 | } | 1726 | } |
| 1714 | 1727 | ||
| 1715 | static void | 1728 | static void |
| @@ -2123,6 +2136,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
| 2123 | struct drm_device *dev = encoder->dev; | 2136 | struct drm_device *dev = encoder->dev; |
| 2124 | struct radeon_device *rdev = dev->dev_private; | 2137 | struct radeon_device *rdev = dev->dev_private; |
| 2125 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 2138 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 2139 | int encoder_mode; | ||
| 2126 | 2140 | ||
| 2127 | radeon_encoder->pixel_clock = adjusted_mode->clock; | 2141 | radeon_encoder->pixel_clock = adjusted_mode->clock; |
| 2128 | 2142 | ||
| @@ -2149,6 +2163,10 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
| 2149 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: | 2163 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: |
| 2150 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | 2164 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: |
| 2151 | /* handled in dpms */ | 2165 | /* handled in dpms */ |
| 2166 | encoder_mode = atombios_get_encoder_mode(encoder); | ||
| 2167 | if (radeon_audio != 0 && | ||
| 2168 | (encoder_mode == ATOM_ENCODER_MODE_HDMI || ENCODER_MODE_IS_DP(encoder_mode))) | ||
| 2169 | radeon_audio_mode_set(encoder, adjusted_mode); | ||
| 2152 | break; | 2170 | break; |
| 2153 | case ENCODER_OBJECT_ID_INTERNAL_DDI: | 2171 | case ENCODER_OBJECT_ID_INTERNAL_DDI: |
| 2154 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: | 2172 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: |
| @@ -2170,13 +2188,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
| 2170 | } | 2188 | } |
| 2171 | 2189 | ||
| 2172 | atombios_apply_encoder_quirks(encoder, adjusted_mode); | 2190 | atombios_apply_encoder_quirks(encoder, adjusted_mode); |
| 2173 | |||
| 2174 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { | ||
| 2175 | if (rdev->asic->display.hdmi_enable) | ||
| 2176 | radeon_hdmi_enable(rdev, encoder, true); | ||
| 2177 | if (rdev->asic->display.hdmi_setmode) | ||
| 2178 | radeon_hdmi_setmode(rdev, encoder, adjusted_mode); | ||
| 2179 | } | ||
| 2180 | } | 2191 | } |
| 2181 | 2192 | ||
| 2182 | static bool | 2193 | static bool |
| @@ -2442,10 +2453,6 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) | |||
| 2442 | 2453 | ||
| 2443 | disable_done: | 2454 | disable_done: |
| 2444 | if (radeon_encoder_is_digital(encoder)) { | 2455 | if (radeon_encoder_is_digital(encoder)) { |
| 2445 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { | ||
| 2446 | if (rdev->asic->display.hdmi_enable) | ||
| 2447 | radeon_hdmi_enable(rdev, encoder, false); | ||
| 2448 | } | ||
| 2449 | dig = radeon_encoder->enc_priv; | 2456 | dig = radeon_encoder->enc_priv; |
| 2450 | dig->dig_encoder = -1; | 2457 | dig->dig_encoder = -1; |
| 2451 | } | 2458 | } |
diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c index 0b2929de9f41..db08f17be76b 100644 --- a/drivers/gpu/drm/radeon/btc_dpm.c +++ b/drivers/gpu/drm/radeon/btc_dpm.c | |||
| @@ -2277,6 +2277,7 @@ static void btc_update_requested_ps(struct radeon_device *rdev, | |||
| 2277 | eg_pi->requested_rps.ps_priv = &eg_pi->requested_ps; | 2277 | eg_pi->requested_rps.ps_priv = &eg_pi->requested_ps; |
| 2278 | } | 2278 | } |
| 2279 | 2279 | ||
| 2280 | #if 0 | ||
| 2280 | void btc_dpm_reset_asic(struct radeon_device *rdev) | 2281 | void btc_dpm_reset_asic(struct radeon_device *rdev) |
| 2281 | { | 2282 | { |
| 2282 | rv770_restrict_performance_levels_before_switch(rdev); | 2283 | rv770_restrict_performance_levels_before_switch(rdev); |
| @@ -2284,6 +2285,7 @@ void btc_dpm_reset_asic(struct radeon_device *rdev) | |||
| 2284 | btc_set_boot_state_timing(rdev); | 2285 | btc_set_boot_state_timing(rdev); |
| 2285 | rv770_set_boot_state(rdev); | 2286 | rv770_set_boot_state(rdev); |
| 2286 | } | 2287 | } |
| 2288 | #endif | ||
| 2287 | 2289 | ||
| 2288 | int btc_dpm_pre_set_power_state(struct radeon_device *rdev) | 2290 | int btc_dpm_pre_set_power_state(struct radeon_device *rdev) |
| 2289 | { | 2291 | { |
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index f373a81ba3d5..bcd2f1fe803f 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c | |||
| @@ -187,6 +187,9 @@ static int ci_update_uvd_dpm(struct radeon_device *rdev, bool gate); | |||
| 187 | static PPSMC_Result ci_send_msg_to_smc_with_parameter(struct radeon_device *rdev, | 187 | static PPSMC_Result ci_send_msg_to_smc_with_parameter(struct radeon_device *rdev, |
| 188 | PPSMC_Msg msg, u32 parameter); | 188 | PPSMC_Msg msg, u32 parameter); |
| 189 | 189 | ||
| 190 | static void ci_thermal_start_smc_fan_control(struct radeon_device *rdev); | ||
| 191 | static void ci_fan_ctrl_set_default_mode(struct radeon_device *rdev); | ||
| 192 | |||
| 190 | static struct ci_power_info *ci_get_pi(struct radeon_device *rdev) | 193 | static struct ci_power_info *ci_get_pi(struct radeon_device *rdev) |
| 191 | { | 194 | { |
| 192 | struct ci_power_info *pi = rdev->pm.dpm.priv; | 195 | 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) | |||
| 1043 | return -EINVAL; | 1046 | return -EINVAL; |
| 1044 | } | 1047 | } |
| 1045 | 1048 | ||
| 1049 | pi->fan_is_controlled_by_smc = true; | ||
| 1046 | return 0; | 1050 | return 0; |
| 1047 | } | 1051 | } |
| 1048 | 1052 | ||
| 1049 | #if 0 | ||
| 1050 | static int ci_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev) | 1053 | static int ci_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev) |
| 1051 | { | 1054 | { |
| 1052 | PPSMC_Result ret; | 1055 | PPSMC_Result ret; |
| 1056 | struct ci_power_info *pi = ci_get_pi(rdev); | ||
| 1053 | 1057 | ||
| 1054 | ret = ci_send_msg_to_smc(rdev, PPSMC_StopFanControl); | 1058 | ret = ci_send_msg_to_smc(rdev, PPSMC_StopFanControl); |
| 1055 | if (ret == PPSMC_Result_OK) | 1059 | if (ret == PPSMC_Result_OK) { |
| 1060 | pi->fan_is_controlled_by_smc = false; | ||
| 1056 | return 0; | 1061 | return 0; |
| 1057 | else | 1062 | } else |
| 1058 | return -EINVAL; | 1063 | return -EINVAL; |
| 1059 | } | 1064 | } |
| 1060 | 1065 | ||
| 1061 | static int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, | 1066 | int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, |
| 1062 | u32 *speed) | 1067 | u32 *speed) |
| 1063 | { | 1068 | { |
| 1064 | u32 duty, duty100; | 1069 | u32 duty, duty100; |
| @@ -1083,21 +1088,22 @@ static int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, | |||
| 1083 | return 0; | 1088 | return 0; |
| 1084 | } | 1089 | } |
| 1085 | 1090 | ||
| 1086 | static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, | 1091 | int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, |
| 1087 | u32 speed) | 1092 | u32 speed) |
| 1088 | { | 1093 | { |
| 1089 | u32 tmp; | 1094 | u32 tmp; |
| 1090 | u32 duty, duty100; | 1095 | u32 duty, duty100; |
| 1091 | u64 tmp64; | 1096 | u64 tmp64; |
| 1097 | struct ci_power_info *pi = ci_get_pi(rdev); | ||
| 1092 | 1098 | ||
| 1093 | if (rdev->pm.no_fan) | 1099 | if (rdev->pm.no_fan) |
| 1094 | return -ENOENT; | 1100 | return -ENOENT; |
| 1095 | 1101 | ||
| 1096 | if (speed > 100) | 1102 | if (pi->fan_is_controlled_by_smc) |
| 1097 | return -EINVAL; | 1103 | return -EINVAL; |
| 1098 | 1104 | ||
| 1099 | if (rdev->pm.dpm.fan.ucode_fan_control) | 1105 | if (speed > 100) |
| 1100 | ci_fan_ctrl_stop_smc_fan_control(rdev); | 1106 | return -EINVAL; |
| 1101 | 1107 | ||
| 1102 | duty100 = (RREG32_SMC(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; | 1108 | duty100 = (RREG32_SMC(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; |
| 1103 | 1109 | ||
| @@ -1112,11 +1118,38 @@ static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, | |||
| 1112 | tmp |= FDO_STATIC_DUTY(duty); | 1118 | tmp |= FDO_STATIC_DUTY(duty); |
| 1113 | WREG32_SMC(CG_FDO_CTRL0, tmp); | 1119 | WREG32_SMC(CG_FDO_CTRL0, tmp); |
| 1114 | 1120 | ||
| 1115 | ci_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC); | ||
| 1116 | |||
| 1117 | return 0; | 1121 | return 0; |
| 1118 | } | 1122 | } |
| 1119 | 1123 | ||
| 1124 | void ci_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode) | ||
| 1125 | { | ||
| 1126 | if (mode) { | ||
| 1127 | /* stop auto-manage */ | ||
| 1128 | if (rdev->pm.dpm.fan.ucode_fan_control) | ||
| 1129 | ci_fan_ctrl_stop_smc_fan_control(rdev); | ||
| 1130 | ci_fan_ctrl_set_static_mode(rdev, mode); | ||
| 1131 | } else { | ||
| 1132 | /* restart auto-manage */ | ||
| 1133 | if (rdev->pm.dpm.fan.ucode_fan_control) | ||
| 1134 | ci_thermal_start_smc_fan_control(rdev); | ||
| 1135 | else | ||
| 1136 | ci_fan_ctrl_set_default_mode(rdev); | ||
| 1137 | } | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | u32 ci_fan_ctrl_get_mode(struct radeon_device *rdev) | ||
| 1141 | { | ||
| 1142 | struct ci_power_info *pi = ci_get_pi(rdev); | ||
| 1143 | u32 tmp; | ||
| 1144 | |||
| 1145 | if (pi->fan_is_controlled_by_smc) | ||
| 1146 | return 0; | ||
| 1147 | |||
| 1148 | tmp = RREG32_SMC(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK; | ||
| 1149 | return (tmp >> FDO_PWM_MODE_SHIFT); | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | #if 0 | ||
| 1120 | static int ci_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev, | 1153 | static int ci_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev, |
| 1121 | u32 *speed) | 1154 | u32 *speed) |
| 1122 | { | 1155 | { |
| @@ -1698,10 +1731,12 @@ static int ci_set_overdrive_target_tdp(struct radeon_device *rdev, | |||
| 1698 | return 0; | 1731 | return 0; |
| 1699 | } | 1732 | } |
| 1700 | 1733 | ||
| 1734 | #if 0 | ||
| 1701 | static int ci_set_boot_state(struct radeon_device *rdev) | 1735 | static int ci_set_boot_state(struct radeon_device *rdev) |
| 1702 | { | 1736 | { |
| 1703 | return ci_enable_sclk_mclk_dpm(rdev, false); | 1737 | return ci_enable_sclk_mclk_dpm(rdev, false); |
| 1704 | } | 1738 | } |
| 1739 | #endif | ||
| 1705 | 1740 | ||
| 1706 | static u32 ci_get_average_sclk_freq(struct radeon_device *rdev) | 1741 | static u32 ci_get_average_sclk_freq(struct radeon_device *rdev) |
| 1707 | { | 1742 | { |
| @@ -5343,10 +5378,12 @@ int ci_dpm_set_power_state(struct radeon_device *rdev) | |||
| 5343 | return 0; | 5378 | return 0; |
| 5344 | } | 5379 | } |
| 5345 | 5380 | ||
| 5381 | #if 0 | ||
| 5346 | void ci_dpm_reset_asic(struct radeon_device *rdev) | 5382 | void ci_dpm_reset_asic(struct radeon_device *rdev) |
| 5347 | { | 5383 | { |
| 5348 | ci_set_boot_state(rdev); | 5384 | ci_set_boot_state(rdev); |
| 5349 | } | 5385 | } |
| 5386 | #endif | ||
| 5350 | 5387 | ||
| 5351 | void ci_dpm_display_configuration_changed(struct radeon_device *rdev) | 5388 | void ci_dpm_display_configuration_changed(struct radeon_device *rdev) |
| 5352 | { | 5389 | { |
diff --git a/drivers/gpu/drm/radeon/ci_dpm.h b/drivers/gpu/drm/radeon/ci_dpm.h index 84e3d3bcf9f3..723220ffbea2 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.h +++ b/drivers/gpu/drm/radeon/ci_dpm.h | |||
| @@ -291,6 +291,7 @@ struct ci_power_info { | |||
| 291 | struct ci_ps requested_ps; | 291 | struct ci_ps requested_ps; |
| 292 | /* fan control */ | 292 | /* fan control */ |
| 293 | bool fan_ctrl_is_in_default_mode; | 293 | bool fan_ctrl_is_in_default_mode; |
| 294 | bool fan_is_controlled_by_smc; | ||
| 294 | u32 t_min; | 295 | u32 t_min; |
| 295 | u32 fan_ctrl_default_mode; | 296 | u32 fan_ctrl_default_mode; |
| 296 | }; | 297 | }; |
diff --git a/drivers/gpu/drm/radeon/ci_smc.c b/drivers/gpu/drm/radeon/ci_smc.c index e78bcad7a43e..35c6f648ba04 100644 --- a/drivers/gpu/drm/radeon/ci_smc.c +++ b/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) | |||
| 184 | return (PPSMC_Result)tmp; | 184 | return (PPSMC_Result)tmp; |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | #if 0 | ||
| 187 | PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev) | 188 | PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev) |
| 188 | { | 189 | { |
| 189 | u32 tmp; | 190 | u32 tmp; |
| @@ -201,6 +202,7 @@ PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev) | |||
| 201 | 202 | ||
| 202 | return PPSMC_Result_OK; | 203 | return PPSMC_Result_OK; |
| 203 | } | 204 | } |
| 205 | #endif | ||
| 204 | 206 | ||
| 205 | int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit) | 207 | int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit) |
| 206 | { | 208 | { |
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index ed336fbfab7c..de77c27d8106 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include "drmP.h" | 27 | #include "drmP.h" |
| 28 | #include "radeon.h" | 28 | #include "radeon.h" |
| 29 | #include "radeon_asic.h" | 29 | #include "radeon_asic.h" |
| 30 | #include "radeon_audio.h" | ||
| 30 | #include "cikd.h" | 31 | #include "cikd.h" |
| 31 | #include "atom.h" | 32 | #include "atom.h" |
| 32 | #include "cik_blit_shaders.h" | 33 | #include "cik_blit_shaders.h" |
| @@ -8517,7 +8518,7 @@ static int cik_startup(struct radeon_device *rdev) | |||
| 8517 | return r; | 8518 | return r; |
| 8518 | } | 8519 | } |
| 8519 | 8520 | ||
| 8520 | r = dce6_audio_init(rdev); | 8521 | r = radeon_audio_init(rdev); |
| 8521 | if (r) | 8522 | if (r) |
| 8522 | return r; | 8523 | return r; |
| 8523 | 8524 | ||
| @@ -8575,7 +8576,7 @@ int cik_suspend(struct radeon_device *rdev) | |||
| 8575 | { | 8576 | { |
| 8576 | radeon_kfd_suspend(rdev); | 8577 | radeon_kfd_suspend(rdev); |
| 8577 | radeon_pm_suspend(rdev); | 8578 | radeon_pm_suspend(rdev); |
| 8578 | dce6_audio_fini(rdev); | 8579 | radeon_audio_fini(rdev); |
| 8579 | radeon_vm_manager_fini(rdev); | 8580 | radeon_vm_manager_fini(rdev); |
| 8580 | cik_cp_enable(rdev, false); | 8581 | cik_cp_enable(rdev, false); |
| 8581 | cik_sdma_enable(rdev, false); | 8582 | cik_sdma_enable(rdev, false); |
diff --git a/drivers/gpu/drm/radeon/cypress_dpm.c b/drivers/gpu/drm/radeon/cypress_dpm.c index 9aad0327e4d1..ca058589ddef 100644 --- a/drivers/gpu/drm/radeon/cypress_dpm.c +++ b/drivers/gpu/drm/radeon/cypress_dpm.c | |||
| @@ -2005,11 +2005,13 @@ int cypress_dpm_set_power_state(struct radeon_device *rdev) | |||
| 2005 | return 0; | 2005 | return 0; |
| 2006 | } | 2006 | } |
| 2007 | 2007 | ||
| 2008 | #if 0 | ||
| 2008 | void cypress_dpm_reset_asic(struct radeon_device *rdev) | 2009 | void cypress_dpm_reset_asic(struct radeon_device *rdev) |
| 2009 | { | 2010 | { |
| 2010 | rv770_restrict_performance_levels_before_switch(rdev); | 2011 | rv770_restrict_performance_levels_before_switch(rdev); |
| 2011 | rv770_set_boot_state(rdev); | 2012 | rv770_set_boot_state(rdev); |
| 2012 | } | 2013 | } |
| 2014 | #endif | ||
| 2013 | 2015 | ||
| 2014 | void cypress_dpm_display_configuration_changed(struct radeon_device *rdev) | 2016 | void cypress_dpm_display_configuration_changed(struct radeon_device *rdev) |
| 2015 | { | 2017 | { |
diff --git a/drivers/gpu/drm/radeon/dce3_1_afmt.c b/drivers/gpu/drm/radeon/dce3_1_afmt.c index bafdf92a5732..f04205170b8a 100644 --- a/drivers/gpu/drm/radeon/dce3_1_afmt.c +++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c | |||
| @@ -24,37 +24,17 @@ | |||
| 24 | #include <drm/drmP.h> | 24 | #include <drm/drmP.h> |
| 25 | #include "radeon.h" | 25 | #include "radeon.h" |
| 26 | #include "radeon_asic.h" | 26 | #include "radeon_asic.h" |
| 27 | #include "radeon_audio.h" | ||
| 27 | #include "r600d.h" | 28 | #include "r600d.h" |
| 28 | 29 | ||
| 29 | static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder) | 30 | void dce3_2_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, |
| 31 | u8 *sadb, int sad_count) | ||
| 30 | { | 32 | { |
| 31 | struct radeon_device *rdev = encoder->dev->dev_private; | 33 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 32 | struct drm_connector *connector; | ||
| 33 | struct radeon_connector *radeon_connector = NULL; | ||
| 34 | u32 tmp; | 34 | u32 tmp; |
| 35 | u8 *sadb = NULL; | ||
| 36 | int sad_count; | ||
| 37 | |||
| 38 | list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { | ||
| 39 | if (connector->encoder == encoder) { | ||
| 40 | radeon_connector = to_radeon_connector(connector); | ||
| 41 | break; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | if (!radeon_connector) { | ||
| 46 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
| 47 | return; | ||
| 48 | } | ||
| 49 | |||
| 50 | sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb); | ||
| 51 | if (sad_count < 0) { | ||
| 52 | DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); | ||
| 53 | sad_count = 0; | ||
| 54 | } | ||
| 55 | 35 | ||
| 56 | /* program the speaker allocation */ | 36 | /* program the speaker allocation */ |
| 57 | tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); | 37 | tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); |
| 58 | tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); | 38 | tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); |
| 59 | /* set HDMI mode */ | 39 | /* set HDMI mode */ |
| 60 | tmp |= HDMI_CONNECTION; | 40 | tmp |= HDMI_CONNECTION; |
| @@ -62,19 +42,32 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder) | |||
| 62 | tmp |= SPEAKER_ALLOCATION(sadb[0]); | 42 | tmp |= SPEAKER_ALLOCATION(sadb[0]); |
| 63 | else | 43 | else |
| 64 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ | 44 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ |
| 65 | WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); | 45 | WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); |
| 66 | |||
| 67 | kfree(sadb); | ||
| 68 | } | 46 | } |
| 69 | 47 | ||
| 70 | static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder) | 48 | void dce3_2_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, |
| 49 | u8 *sadb, int sad_count) | ||
| 71 | { | 50 | { |
| 72 | struct radeon_device *rdev = encoder->dev->dev_private; | 51 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 73 | struct drm_connector *connector; | 52 | u32 tmp; |
| 74 | struct radeon_connector *radeon_connector = NULL; | 53 | |
| 75 | struct cea_sad *sads; | 54 | /* program the speaker allocation */ |
| 76 | int i, sad_count; | 55 | tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); |
| 56 | tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK); | ||
| 57 | /* set DP mode */ | ||
| 58 | tmp |= DP_CONNECTION; | ||
| 59 | if (sad_count) | ||
| 60 | tmp |= SPEAKER_ALLOCATION(sadb[0]); | ||
| 61 | else | ||
| 62 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ | ||
| 63 | WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); | ||
| 64 | } | ||
| 77 | 65 | ||
| 66 | void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder, | ||
| 67 | struct cea_sad *sads, int sad_count) | ||
| 68 | { | ||
| 69 | int i; | ||
| 70 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 78 | static const u16 eld_reg_to_type[][2] = { | 71 | static const u16 eld_reg_to_type[][2] = { |
| 79 | { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM }, | 72 | { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM }, |
| 80 | { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 }, | 73 | { 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) | |||
| 90 | { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, | 83 | { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, |
| 91 | }; | 84 | }; |
| 92 | 85 | ||
| 93 | list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { | ||
| 94 | if (connector->encoder == encoder) { | ||
| 95 | radeon_connector = to_radeon_connector(connector); | ||
| 96 | break; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | if (!radeon_connector) { | ||
| 101 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
| 102 | return; | ||
| 103 | } | ||
| 104 | |||
| 105 | sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); | ||
| 106 | if (sad_count <= 0) { | ||
| 107 | DRM_ERROR("Couldn't read SADs: %d\n", sad_count); | ||
| 108 | return; | ||
| 109 | } | ||
| 110 | BUG_ON(!sads); | ||
| 111 | |||
| 112 | for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { | 86 | for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { |
| 113 | u32 value = 0; | 87 | u32 value = 0; |
| 114 | u8 stereo_freqs = 0; | 88 | u8 stereo_freqs = 0; |
| @@ -135,110 +109,124 @@ static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder) | |||
| 135 | 109 | ||
| 136 | value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs); | 110 | value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs); |
| 137 | 111 | ||
| 138 | WREG32(eld_reg_to_type[i][0], value); | 112 | WREG32_ENDPOINT(0, eld_reg_to_type[i][0], value); |
| 139 | } | 113 | } |
| 140 | |||
| 141 | kfree(sads); | ||
| 142 | } | 114 | } |
| 143 | 115 | ||
| 144 | /* | 116 | void dce3_2_audio_set_dto(struct radeon_device *rdev, |
| 145 | * update the info frames with the data from the current display mode | 117 | struct radeon_crtc *crtc, unsigned int clock) |
| 146 | */ | ||
| 147 | void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) | ||
| 148 | { | 118 | { |
| 149 | struct drm_device *dev = encoder->dev; | 119 | struct radeon_encoder *radeon_encoder; |
| 150 | struct radeon_device *rdev = dev->dev_private; | 120 | struct radeon_encoder_atom_dig *dig; |
| 151 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 121 | unsigned int max_ratio = clock / 24000; |
| 152 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 122 | u32 dto_phase; |
| 153 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; | 123 | u32 wallclock_ratio; |
| 154 | struct hdmi_avi_infoframe frame; | 124 | u32 dto_cntl; |
| 155 | uint32_t offset; | 125 | |
| 156 | ssize_t err; | 126 | if (!crtc) |
| 157 | |||
| 158 | if (!dig || !dig->afmt) | ||
| 159 | return; | ||
| 160 | |||
| 161 | /* Silent, r600_hdmi_enable will raise WARN for us */ | ||
| 162 | if (!dig->afmt->enabled) | ||
| 163 | return; | 127 | return; |
| 164 | offset = dig->afmt->offset; | ||
| 165 | |||
| 166 | /* disable audio prior to setting up hw */ | ||
| 167 | dig->afmt->pin = r600_audio_get_pin(rdev); | ||
| 168 | r600_audio_enable(rdev, dig->afmt->pin, 0); | ||
| 169 | 128 | ||
| 170 | r600_audio_set_dto(encoder, mode->clock); | 129 | radeon_encoder = to_radeon_encoder(crtc->encoder); |
| 130 | dig = radeon_encoder->enc_priv; | ||
| 171 | 131 | ||
| 172 | WREG32(HDMI0_VBI_PACKET_CONTROL + offset, | 132 | if (!dig) |
| 173 | HDMI0_NULL_SEND); /* send null packets when required */ | 133 | return; |
| 174 | |||
| 175 | WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000); | ||
| 176 | 134 | ||
| 177 | if (ASIC_IS_DCE32(rdev)) { | 135 | if (max_ratio >= 8) { |
| 178 | WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, | 136 | dto_phase = 192 * 1000; |
| 179 | HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ | 137 | wallclock_ratio = 3; |
| 180 | HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ | 138 | } else if (max_ratio >= 4) { |
| 181 | WREG32(AFMT_AUDIO_PACKET_CONTROL + offset, | 139 | dto_phase = 96 * 1000; |
| 182 | AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */ | 140 | wallclock_ratio = 2; |
| 183 | AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ | 141 | } else if (max_ratio >= 2) { |
| 142 | dto_phase = 48 * 1000; | ||
| 143 | wallclock_ratio = 1; | ||
| 184 | } else { | 144 | } else { |
| 185 | WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, | 145 | dto_phase = 24 * 1000; |
| 186 | HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ | 146 | wallclock_ratio = 0; |
| 187 | HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ | ||
| 188 | HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */ | ||
| 189 | HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ | ||
| 190 | } | 147 | } |
| 191 | 148 | ||
| 192 | if (ASIC_IS_DCE32(rdev)) { | 149 | /* Express [24MHz / target pixel clock] as an exact rational |
| 193 | dce3_2_afmt_write_speaker_allocation(encoder); | 150 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE |
| 194 | dce3_2_afmt_write_sad_regs(encoder); | 151 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator |
| 152 | */ | ||
| 153 | if (dig->dig_encoder == 0) { | ||
| 154 | dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; | ||
| 155 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); | ||
| 156 | WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl); | ||
| 157 | WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase); | ||
| 158 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock); | ||
| 159 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ | ||
| 160 | } else { | ||
| 161 | dto_cntl = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; | ||
| 162 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); | ||
| 163 | WREG32(DCCG_AUDIO_DTO1_CNTL, dto_cntl); | ||
| 164 | WREG32(DCCG_AUDIO_DTO1_PHASE, dto_phase); | ||
| 165 | WREG32(DCCG_AUDIO_DTO1_MODULE, clock); | ||
| 166 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ | ||
| 195 | } | 167 | } |
| 168 | } | ||
| 169 | |||
| 170 | void dce3_2_hdmi_update_acr(struct drm_encoder *encoder, long offset, | ||
| 171 | const struct radeon_hdmi_acr *acr) | ||
| 172 | { | ||
| 173 | struct drm_device *dev = encoder->dev; | ||
| 174 | struct radeon_device *rdev = dev->dev_private; | ||
| 196 | 175 | ||
| 197 | WREG32(HDMI0_ACR_PACKET_CONTROL + offset, | 176 | WREG32(HDMI0_ACR_PACKET_CONTROL + offset, |
| 198 | HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */ | 177 | HDMI0_ACR_SOURCE | /* select SW CTS value */ |
| 199 | HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ | 178 | HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ |
| 200 | 179 | ||
| 201 | WREG32(HDMI0_VBI_PACKET_CONTROL + offset, | 180 | WREG32_P(HDMI0_ACR_32_0 + offset, |
| 202 | HDMI0_NULL_SEND | /* send null packets when required */ | 181 | HDMI0_ACR_CTS_32(acr->cts_32khz), |
| 203 | HDMI0_GC_SEND | /* send general control packets */ | 182 | ~HDMI0_ACR_CTS_32_MASK); |
| 204 | HDMI0_GC_CONT); /* send general control packets every frame */ | 183 | WREG32_P(HDMI0_ACR_32_1 + offset, |
| 205 | 184 | HDMI0_ACR_N_32(acr->n_32khz), | |
| 206 | /* TODO: HDMI0_AUDIO_INFO_UPDATE */ | 185 | ~HDMI0_ACR_N_32_MASK); |
| 207 | WREG32(HDMI0_INFOFRAME_CONTROL0 + offset, | 186 | |
| 208 | HDMI0_AVI_INFO_SEND | /* enable AVI info frames */ | 187 | WREG32_P(HDMI0_ACR_44_0 + offset, |
| 209 | HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */ | 188 | HDMI0_ACR_CTS_44(acr->cts_44_1khz), |
| 210 | HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ | 189 | ~HDMI0_ACR_CTS_44_MASK); |
| 211 | HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */ | 190 | WREG32_P(HDMI0_ACR_44_1 + offset, |
| 212 | 191 | HDMI0_ACR_N_44(acr->n_44_1khz), | |
| 213 | WREG32(HDMI0_INFOFRAME_CONTROL1 + offset, | 192 | ~HDMI0_ACR_N_44_MASK); |
| 214 | HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */ | 193 | |
| 215 | HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */ | 194 | WREG32_P(HDMI0_ACR_48_0 + offset, |
| 216 | 195 | HDMI0_ACR_CTS_48(acr->cts_48khz), | |
| 217 | WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */ | 196 | ~HDMI0_ACR_CTS_48_MASK); |
| 218 | 197 | WREG32_P(HDMI0_ACR_48_1 + offset, | |
| 219 | err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); | 198 | HDMI0_ACR_N_48(acr->n_48khz), |
| 220 | if (err < 0) { | 199 | ~HDMI0_ACR_N_48_MASK); |
| 221 | DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); | 200 | } |
| 222 | return; | ||
| 223 | } | ||
| 224 | 201 | ||
| 225 | err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); | 202 | void dce3_2_set_audio_packet(struct drm_encoder *encoder, u32 offset) |
| 226 | if (err < 0) { | 203 | { |
| 227 | DRM_ERROR("failed to pack AVI infoframe: %zd\n", err); | 204 | struct drm_device *dev = encoder->dev; |
| 228 | return; | 205 | struct radeon_device *rdev = dev->dev_private; |
| 229 | } | ||
| 230 | 206 | ||
| 231 | r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer)); | 207 | WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, |
| 232 | r600_hdmi_update_ACR(encoder, mode->clock); | 208 | HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ |
| 209 | HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ | ||
| 233 | 210 | ||
| 234 | /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ | 211 | WREG32(AFMT_AUDIO_PACKET_CONTROL + offset, |
| 235 | WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF); | 212 | AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */ |
| 236 | WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF); | 213 | AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ |
| 237 | WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001); | ||
| 238 | WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001); | ||
| 239 | 214 | ||
| 240 | r600_hdmi_audio_workaround(encoder); | 215 | WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset, |
| 216 | HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ | ||
| 217 | HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */ | ||
| 241 | 218 | ||
| 242 | /* enable audio after to setting up hw */ | 219 | WREG32_OR(HDMI0_INFOFRAME_CONTROL1 + offset, |
| 243 | r600_audio_enable(rdev, dig->afmt->pin, 0xf); | 220 | HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */ |
| 221 | } | ||
| 222 | |||
| 223 | void dce3_2_set_mute(struct drm_encoder *encoder, u32 offset, bool mute) | ||
| 224 | { | ||
| 225 | struct drm_device *dev = encoder->dev; | ||
| 226 | struct radeon_device *rdev = dev->dev_private; | ||
| 227 | |||
| 228 | if (mute) | ||
| 229 | WREG32_OR(HDMI0_GC + offset, HDMI0_GC_AVMUTE); | ||
| 230 | else | ||
| 231 | WREG32_AND(HDMI0_GC + offset, ~HDMI0_GC_AVMUTE); | ||
| 244 | } | 232 | } |
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index f312edf4d50e..192c80389151 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c | |||
| @@ -23,9 +23,10 @@ | |||
| 23 | #include <linux/hdmi.h> | 23 | #include <linux/hdmi.h> |
| 24 | #include <drm/drmP.h> | 24 | #include <drm/drmP.h> |
| 25 | #include "radeon.h" | 25 | #include "radeon.h" |
| 26 | #include "radeon_audio.h" | ||
| 26 | #include "sid.h" | 27 | #include "sid.h" |
| 27 | 28 | ||
| 28 | static u32 dce6_endpoint_rreg(struct radeon_device *rdev, | 29 | u32 dce6_endpoint_rreg(struct radeon_device *rdev, |
| 29 | u32 block_offset, u32 reg) | 30 | u32 block_offset, u32 reg) |
| 30 | { | 31 | { |
| 31 | unsigned long flags; | 32 | unsigned long flags; |
| @@ -39,7 +40,7 @@ static u32 dce6_endpoint_rreg(struct radeon_device *rdev, | |||
| 39 | return r; | 40 | return r; |
| 40 | } | 41 | } |
| 41 | 42 | ||
| 42 | static void dce6_endpoint_wreg(struct radeon_device *rdev, | 43 | void dce6_endpoint_wreg(struct radeon_device *rdev, |
| 43 | u32 block_offset, u32 reg, u32 v) | 44 | u32 block_offset, u32 reg, u32 v) |
| 44 | { | 45 | { |
| 45 | unsigned long flags; | 46 | unsigned long flags; |
| @@ -54,10 +55,6 @@ static void dce6_endpoint_wreg(struct radeon_device *rdev, | |||
| 54 | spin_unlock_irqrestore(&rdev->end_idx_lock, flags); | 55 | spin_unlock_irqrestore(&rdev->end_idx_lock, flags); |
| 55 | } | 56 | } |
| 56 | 57 | ||
| 57 | #define RREG32_ENDPOINT(block, reg) dce6_endpoint_rreg(rdev, (block), (reg)) | ||
| 58 | #define WREG32_ENDPOINT(block, reg, v) dce6_endpoint_wreg(rdev, (block), (reg), (v)) | ||
| 59 | |||
| 60 | |||
| 61 | static void dce6_afmt_get_connected_pins(struct radeon_device *rdev) | 58 | static void dce6_afmt_get_connected_pins(struct radeon_device *rdev) |
| 62 | { | 59 | { |
| 63 | int i; | 60 | int i; |
| @@ -105,13 +102,11 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder) | |||
| 105 | } | 102 | } |
| 106 | 103 | ||
| 107 | void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, | 104 | void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, |
| 108 | struct drm_display_mode *mode) | 105 | struct drm_connector *connector, struct drm_display_mode *mode) |
| 109 | { | 106 | { |
| 110 | struct radeon_device *rdev = encoder->dev->dev_private; | 107 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 111 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 108 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 112 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 109 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| 113 | struct drm_connector *connector; | ||
| 114 | struct radeon_connector *radeon_connector = NULL; | ||
| 115 | u32 tmp = 0, offset; | 110 | u32 tmp = 0, offset; |
| 116 | 111 | ||
| 117 | if (!dig || !dig->afmt || !dig->afmt->pin) | 112 | if (!dig || !dig->afmt || !dig->afmt->pin) |
| @@ -119,18 +114,6 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, | |||
| 119 | 114 | ||
| 120 | offset = dig->afmt->pin->offset; | 115 | offset = dig->afmt->pin->offset; |
| 121 | 116 | ||
| 122 | list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { | ||
| 123 | if (connector->encoder == encoder) { | ||
| 124 | radeon_connector = to_radeon_connector(connector); | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | if (!radeon_connector) { | ||
| 130 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
| 131 | return; | ||
| 132 | } | ||
| 133 | |||
| 134 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) { | 117 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) { |
| 135 | if (connector->latency_present[1]) | 118 | if (connector->latency_present[1]) |
| 136 | tmp = VIDEO_LIPSYNC(connector->video_latency[1]) | | 119 | tmp = VIDEO_LIPSYNC(connector->video_latency[1]) | |
| @@ -147,40 +130,19 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, | |||
| 147 | WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp); | 130 | WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp); |
| 148 | } | 131 | } |
| 149 | 132 | ||
| 150 | void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder) | 133 | void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, |
| 134 | u8 *sadb, int sad_count) | ||
| 151 | { | 135 | { |
| 152 | struct radeon_device *rdev = encoder->dev->dev_private; | 136 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 153 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 137 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 154 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 138 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| 155 | struct drm_connector *connector; | ||
| 156 | struct radeon_connector *radeon_connector = NULL; | ||
| 157 | u32 offset, tmp; | 139 | u32 offset, tmp; |
| 158 | u8 *sadb = NULL; | ||
| 159 | int sad_count; | ||
| 160 | 140 | ||
| 161 | if (!dig || !dig->afmt || !dig->afmt->pin) | 141 | if (!dig || !dig->afmt || !dig->afmt->pin) |
| 162 | return; | 142 | return; |
| 163 | 143 | ||
| 164 | offset = dig->afmt->pin->offset; | 144 | offset = dig->afmt->pin->offset; |
| 165 | 145 | ||
| 166 | list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { | ||
| 167 | if (connector->encoder == encoder) { | ||
| 168 | radeon_connector = to_radeon_connector(connector); | ||
| 169 | break; | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | if (!radeon_connector) { | ||
| 174 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
| 175 | return; | ||
| 176 | } | ||
| 177 | |||
| 178 | sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb); | ||
| 179 | if (sad_count < 0) { | ||
| 180 | DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); | ||
| 181 | sad_count = 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | /* program the speaker allocation */ | 146 | /* program the speaker allocation */ |
| 185 | tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); | 147 | tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); |
| 186 | tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); | 148 | tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); |
| @@ -191,21 +153,41 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder) | |||
| 191 | else | 153 | else |
| 192 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ | 154 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ |
| 193 | WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); | 155 | WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); |
| 194 | |||
| 195 | kfree(sadb); | ||
| 196 | } | 156 | } |
| 197 | 157 | ||
| 198 | void dce6_afmt_write_sad_regs(struct drm_encoder *encoder) | 158 | void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, |
| 159 | u8 *sadb, int sad_count) | ||
| 199 | { | 160 | { |
| 200 | struct radeon_device *rdev = encoder->dev->dev_private; | 161 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 201 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 162 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 202 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 163 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
| 203 | u32 offset; | 164 | u32 offset, tmp; |
| 204 | struct drm_connector *connector; | 165 | |
| 205 | struct radeon_connector *radeon_connector = NULL; | 166 | if (!dig || !dig->afmt || !dig->afmt->pin) |
| 206 | struct cea_sad *sads; | 167 | return; |
| 207 | int i, sad_count; | ||
| 208 | 168 | ||
| 169 | offset = dig->afmt->pin->offset; | ||
| 170 | |||
| 171 | /* program the speaker allocation */ | ||
| 172 | tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); | ||
| 173 | tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK); | ||
| 174 | /* set DP mode */ | ||
| 175 | tmp |= DP_CONNECTION; | ||
| 176 | if (sad_count) | ||
| 177 | tmp |= SPEAKER_ALLOCATION(sadb[0]); | ||
| 178 | else | ||
| 179 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ | ||
| 180 | WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); | ||
| 181 | } | ||
| 182 | |||
| 183 | void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, | ||
| 184 | struct cea_sad *sads, int sad_count) | ||
| 185 | { | ||
| 186 | u32 offset; | ||
| 187 | int i; | ||
| 188 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 189 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 190 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 209 | static const u16 eld_reg_to_type[][2] = { | 191 | static const u16 eld_reg_to_type[][2] = { |
| 210 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM }, | 192 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM }, |
| 211 | { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 }, | 193 | { 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) | |||
| 226 | 208 | ||
| 227 | offset = dig->afmt->pin->offset; | 209 | offset = dig->afmt->pin->offset; |
| 228 | 210 | ||
| 229 | list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { | ||
| 230 | if (connector->encoder == encoder) { | ||
| 231 | radeon_connector = to_radeon_connector(connector); | ||
| 232 | break; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | if (!radeon_connector) { | ||
| 237 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
| 238 | return; | ||
| 239 | } | ||
| 240 | |||
| 241 | sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads); | ||
| 242 | if (sad_count <= 0) { | ||
| 243 | DRM_ERROR("Couldn't read SADs: %d\n", sad_count); | ||
| 244 | return; | ||
| 245 | } | ||
| 246 | BUG_ON(!sads); | ||
| 247 | |||
| 248 | for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { | 211 | for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { |
| 249 | u32 value = 0; | 212 | u32 value = 0; |
| 250 | u8 stereo_freqs = 0; | 213 | u8 stereo_freqs = 0; |
| @@ -273,13 +236,6 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder) | |||
| 273 | 236 | ||
| 274 | WREG32_ENDPOINT(offset, eld_reg_to_type[i][0], value); | 237 | WREG32_ENDPOINT(offset, eld_reg_to_type[i][0], value); |
| 275 | } | 238 | } |
| 276 | |||
| 277 | kfree(sads); | ||
| 278 | } | ||
| 279 | |||
| 280 | static int dce6_audio_chipset_supported(struct radeon_device *rdev) | ||
| 281 | { | ||
| 282 | return !ASIC_IS_NODCE(rdev); | ||
| 283 | } | 239 | } |
| 284 | 240 | ||
| 285 | void dce6_audio_enable(struct radeon_device *rdev, | 241 | void dce6_audio_enable(struct radeon_device *rdev, |
| @@ -293,64 +249,76 @@ void dce6_audio_enable(struct radeon_device *rdev, | |||
| 293 | enable_mask ? AUDIO_ENABLED : 0); | 249 | enable_mask ? AUDIO_ENABLED : 0); |
| 294 | } | 250 | } |
| 295 | 251 | ||
| 296 | static const u32 pin_offsets[7] = | 252 | void dce6_hdmi_audio_set_dto(struct radeon_device *rdev, |
| 297 | { | 253 | struct radeon_crtc *crtc, unsigned int clock) |
| 298 | (0x5e00 - 0x5e00), | ||
| 299 | (0x5e18 - 0x5e00), | ||
| 300 | (0x5e30 - 0x5e00), | ||
| 301 | (0x5e48 - 0x5e00), | ||
| 302 | (0x5e60 - 0x5e00), | ||
| 303 | (0x5e78 - 0x5e00), | ||
| 304 | (0x5e90 - 0x5e00), | ||
| 305 | }; | ||
| 306 | |||
| 307 | int dce6_audio_init(struct radeon_device *rdev) | ||
| 308 | { | 254 | { |
| 309 | int i; | 255 | /* Two dtos; generally use dto0 for HDMI */ |
| 256 | u32 value = 0; | ||
| 310 | 257 | ||
| 311 | if (!radeon_audio || !dce6_audio_chipset_supported(rdev)) | 258 | if (crtc) |
| 312 | return 0; | 259 | value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id); |
| 313 | 260 | ||
| 314 | rdev->audio.enabled = true; | 261 | WREG32(DCCG_AUDIO_DTO_SOURCE, value); |
| 315 | 262 | ||
| 316 | if (ASIC_IS_DCE81(rdev)) /* KV: 4 streams, 7 endpoints */ | 263 | /* Express [24MHz / target pixel clock] as an exact rational |
| 317 | rdev->audio.num_pins = 7; | 264 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE |
| 318 | else if (ASIC_IS_DCE83(rdev)) /* KB: 2 streams, 3 endpoints */ | 265 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator |
| 319 | rdev->audio.num_pins = 3; | 266 | */ |
| 320 | else if (ASIC_IS_DCE8(rdev)) /* BN/HW: 6 streams, 7 endpoints */ | 267 | WREG32(DCCG_AUDIO_DTO0_PHASE, 24000); |
| 321 | rdev->audio.num_pins = 7; | 268 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock); |
| 322 | else if (ASIC_IS_DCE61(rdev)) /* TN: 4 streams, 6 endpoints */ | 269 | } |
| 323 | rdev->audio.num_pins = 6; | ||
| 324 | else if (ASIC_IS_DCE64(rdev)) /* OL: 2 streams, 2 endpoints */ | ||
| 325 | rdev->audio.num_pins = 2; | ||
| 326 | else /* SI: 6 streams, 6 endpoints */ | ||
| 327 | rdev->audio.num_pins = 6; | ||
| 328 | 270 | ||
| 329 | for (i = 0; i < rdev->audio.num_pins; i++) { | 271 | void dce6_dp_audio_set_dto(struct radeon_device *rdev, |
| 330 | rdev->audio.pin[i].channels = -1; | 272 | struct radeon_crtc *crtc, unsigned int clock) |
| 331 | rdev->audio.pin[i].rate = -1; | 273 | { |
| 332 | rdev->audio.pin[i].bits_per_sample = -1; | 274 | /* Two dtos; generally use dto1 for DP */ |
| 333 | rdev->audio.pin[i].status_bits = 0; | 275 | u32 value = 0; |
| 334 | rdev->audio.pin[i].category_code = 0; | 276 | value |= DCCG_AUDIO_DTO_SEL; |
| 335 | rdev->audio.pin[i].connected = false; | 277 | |
| 336 | rdev->audio.pin[i].offset = pin_offsets[i]; | 278 | if (crtc) |
| 337 | rdev->audio.pin[i].id = i; | 279 | value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id); |
| 338 | /* disable audio. it will be set up later */ | 280 | |
| 339 | dce6_audio_enable(rdev, &rdev->audio.pin[i], false); | 281 | WREG32(DCCG_AUDIO_DTO_SOURCE, value); |
| 340 | } | ||
| 341 | 282 | ||
| 342 | return 0; | 283 | /* Express [24MHz / target pixel clock] as an exact rational |
| 284 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE | ||
| 285 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator | ||
| 286 | */ | ||
| 287 | WREG32(DCCG_AUDIO_DTO1_PHASE, 24000); | ||
| 288 | WREG32(DCCG_AUDIO_DTO1_MODULE, clock); | ||
| 343 | } | 289 | } |
| 344 | 290 | ||
| 345 | void dce6_audio_fini(struct radeon_device *rdev) | 291 | void dce6_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable) |
| 346 | { | 292 | { |
| 347 | int i; | 293 | struct drm_device *dev = encoder->dev; |
| 294 | struct radeon_device *rdev = dev->dev_private; | ||
| 295 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 296 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 297 | uint32_t offset; | ||
| 348 | 298 | ||
| 349 | if (!rdev->audio.enabled) | 299 | if (!dig || !dig->afmt) |
| 350 | return; | 300 | return; |
| 351 | 301 | ||
| 352 | for (i = 0; i < rdev->audio.num_pins; i++) | 302 | offset = dig->afmt->offset; |
| 353 | dce6_audio_enable(rdev, &rdev->audio.pin[i], false); | 303 | |
| 304 | if (enable) { | ||
| 305 | if (dig->afmt->enabled) | ||
| 306 | return; | ||
| 307 | |||
| 308 | WREG32(EVERGREEN_DP_SEC_TIMESTAMP + offset, EVERGREEN_DP_SEC_TIMESTAMP_MODE(1)); | ||
| 309 | WREG32(EVERGREEN_DP_SEC_CNTL + offset, | ||
| 310 | EVERGREEN_DP_SEC_ASP_ENABLE | /* Audio packet transmission */ | ||
| 311 | EVERGREEN_DP_SEC_ATP_ENABLE | /* Audio timestamp packet transmission */ | ||
| 312 | EVERGREEN_DP_SEC_AIP_ENABLE | /* Audio infoframe packet transmission */ | ||
| 313 | EVERGREEN_DP_SEC_STREAM_ENABLE); /* Master enable for secondary stream engine */ | ||
| 314 | radeon_audio_enable(rdev, dig->afmt->pin, true); | ||
| 315 | } else { | ||
| 316 | if (!dig->afmt->enabled) | ||
| 317 | return; | ||
| 318 | |||
| 319 | WREG32(EVERGREEN_DP_SEC_CNTL + offset, 0); | ||
| 320 | radeon_audio_enable(rdev, dig->afmt->pin, false); | ||
| 321 | } | ||
| 354 | 322 | ||
| 355 | rdev->audio.enabled = false; | 323 | dig->afmt->enabled = enable; |
| 356 | } | 324 | } |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 85995b4e3338..78600f534c80 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <drm/drmP.h> | 26 | #include <drm/drmP.h> |
| 27 | #include "radeon.h" | 27 | #include "radeon.h" |
| 28 | #include "radeon_asic.h" | 28 | #include "radeon_asic.h" |
| 29 | #include "radeon_audio.h" | ||
| 29 | #include <drm/radeon_drm.h> | 30 | #include <drm/radeon_drm.h> |
| 30 | #include "evergreend.h" | 31 | #include "evergreend.h" |
| 31 | #include "atom.h" | 32 | #include "atom.h" |
| @@ -5286,7 +5287,7 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
| 5286 | return r; | 5287 | return r; |
| 5287 | } | 5288 | } |
| 5288 | 5289 | ||
| 5289 | r = r600_audio_init(rdev); | 5290 | r = radeon_audio_init(rdev); |
| 5290 | if (r) { | 5291 | if (r) { |
| 5291 | DRM_ERROR("radeon: audio init failed\n"); | 5292 | DRM_ERROR("radeon: audio init failed\n"); |
| 5292 | return r; | 5293 | return r; |
| @@ -5332,7 +5333,7 @@ int evergreen_resume(struct radeon_device *rdev) | |||
| 5332 | int evergreen_suspend(struct radeon_device *rdev) | 5333 | int evergreen_suspend(struct radeon_device *rdev) |
| 5333 | { | 5334 | { |
| 5334 | radeon_pm_suspend(rdev); | 5335 | radeon_pm_suspend(rdev); |
| 5335 | r600_audio_fini(rdev); | 5336 | radeon_audio_fini(rdev); |
| 5336 | uvd_v1_0_fini(rdev); | 5337 | uvd_v1_0_fini(rdev); |
| 5337 | radeon_uvd_suspend(rdev); | 5338 | radeon_uvd_suspend(rdev); |
| 5338 | r700_cp_stop(rdev); | 5339 | r700_cp_stop(rdev); |
| @@ -5482,7 +5483,7 @@ int evergreen_init(struct radeon_device *rdev) | |||
| 5482 | void evergreen_fini(struct radeon_device *rdev) | 5483 | void evergreen_fini(struct radeon_device *rdev) |
| 5483 | { | 5484 | { |
| 5484 | radeon_pm_fini(rdev); | 5485 | radeon_pm_fini(rdev); |
| 5485 | r600_audio_fini(rdev); | 5486 | radeon_audio_fini(rdev); |
| 5486 | r700_cp_fini(rdev); | 5487 | r700_cp_fini(rdev); |
| 5487 | r600_dma_fini(rdev); | 5488 | r600_dma_fini(rdev); |
| 5488 | r600_irq_fini(rdev); | 5489 | r600_irq_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 924b1b7ab455..c9e0fbbf76a3 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c | |||
| @@ -83,6 +83,7 @@ struct evergreen_cs_track { | |||
| 83 | u32 htile_offset; | 83 | u32 htile_offset; |
| 84 | u32 htile_surface; | 84 | u32 htile_surface; |
| 85 | struct radeon_bo *htile_bo; | 85 | struct radeon_bo *htile_bo; |
| 86 | unsigned long indirect_draw_buffer_size; | ||
| 86 | }; | 87 | }; |
| 87 | 88 | ||
| 88 | static u32 evergreen_cs_get_aray_mode(u32 tiling_flags) | 89 | static u32 evergreen_cs_get_aray_mode(u32 tiling_flags) |
| @@ -1896,6 +1897,14 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
| 1896 | } | 1897 | } |
| 1897 | break; | 1898 | break; |
| 1898 | } | 1899 | } |
| 1900 | case PACKET3_INDEX_BUFFER_SIZE: | ||
| 1901 | { | ||
| 1902 | if (pkt->count != 0) { | ||
| 1903 | DRM_ERROR("bad INDEX_BUFFER_SIZE\n"); | ||
| 1904 | return -EINVAL; | ||
| 1905 | } | ||
| 1906 | break; | ||
| 1907 | } | ||
| 1899 | case PACKET3_DRAW_INDEX: | 1908 | case PACKET3_DRAW_INDEX: |
| 1900 | { | 1909 | { |
| 1901 | uint64_t offset; | 1910 | uint64_t offset; |
| @@ -2006,6 +2015,67 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
| 2006 | return r; | 2015 | return r; |
| 2007 | } | 2016 | } |
| 2008 | break; | 2017 | break; |
| 2018 | case PACKET3_SET_BASE: | ||
| 2019 | { | ||
| 2020 | /* | ||
| 2021 | 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. | ||
| 2022 | 2 BASE_INDEX Bits [3:0] BASE_INDEX - Base Index specifies which base address is specified in the last two DWs. | ||
| 2023 | 0001: DX11 Draw_Index_Indirect Patch Table Base: Base address for Draw_Index_Indirect data. | ||
| 2024 | 3 ADDRESS_LO Bits [31:3] - Lower bits of QWORD-Aligned Address. Bits [2:0] - Reserved | ||
| 2025 | 4 ADDRESS_HI Bits [31:8] - Reserved. Bits [7:0] - Upper bits of Address [47:32] | ||
| 2026 | */ | ||
| 2027 | if (pkt->count != 2) { | ||
| 2028 | DRM_ERROR("bad SET_BASE\n"); | ||
| 2029 | return -EINVAL; | ||
| 2030 | } | ||
| 2031 | |||
| 2032 | /* currently only supporting setting indirect draw buffer base address */ | ||
| 2033 | if (idx_value != 1) { | ||
| 2034 | DRM_ERROR("bad SET_BASE\n"); | ||
| 2035 | return -EINVAL; | ||
| 2036 | } | ||
| 2037 | |||
| 2038 | r = radeon_cs_packet_next_reloc(p, &reloc, 0); | ||
| 2039 | if (r) { | ||
| 2040 | DRM_ERROR("bad SET_BASE\n"); | ||
| 2041 | return -EINVAL; | ||
| 2042 | } | ||
| 2043 | |||
| 2044 | track->indirect_draw_buffer_size = radeon_bo_size(reloc->robj); | ||
| 2045 | |||
| 2046 | ib[idx+1] = reloc->gpu_offset; | ||
| 2047 | ib[idx+2] = upper_32_bits(reloc->gpu_offset) & 0xff; | ||
| 2048 | |||
| 2049 | break; | ||
| 2050 | } | ||
| 2051 | case PACKET3_DRAW_INDIRECT: | ||
| 2052 | case PACKET3_DRAW_INDEX_INDIRECT: | ||
| 2053 | { | ||
| 2054 | u64 size = pkt->opcode == PACKET3_DRAW_INDIRECT ? 16 : 20; | ||
| 2055 | |||
| 2056 | /* | ||
| 2057 | DW 1 HEADER | ||
| 2058 | 2 DATA_OFFSET Bits [31:0] + byte aligned offset where the required data structure starts. Bits 1:0 are zero | ||
| 2059 | 3 DRAW_INITIATOR Draw Initiator Register. Written to the VGT_DRAW_INITIATOR register for the assigned context | ||
| 2060 | */ | ||
| 2061 | if (pkt->count != 1) { | ||
| 2062 | DRM_ERROR("bad DRAW_INDIRECT\n"); | ||
| 2063 | return -EINVAL; | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | if (idx_value + size > track->indirect_draw_buffer_size) { | ||
| 2067 | dev_warn(p->dev, "DRAW_INDIRECT buffer too small %u + %llu > %lu\n", | ||
| 2068 | idx_value, size, track->indirect_draw_buffer_size); | ||
| 2069 | return -EINVAL; | ||
| 2070 | } | ||
| 2071 | |||
| 2072 | r = evergreen_cs_track_check(p); | ||
| 2073 | if (r) { | ||
| 2074 | dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); | ||
| 2075 | return r; | ||
| 2076 | } | ||
| 2077 | break; | ||
| 2078 | } | ||
| 2009 | case PACKET3_DISPATCH_DIRECT: | 2079 | case PACKET3_DISPATCH_DIRECT: |
| 2010 | if (pkt->count != 3) { | 2080 | if (pkt->count != 3) { |
| 2011 | DRM_ERROR("bad DISPATCH_DIRECT\n"); | 2081 | DRM_ERROR("bad DISPATCH_DIRECT\n"); |
| @@ -3243,7 +3313,13 @@ static int evergreen_vm_packet3_check(struct radeon_device *rdev, | |||
| 3243 | 3313 | ||
| 3244 | switch (pkt->opcode) { | 3314 | switch (pkt->opcode) { |
| 3245 | case PACKET3_NOP: | 3315 | case PACKET3_NOP: |
| 3316 | break; | ||
| 3246 | case PACKET3_SET_BASE: | 3317 | case PACKET3_SET_BASE: |
| 3318 | if (idx_value != 1) { | ||
| 3319 | DRM_ERROR("bad SET_BASE"); | ||
| 3320 | return -EINVAL; | ||
| 3321 | } | ||
| 3322 | break; | ||
| 3247 | case PACKET3_CLEAR_STATE: | 3323 | case PACKET3_CLEAR_STATE: |
| 3248 | case PACKET3_INDEX_BUFFER_SIZE: | 3324 | case PACKET3_INDEX_BUFFER_SIZE: |
| 3249 | case PACKET3_DISPATCH_DIRECT: | 3325 | case PACKET3_DISPATCH_DIRECT: |
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index 53abd9b17a50..1d9aebc79595 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c | |||
| @@ -29,17 +29,12 @@ | |||
| 29 | #include <drm/radeon_drm.h> | 29 | #include <drm/radeon_drm.h> |
| 30 | #include "radeon.h" | 30 | #include "radeon.h" |
| 31 | #include "radeon_asic.h" | 31 | #include "radeon_asic.h" |
| 32 | #include "radeon_audio.h" | ||
| 32 | #include "evergreend.h" | 33 | #include "evergreend.h" |
| 33 | #include "atom.h" | 34 | #include "atom.h" |
| 34 | 35 | ||
| 35 | extern void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder); | ||
| 36 | extern void dce6_afmt_write_sad_regs(struct drm_encoder *encoder); | ||
| 37 | extern void dce6_afmt_select_pin(struct drm_encoder *encoder); | ||
| 38 | extern void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, | ||
| 39 | struct drm_display_mode *mode); | ||
| 40 | |||
| 41 | /* enable the audio stream */ | 36 | /* enable the audio stream */ |
| 42 | static void dce4_audio_enable(struct radeon_device *rdev, | 37 | void dce4_audio_enable(struct radeon_device *rdev, |
| 43 | struct r600_audio_pin *pin, | 38 | struct r600_audio_pin *pin, |
| 44 | u8 enable_mask) | 39 | u8 enable_mask) |
| 45 | { | 40 | { |
| @@ -69,48 +64,42 @@ static void dce4_audio_enable(struct radeon_device *rdev, | |||
| 69 | WREG32(AZ_HOT_PLUG_CONTROL, tmp); | 64 | WREG32(AZ_HOT_PLUG_CONTROL, tmp); |
| 70 | } | 65 | } |
| 71 | 66 | ||
| 72 | /* | 67 | void evergreen_hdmi_update_acr(struct drm_encoder *encoder, long offset, |
| 73 | * update the N and CTS parameters for a given pixel clock rate | 68 | const struct radeon_hdmi_acr *acr) |
| 74 | */ | ||
| 75 | static void evergreen_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) | ||
| 76 | { | 69 | { |
| 77 | struct drm_device *dev = encoder->dev; | 70 | struct drm_device *dev = encoder->dev; |
| 78 | struct radeon_device *rdev = dev->dev_private; | 71 | struct radeon_device *rdev = dev->dev_private; |
| 79 | struct radeon_hdmi_acr acr = r600_hdmi_acr(clock); | 72 | int bpc = 8; |
| 80 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 81 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 82 | uint32_t offset = dig->afmt->offset; | ||
| 83 | 73 | ||
| 84 | WREG32(HDMI_ACR_32_0 + offset, HDMI_ACR_CTS_32(acr.cts_32khz)); | 74 | if (encoder->crtc) { |
| 85 | WREG32(HDMI_ACR_32_1 + offset, acr.n_32khz); | 75 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); |
| 76 | bpc = radeon_crtc->bpc; | ||
| 77 | } | ||
| 86 | 78 | ||
| 87 | WREG32(HDMI_ACR_44_0 + offset, HDMI_ACR_CTS_44(acr.cts_44_1khz)); | 79 | if (bpc > 8) |
| 88 | WREG32(HDMI_ACR_44_1 + offset, acr.n_44_1khz); | 80 | WREG32(HDMI_ACR_PACKET_CONTROL + offset, |
| 81 | HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ | ||
| 82 | else | ||
| 83 | WREG32(HDMI_ACR_PACKET_CONTROL + offset, | ||
| 84 | HDMI_ACR_SOURCE | /* select SW CTS value */ | ||
| 85 | HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ | ||
| 86 | |||
| 87 | WREG32(HDMI_ACR_32_0 + offset, HDMI_ACR_CTS_32(acr->cts_32khz)); | ||
| 88 | WREG32(HDMI_ACR_32_1 + offset, acr->n_32khz); | ||
| 89 | 89 | ||
| 90 | WREG32(HDMI_ACR_48_0 + offset, HDMI_ACR_CTS_48(acr.cts_48khz)); | 90 | WREG32(HDMI_ACR_44_0 + offset, HDMI_ACR_CTS_44(acr->cts_44_1khz)); |
| 91 | WREG32(HDMI_ACR_48_1 + offset, acr.n_48khz); | 91 | WREG32(HDMI_ACR_44_1 + offset, acr->n_44_1khz); |
| 92 | |||
| 93 | WREG32(HDMI_ACR_48_0 + offset, HDMI_ACR_CTS_48(acr->cts_48khz)); | ||
| 94 | WREG32(HDMI_ACR_48_1 + offset, acr->n_48khz); | ||
| 92 | } | 95 | } |
| 93 | 96 | ||
| 94 | static void dce4_afmt_write_latency_fields(struct drm_encoder *encoder, | 97 | void dce4_afmt_write_latency_fields(struct drm_encoder *encoder, |
| 95 | struct drm_display_mode *mode) | 98 | struct drm_connector *connector, struct drm_display_mode *mode) |
| 96 | { | 99 | { |
| 97 | struct radeon_device *rdev = encoder->dev->dev_private; | 100 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 98 | struct drm_connector *connector; | ||
| 99 | struct radeon_connector *radeon_connector = NULL; | ||
| 100 | u32 tmp = 0; | 101 | u32 tmp = 0; |
| 101 | 102 | ||
| 102 | list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { | ||
| 103 | if (connector->encoder == encoder) { | ||
| 104 | radeon_connector = to_radeon_connector(connector); | ||
| 105 | break; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | if (!radeon_connector) { | ||
| 110 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
| 111 | return; | ||
| 112 | } | ||
| 113 | |||
| 114 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) { | 103 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) { |
| 115 | if (connector->latency_present[1]) | 104 | if (connector->latency_present[1]) |
| 116 | tmp = VIDEO_LIPSYNC(connector->video_latency[1]) | | 105 | tmp = VIDEO_LIPSYNC(connector->video_latency[1]) | |
| @@ -124,38 +113,17 @@ static void dce4_afmt_write_latency_fields(struct drm_encoder *encoder, | |||
| 124 | else | 113 | else |
| 125 | tmp = VIDEO_LIPSYNC(255) | AUDIO_LIPSYNC(255); | 114 | tmp = VIDEO_LIPSYNC(255) | AUDIO_LIPSYNC(255); |
| 126 | } | 115 | } |
| 127 | WREG32(AZ_F0_CODEC_PIN0_CONTROL_RESPONSE_LIPSYNC, tmp); | 116 | WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_RESPONSE_LIPSYNC, tmp); |
| 128 | } | 117 | } |
| 129 | 118 | ||
| 130 | static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder) | 119 | void dce4_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, |
| 120 | u8 *sadb, int sad_count) | ||
| 131 | { | 121 | { |
| 132 | struct radeon_device *rdev = encoder->dev->dev_private; | 122 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 133 | struct drm_connector *connector; | ||
| 134 | struct radeon_connector *radeon_connector = NULL; | ||
| 135 | u32 tmp; | 123 | u32 tmp; |
| 136 | u8 *sadb = NULL; | ||
| 137 | int sad_count; | ||
| 138 | |||
| 139 | list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { | ||
| 140 | if (connector->encoder == encoder) { | ||
| 141 | radeon_connector = to_radeon_connector(connector); | ||
| 142 | break; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | if (!radeon_connector) { | ||
| 147 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
| 148 | return; | ||
| 149 | } | ||
| 150 | |||
| 151 | sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb); | ||
| 152 | if (sad_count < 0) { | ||
| 153 | DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); | ||
| 154 | sad_count = 0; | ||
| 155 | } | ||
| 156 | 124 | ||
| 157 | /* program the speaker allocation */ | 125 | /* program the speaker allocation */ |
| 158 | tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); | 126 | tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); |
| 159 | tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); | 127 | tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); |
| 160 | /* set HDMI mode */ | 128 | /* set HDMI mode */ |
| 161 | tmp |= HDMI_CONNECTION; | 129 | tmp |= HDMI_CONNECTION; |
| @@ -163,19 +131,32 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder) | |||
| 163 | tmp |= SPEAKER_ALLOCATION(sadb[0]); | 131 | tmp |= SPEAKER_ALLOCATION(sadb[0]); |
| 164 | else | 132 | else |
| 165 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ | 133 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ |
| 166 | WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); | 134 | WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); |
| 167 | |||
| 168 | kfree(sadb); | ||
| 169 | } | 135 | } |
| 170 | 136 | ||
| 171 | static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder) | 137 | void dce4_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, |
| 138 | u8 *sadb, int sad_count) | ||
| 172 | { | 139 | { |
| 173 | struct radeon_device *rdev = encoder->dev->dev_private; | 140 | struct radeon_device *rdev = encoder->dev->dev_private; |
| 174 | struct drm_connector *connector; | 141 | u32 tmp; |
| 175 | struct radeon_connector *radeon_connector = NULL; | ||
| 176 | struct cea_sad *sads; | ||
| 177 | int i, sad_count; | ||
| 178 | 142 | ||
| 143 | /* program the speaker allocation */ | ||
| 144 | tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); | ||
| 145 | tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK); | ||
| 146 | /* set DP mode */ | ||
| 147 | tmp |= DP_CONNECTION; | ||
| 148 | if (sad_count) | ||
| 149 | tmp |= SPEAKER_ALLOCATION(sadb[0]); | ||
| 150 | else | ||
| 151 | tmp |= SPEAKER_ALLOCATION(5); /* stereo */ | ||
| 152 | WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); | ||
| 153 | } | ||
| 154 | |||
| 155 | void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder, | ||
| 156 | struct cea_sad *sads, int sad_count) | ||
| 157 | { | ||
| 158 | int i; | ||
| 159 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 179 | static const u16 eld_reg_to_type[][2] = { | 160 | static const u16 eld_reg_to_type[][2] = { |
| 180 | { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM }, | 161 | { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR0, HDMI_AUDIO_CODING_TYPE_PCM }, |
| 181 | { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR1, HDMI_AUDIO_CODING_TYPE_AC3 }, | 162 | { 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) | |||
| 191 | { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, | 172 | { AZ_F0_CODEC_PIN0_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, |
| 192 | }; | 173 | }; |
| 193 | 174 | ||
| 194 | list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { | ||
| 195 | if (connector->encoder == encoder) { | ||
| 196 | radeon_connector = to_radeon_connector(connector); | ||
| 197 | break; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | if (!radeon_connector) { | ||
| 202 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
| 203 | return; | ||
| 204 | } | ||
| 205 | |||
| 206 | sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads); | ||
| 207 | if (sad_count <= 0) { | ||
| 208 | DRM_ERROR("Couldn't read SADs: %d\n", sad_count); | ||
| 209 | return; | ||
| 210 | } | ||
| 211 | BUG_ON(!sads); | ||
| 212 | |||
| 213 | for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { | 175 | for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { |
| 214 | u32 value = 0; | 176 | u32 value = 0; |
| 215 | u8 stereo_freqs = 0; | 177 | u8 stereo_freqs = 0; |
| @@ -236,25 +198,17 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder) | |||
| 236 | 198 | ||
| 237 | value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs); | 199 | value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs); |
| 238 | 200 | ||
| 239 | WREG32(eld_reg_to_type[i][0], value); | 201 | WREG32_ENDPOINT(0, eld_reg_to_type[i][0], value); |
| 240 | } | 202 | } |
| 241 | |||
| 242 | kfree(sads); | ||
| 243 | } | 203 | } |
| 244 | 204 | ||
| 245 | /* | 205 | /* |
| 246 | * build a HDMI Video Info Frame | 206 | * build a AVI Info Frame |
| 247 | */ | 207 | */ |
| 248 | static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder, | 208 | void evergreen_set_avi_packet(struct radeon_device *rdev, u32 offset, |
| 249 | void *buffer, size_t size) | 209 | unsigned char *buffer, size_t size) |
| 250 | { | 210 | { |
| 251 | struct drm_device *dev = encoder->dev; | ||
| 252 | struct radeon_device *rdev = dev->dev_private; | ||
| 253 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 254 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 255 | uint32_t offset = dig->afmt->offset; | ||
| 256 | uint8_t *frame = buffer + 3; | 211 | uint8_t *frame = buffer + 3; |
| 257 | uint8_t *header = buffer; | ||
| 258 | 212 | ||
| 259 | WREG32(AFMT_AVI_INFO0 + offset, | 213 | WREG32(AFMT_AVI_INFO0 + offset, |
| 260 | frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); | 214 | 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, | |||
| 263 | WREG32(AFMT_AVI_INFO2 + offset, | 217 | WREG32(AFMT_AVI_INFO2 + offset, |
| 264 | frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24)); | 218 | frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24)); |
| 265 | WREG32(AFMT_AVI_INFO3 + offset, | 219 | WREG32(AFMT_AVI_INFO3 + offset, |
| 266 | frame[0xC] | (frame[0xD] << 8) | (header[1] << 24)); | 220 | frame[0xC] | (frame[0xD] << 8) | (buffer[1] << 24)); |
| 221 | |||
| 222 | WREG32_OR(HDMI_INFOFRAME_CONTROL0 + offset, | ||
| 223 | HDMI_AVI_INFO_SEND | /* enable AVI info frames */ | ||
| 224 | HDMI_AVI_INFO_CONT); /* required for audio info values to be updated */ | ||
| 225 | |||
| 226 | WREG32_P(HDMI_INFOFRAME_CONTROL1 + offset, | ||
| 227 | HDMI_AVI_INFO_LINE(2), /* anything other than 0 */ | ||
| 228 | ~HDMI_AVI_INFO_LINE_MASK); | ||
| 267 | } | 229 | } |
| 268 | 230 | ||
| 269 | static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock) | 231 | void dce4_hdmi_audio_set_dto(struct radeon_device *rdev, |
| 232 | struct radeon_crtc *crtc, unsigned int clock) | ||
| 270 | { | 233 | { |
| 271 | struct drm_device *dev = encoder->dev; | 234 | unsigned int max_ratio = clock / 24000; |
| 272 | struct radeon_device *rdev = dev->dev_private; | ||
| 273 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 274 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 275 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 276 | u32 base_rate = 24000; | ||
| 277 | u32 max_ratio = clock / base_rate; | ||
| 278 | u32 dto_phase; | 235 | u32 dto_phase; |
| 279 | u32 dto_modulo = clock; | ||
| 280 | u32 wallclock_ratio; | 236 | u32 wallclock_ratio; |
| 281 | u32 dto_cntl; | 237 | u32 value; |
| 282 | 238 | ||
| 283 | if (!dig || !dig->afmt) | 239 | if (max_ratio >= 8) { |
| 284 | return; | 240 | dto_phase = 192 * 1000; |
| 285 | 241 | wallclock_ratio = 3; | |
| 286 | if (ASIC_IS_DCE6(rdev)) { | 242 | } else if (max_ratio >= 4) { |
| 287 | dto_phase = 24 * 1000; | 243 | dto_phase = 96 * 1000; |
| 244 | wallclock_ratio = 2; | ||
| 245 | } else if (max_ratio >= 2) { | ||
| 246 | dto_phase = 48 * 1000; | ||
| 247 | wallclock_ratio = 1; | ||
| 288 | } else { | 248 | } else { |
| 289 | if (max_ratio >= 8) { | 249 | dto_phase = 24 * 1000; |
| 290 | dto_phase = 192 * 1000; | 250 | wallclock_ratio = 0; |
| 291 | wallclock_ratio = 3; | ||
| 292 | } else if (max_ratio >= 4) { | ||
| 293 | dto_phase = 96 * 1000; | ||
| 294 | wallclock_ratio = 2; | ||
| 295 | } else if (max_ratio >= 2) { | ||
| 296 | dto_phase = 48 * 1000; | ||
| 297 | wallclock_ratio = 1; | ||
| 298 | } else { | ||
| 299 | dto_phase = 24 * 1000; | ||
| 300 | wallclock_ratio = 0; | ||
| 301 | } | ||
| 302 | dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; | ||
| 303 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); | ||
| 304 | WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl); | ||
| 305 | } | 251 | } |
| 306 | 252 | ||
| 307 | /* XXX two dtos; generally use dto0 for hdmi */ | 253 | value = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; |
| 254 | value |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); | ||
| 255 | value &= ~DCCG_AUDIO_DTO1_USE_512FBR_DTO; | ||
| 256 | WREG32(DCCG_AUDIO_DTO0_CNTL, value); | ||
| 257 | |||
| 258 | /* Two dtos; generally use dto0 for HDMI */ | ||
| 259 | value = 0; | ||
| 260 | |||
| 261 | if (crtc) | ||
| 262 | value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id); | ||
| 263 | |||
| 264 | WREG32(DCCG_AUDIO_DTO_SOURCE, value); | ||
| 265 | |||
| 308 | /* Express [24MHz / target pixel clock] as an exact rational | 266 | /* Express [24MHz / target pixel clock] as an exact rational |
| 309 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE | 267 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE |
| 310 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator | 268 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator |
| 311 | */ | 269 | */ |
| 312 | WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id)); | ||
| 313 | WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase); | 270 | WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase); |
| 314 | WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo); | 271 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock); |
| 315 | } | 272 | } |
| 316 | 273 | ||
| 317 | 274 | void dce4_dp_audio_set_dto(struct radeon_device *rdev, | |
| 318 | /* | 275 | struct radeon_crtc *crtc, unsigned int clock) |
| 319 | * update the info frames with the data from the current display mode | ||
| 320 | */ | ||
| 321 | void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) | ||
| 322 | { | 276 | { |
| 323 | struct drm_device *dev = encoder->dev; | 277 | u32 value; |
| 324 | struct radeon_device *rdev = dev->dev_private; | ||
| 325 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 326 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 327 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | ||
| 328 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; | ||
| 329 | struct hdmi_avi_infoframe frame; | ||
| 330 | uint32_t offset; | ||
| 331 | ssize_t err; | ||
| 332 | uint32_t val; | ||
| 333 | int bpc = 8; | ||
| 334 | 278 | ||
| 335 | if (!dig || !dig->afmt) | 279 | value = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; |
| 336 | return; | 280 | value |= DCCG_AUDIO_DTO1_USE_512FBR_DTO; |
| 281 | WREG32(DCCG_AUDIO_DTO1_CNTL, value); | ||
| 337 | 282 | ||
| 338 | /* Silent, r600_hdmi_enable will raise WARN for us */ | 283 | /* Two dtos; generally use dto1 for DP */ |
| 339 | if (!dig->afmt->enabled) | 284 | value = 0; |
| 340 | return; | 285 | value |= DCCG_AUDIO_DTO_SEL; |
| 341 | offset = dig->afmt->offset; | ||
| 342 | 286 | ||
| 343 | /* hdmi deep color mode general control packets setup, if bpc > 8 */ | 287 | if (crtc) |
| 344 | if (encoder->crtc) { | 288 | value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id); |
| 345 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 346 | bpc = radeon_crtc->bpc; | ||
| 347 | } | ||
| 348 | 289 | ||
| 349 | /* disable audio prior to setting up hw */ | 290 | WREG32(DCCG_AUDIO_DTO_SOURCE, value); |
| 350 | if (ASIC_IS_DCE6(rdev)) { | 291 | |
| 351 | dig->afmt->pin = dce6_audio_get_pin(rdev); | 292 | /* Express [24MHz / target pixel clock] as an exact rational |
| 352 | dce6_audio_enable(rdev, dig->afmt->pin, 0); | 293 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE |
| 353 | } else { | 294 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator |
| 354 | dig->afmt->pin = r600_audio_get_pin(rdev); | 295 | */ |
| 355 | dce4_audio_enable(rdev, dig->afmt->pin, 0); | 296 | WREG32(DCCG_AUDIO_DTO1_PHASE, 24000); |
| 356 | } | 297 | WREG32(DCCG_AUDIO_DTO1_MODULE, rdev->clock.max_pixel_clock * 10); |
| 298 | } | ||
| 357 | 299 | ||
| 358 | evergreen_audio_set_dto(encoder, mode->clock); | 300 | void dce4_set_vbi_packet(struct drm_encoder *encoder, u32 offset) |
| 301 | { | ||
| 302 | struct drm_device *dev = encoder->dev; | ||
| 303 | struct radeon_device *rdev = dev->dev_private; | ||
| 359 | 304 | ||
| 360 | WREG32(HDMI_VBI_PACKET_CONTROL + offset, | 305 | WREG32(HDMI_VBI_PACKET_CONTROL + offset, |
| 361 | HDMI_NULL_SEND); /* send null packets when required */ | 306 | HDMI_NULL_SEND | /* send null packets when required */ |
| 307 | HDMI_GC_SEND | /* send general control packets */ | ||
| 308 | HDMI_GC_CONT); /* send general control packets every frame */ | ||
| 309 | } | ||
| 362 | 310 | ||
| 363 | WREG32(AFMT_AUDIO_CRC_CONTROL + offset, 0x1000); | 311 | void dce4_hdmi_set_color_depth(struct drm_encoder *encoder, u32 offset, int bpc) |
| 312 | { | ||
| 313 | struct drm_device *dev = encoder->dev; | ||
| 314 | struct radeon_device *rdev = dev->dev_private; | ||
| 315 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | ||
| 316 | uint32_t val; | ||
| 364 | 317 | ||
| 365 | val = RREG32(HDMI_CONTROL + offset); | 318 | val = RREG32(HDMI_CONTROL + offset); |
| 366 | val &= ~HDMI_DEEP_COLOR_ENABLE; | 319 | val &= ~HDMI_DEEP_COLOR_ENABLE; |
| @@ -390,113 +343,59 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode | |||
| 390 | } | 343 | } |
| 391 | 344 | ||
| 392 | WREG32(HDMI_CONTROL + offset, val); | 345 | WREG32(HDMI_CONTROL + offset, val); |
| 346 | } | ||
| 393 | 347 | ||
| 394 | WREG32(HDMI_VBI_PACKET_CONTROL + offset, | 348 | void dce4_set_audio_packet(struct drm_encoder *encoder, u32 offset) |
| 395 | HDMI_NULL_SEND | /* send null packets when required */ | 349 | { |
| 396 | HDMI_GC_SEND | /* send general control packets */ | 350 | struct drm_device *dev = encoder->dev; |
| 397 | HDMI_GC_CONT); /* send general control packets every frame */ | 351 | struct radeon_device *rdev = dev->dev_private; |
| 398 | 352 | ||
| 399 | WREG32(HDMI_INFOFRAME_CONTROL0 + offset, | 353 | WREG32(HDMI_INFOFRAME_CONTROL0 + offset, |
| 400 | HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ | 354 | HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ |
| 401 | HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */ | 355 | HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */ |
| 402 | 356 | ||
| 403 | WREG32(AFMT_INFOFRAME_CONTROL0 + offset, | 357 | WREG32(AFMT_INFOFRAME_CONTROL0 + offset, |
| 404 | AFMT_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */ | 358 | AFMT_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */ |
| 405 | 359 | ||
| 406 | WREG32(HDMI_INFOFRAME_CONTROL1 + offset, | 360 | WREG32(HDMI_INFOFRAME_CONTROL1 + offset, |
| 407 | HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */ | 361 | HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */ |
| 408 | |||
| 409 | WREG32(HDMI_GC + offset, 0); /* unset HDMI_GC_AVMUTE */ | ||
| 410 | 362 | ||
| 411 | WREG32(HDMI_AUDIO_PACKET_CONTROL + offset, | 363 | WREG32(HDMI_AUDIO_PACKET_CONTROL + offset, |
| 412 | HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */ | 364 | HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */ |
| 413 | HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ | 365 | HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */ |
| 414 | |||
| 415 | WREG32(AFMT_AUDIO_PACKET_CONTROL + offset, | ||
| 416 | AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ | ||
| 417 | |||
| 418 | /* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */ | ||
| 419 | |||
| 420 | if (bpc > 8) | ||
| 421 | WREG32(HDMI_ACR_PACKET_CONTROL + offset, | ||
| 422 | HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ | ||
| 423 | else | ||
| 424 | WREG32(HDMI_ACR_PACKET_CONTROL + offset, | ||
| 425 | HDMI_ACR_SOURCE | /* select SW CTS value */ | ||
| 426 | HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ | ||
| 427 | |||
| 428 | evergreen_hdmi_update_ACR(encoder, mode->clock); | ||
| 429 | 366 | ||
| 430 | WREG32(AFMT_60958_0 + offset, | 367 | WREG32(AFMT_60958_0 + offset, |
| 431 | AFMT_60958_CS_CHANNEL_NUMBER_L(1)); | 368 | AFMT_60958_CS_CHANNEL_NUMBER_L(1)); |
| 432 | 369 | ||
| 433 | WREG32(AFMT_60958_1 + offset, | 370 | WREG32(AFMT_60958_1 + offset, |
| 434 | AFMT_60958_CS_CHANNEL_NUMBER_R(2)); | 371 | AFMT_60958_CS_CHANNEL_NUMBER_R(2)); |
| 435 | 372 | ||
| 436 | WREG32(AFMT_60958_2 + offset, | 373 | WREG32(AFMT_60958_2 + offset, |
| 437 | AFMT_60958_CS_CHANNEL_NUMBER_2(3) | | 374 | AFMT_60958_CS_CHANNEL_NUMBER_2(3) | |
| 438 | AFMT_60958_CS_CHANNEL_NUMBER_3(4) | | 375 | AFMT_60958_CS_CHANNEL_NUMBER_3(4) | |
| 439 | AFMT_60958_CS_CHANNEL_NUMBER_4(5) | | 376 | AFMT_60958_CS_CHANNEL_NUMBER_4(5) | |
| 440 | AFMT_60958_CS_CHANNEL_NUMBER_5(6) | | 377 | AFMT_60958_CS_CHANNEL_NUMBER_5(6) | |
| 441 | AFMT_60958_CS_CHANNEL_NUMBER_6(7) | | 378 | AFMT_60958_CS_CHANNEL_NUMBER_6(7) | |
| 442 | AFMT_60958_CS_CHANNEL_NUMBER_7(8)); | 379 | AFMT_60958_CS_CHANNEL_NUMBER_7(8)); |
| 443 | |||
| 444 | if (ASIC_IS_DCE6(rdev)) { | ||
| 445 | dce6_afmt_write_speaker_allocation(encoder); | ||
| 446 | } else { | ||
| 447 | dce4_afmt_write_speaker_allocation(encoder); | ||
| 448 | } | ||
| 449 | 380 | ||
| 450 | WREG32(AFMT_AUDIO_PACKET_CONTROL2 + offset, | 381 | WREG32(AFMT_AUDIO_PACKET_CONTROL2 + offset, |
| 451 | AFMT_AUDIO_CHANNEL_ENABLE(0xff)); | 382 | AFMT_AUDIO_CHANNEL_ENABLE(0xff)); |
| 452 | |||
| 453 | /* fglrx sets 0x40 in 0x5f80 here */ | ||
| 454 | |||
| 455 | if (ASIC_IS_DCE6(rdev)) { | ||
| 456 | dce6_afmt_select_pin(encoder); | ||
| 457 | dce6_afmt_write_sad_regs(encoder); | ||
| 458 | dce6_afmt_write_latency_fields(encoder, mode); | ||
| 459 | } else { | ||
| 460 | evergreen_hdmi_write_sad_regs(encoder); | ||
| 461 | dce4_afmt_write_latency_fields(encoder, mode); | ||
| 462 | } | ||
| 463 | |||
| 464 | err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); | ||
| 465 | if (err < 0) { | ||
| 466 | DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); | ||
| 467 | return; | ||
| 468 | } | ||
| 469 | |||
| 470 | err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); | ||
| 471 | if (err < 0) { | ||
| 472 | DRM_ERROR("failed to pack AVI infoframe: %zd\n", err); | ||
| 473 | return; | ||
| 474 | } | ||
| 475 | |||
| 476 | evergreen_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer)); | ||
| 477 | |||
| 478 | WREG32_OR(HDMI_INFOFRAME_CONTROL0 + offset, | ||
| 479 | HDMI_AVI_INFO_SEND | /* enable AVI info frames */ | ||
| 480 | HDMI_AVI_INFO_CONT); /* required for audio info values to be updated */ | ||
| 481 | 383 | ||
| 482 | WREG32_P(HDMI_INFOFRAME_CONTROL1 + offset, | 384 | /* allow 60958 channel status and send audio packets fields to be updated */ |
| 483 | HDMI_AVI_INFO_LINE(2), /* anything other than 0 */ | 385 | WREG32(AFMT_AUDIO_PACKET_CONTROL + offset, |
| 484 | ~HDMI_AVI_INFO_LINE_MASK); | 386 | AFMT_AUDIO_SAMPLE_SEND | AFMT_RESET_FIFO_WHEN_AUDIO_DIS | AFMT_60958_CS_UPDATE); |
| 387 | } | ||
| 485 | 388 | ||
| 486 | WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + offset, | ||
| 487 | AFMT_AUDIO_SAMPLE_SEND); /* send audio packets */ | ||
| 488 | 389 | ||
| 489 | /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ | 390 | void dce4_set_mute(struct drm_encoder *encoder, u32 offset, bool mute) |
| 490 | WREG32(AFMT_RAMP_CONTROL0 + offset, 0x00FFFFFF); | 391 | { |
| 491 | WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF); | 392 | struct drm_device *dev = encoder->dev; |
| 492 | WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001); | 393 | struct radeon_device *rdev = dev->dev_private; |
| 493 | WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001); | ||
| 494 | 394 | ||
| 495 | /* enable audio after to setting up hw */ | 395 | if (mute) |
| 496 | if (ASIC_IS_DCE6(rdev)) | 396 | WREG32_OR(HDMI_GC + offset, HDMI_GC_AVMUTE); |
| 497 | dce6_audio_enable(rdev, dig->afmt->pin, 1); | ||
| 498 | else | 397 | else |
| 499 | dce4_audio_enable(rdev, dig->afmt->pin, 0xf); | 398 | WREG32_AND(HDMI_GC + offset, ~HDMI_GC_AVMUTE); |
| 500 | } | 399 | } |
| 501 | 400 | ||
| 502 | void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) | 401 | void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) |
| @@ -516,10 +415,7 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) | |||
| 516 | return; | 415 | return; |
| 517 | 416 | ||
| 518 | if (!enable && dig->afmt->pin) { | 417 | if (!enable && dig->afmt->pin) { |
| 519 | if (ASIC_IS_DCE6(rdev)) | 418 | radeon_audio_enable(rdev, dig->afmt->pin, 0); |
| 520 | dce6_audio_enable(rdev, dig->afmt->pin, 0); | ||
| 521 | else | ||
| 522 | dce4_audio_enable(rdev, dig->afmt->pin, 0); | ||
| 523 | dig->afmt->pin = NULL; | 419 | dig->afmt->pin = NULL; |
| 524 | } | 420 | } |
| 525 | 421 | ||
| @@ -528,3 +424,57 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) | |||
| 528 | DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n", | 424 | DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n", |
| 529 | enable ? "En" : "Dis", dig->afmt->offset, radeon_encoder->encoder_id); | 425 | enable ? "En" : "Dis", dig->afmt->offset, radeon_encoder->encoder_id); |
| 530 | } | 426 | } |
| 427 | |||
| 428 | void evergreen_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable) | ||
| 429 | { | ||
| 430 | struct drm_device *dev = encoder->dev; | ||
| 431 | struct radeon_device *rdev = dev->dev_private; | ||
| 432 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 433 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 434 | uint32_t offset; | ||
| 435 | |||
| 436 | if (!dig || !dig->afmt) | ||
| 437 | return; | ||
| 438 | |||
| 439 | offset = dig->afmt->offset; | ||
| 440 | |||
| 441 | if (enable) { | ||
| 442 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | ||
| 443 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 444 | struct radeon_connector_atom_dig *dig_connector; | ||
| 445 | uint32_t val; | ||
| 446 | |||
| 447 | if (dig->afmt->enabled) | ||
| 448 | return; | ||
| 449 | |||
| 450 | WREG32(EVERGREEN_DP_SEC_TIMESTAMP + offset, EVERGREEN_DP_SEC_TIMESTAMP_MODE(1)); | ||
| 451 | |||
| 452 | if (radeon_connector->con_priv) { | ||
| 453 | dig_connector = radeon_connector->con_priv; | ||
| 454 | val = RREG32(EVERGREEN_DP_SEC_AUD_N + offset); | ||
| 455 | val &= ~EVERGREEN_DP_SEC_N_BASE_MULTIPLE(0xf); | ||
| 456 | |||
| 457 | if (dig_connector->dp_clock == 162000) | ||
| 458 | val |= EVERGREEN_DP_SEC_N_BASE_MULTIPLE(3); | ||
| 459 | else | ||
| 460 | val |= EVERGREEN_DP_SEC_N_BASE_MULTIPLE(5); | ||
| 461 | |||
| 462 | WREG32(EVERGREEN_DP_SEC_AUD_N + offset, val); | ||
| 463 | } | ||
| 464 | |||
| 465 | WREG32(EVERGREEN_DP_SEC_CNTL + offset, | ||
| 466 | EVERGREEN_DP_SEC_ASP_ENABLE | /* Audio packet transmission */ | ||
| 467 | EVERGREEN_DP_SEC_ATP_ENABLE | /* Audio timestamp packet transmission */ | ||
| 468 | EVERGREEN_DP_SEC_AIP_ENABLE | /* Audio infoframe packet transmission */ | ||
| 469 | EVERGREEN_DP_SEC_STREAM_ENABLE); /* Master enable for secondary stream engine */ | ||
| 470 | radeon_audio_enable(rdev, dig->afmt->pin, 0xf); | ||
| 471 | } else { | ||
| 472 | if (!dig->afmt->enabled) | ||
| 473 | return; | ||
| 474 | |||
| 475 | WREG32(EVERGREEN_DP_SEC_CNTL + offset, 0); | ||
| 476 | radeon_audio_enable(rdev, dig->afmt->pin, 0); | ||
| 477 | } | ||
| 478 | |||
| 479 | dig->afmt->enabled = enable; | ||
| 480 | } | ||
diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h index 23bff590fb6e..aa939dfed3a3 100644 --- a/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/drivers/gpu/drm/radeon/evergreen_reg.h | |||
| @@ -251,4 +251,19 @@ | |||
| 251 | /* HDMI blocks at 0x7030, 0x7c30, 0x10830, 0x11430, 0x12030, 0x12c30 */ | 251 | /* HDMI blocks at 0x7030, 0x7c30, 0x10830, 0x11430, 0x12030, 0x12c30 */ |
| 252 | #define EVERGREEN_HDMI_BASE 0x7030 | 252 | #define EVERGREEN_HDMI_BASE 0x7030 |
| 253 | 253 | ||
| 254 | /* Display Port block */ | ||
| 255 | #define EVERGREEN_DP_SEC_CNTL 0x7280 | ||
| 256 | # define EVERGREEN_DP_SEC_STREAM_ENABLE (1 << 0) | ||
| 257 | # define EVERGREEN_DP_SEC_ASP_ENABLE (1 << 4) | ||
| 258 | # define EVERGREEN_DP_SEC_ATP_ENABLE (1 << 8) | ||
| 259 | # define EVERGREEN_DP_SEC_AIP_ENABLE (1 << 12) | ||
| 260 | # define EVERGREEN_DP_SEC_GSP_ENABLE (1 << 20) | ||
| 261 | # define EVERGREEN_DP_SEC_AVI_ENABLE (1 << 24) | ||
| 262 | # define EVERGREEN_DP_SEC_MPG_ENABLE (1 << 28) | ||
| 263 | #define EVERGREEN_DP_SEC_TIMESTAMP 0x72a4 | ||
| 264 | # define EVERGREEN_DP_SEC_TIMESTAMP_MODE(x) (((x) & 0x3) << 0) | ||
| 265 | #define EVERGREEN_DP_SEC_AUD_N 0x7294 | ||
| 266 | # define EVERGREEN_DP_SEC_N_BASE_MULTIPLE(x) (((x) & 0xf) << 24) | ||
| 267 | # define EVERGREEN_DP_SEC_SS_EN (1 << 28) | ||
| 268 | |||
| 254 | #endif | 269 | #endif |
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index b066d6711b8d..ee83d2a88750 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h | |||
| @@ -509,6 +509,7 @@ | |||
| 509 | #define DCCG_AUDIO_DTO1_MODULE 0x05c4 | 509 | #define DCCG_AUDIO_DTO1_MODULE 0x05c4 |
| 510 | #define DCCG_AUDIO_DTO1_LOAD 0x05c8 | 510 | #define DCCG_AUDIO_DTO1_LOAD 0x05c8 |
| 511 | #define DCCG_AUDIO_DTO1_CNTL 0x05cc | 511 | #define DCCG_AUDIO_DTO1_CNTL 0x05cc |
| 512 | # define DCCG_AUDIO_DTO1_USE_512FBR_DTO (1 << 3) | ||
| 512 | 513 | ||
| 513 | /* DCE 4.0 AFMT */ | 514 | /* DCE 4.0 AFMT */ |
| 514 | #define HDMI_CONTROL 0x7030 | 515 | #define HDMI_CONTROL 0x7030 |
diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index e3e9c10cfba9..c5eb286517a8 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c | |||
| @@ -1925,6 +1925,7 @@ void kv_dpm_setup_asic(struct radeon_device *rdev) | |||
| 1925 | kv_init_sclk_t(rdev); | 1925 | kv_init_sclk_t(rdev); |
| 1926 | } | 1926 | } |
| 1927 | 1927 | ||
| 1928 | #if 0 | ||
| 1928 | void kv_dpm_reset_asic(struct radeon_device *rdev) | 1929 | void kv_dpm_reset_asic(struct radeon_device *rdev) |
| 1929 | { | 1930 | { |
| 1930 | struct kv_power_info *pi = kv_get_pi(rdev); | 1931 | struct kv_power_info *pi = kv_get_pi(rdev); |
| @@ -1945,6 +1946,7 @@ void kv_dpm_reset_asic(struct radeon_device *rdev) | |||
| 1945 | kv_set_enabled_level(rdev, pi->graphics_boot_level); | 1946 | kv_set_enabled_level(rdev, pi->graphics_boot_level); |
| 1946 | } | 1947 | } |
| 1947 | } | 1948 | } |
| 1949 | #endif | ||
| 1948 | 1950 | ||
| 1949 | //XXX use sumo_dpm_display_configuration_changed | 1951 | //XXX use sumo_dpm_display_configuration_changed |
| 1950 | 1952 | ||
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index aea48c89b241..24242a7f0ac3 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <drm/drmP.h> | 27 | #include <drm/drmP.h> |
| 28 | #include "radeon.h" | 28 | #include "radeon.h" |
| 29 | #include "radeon_asic.h" | 29 | #include "radeon_asic.h" |
| 30 | #include "radeon_audio.h" | ||
| 30 | #include <drm/radeon_drm.h> | 31 | #include <drm/radeon_drm.h> |
| 31 | #include "nid.h" | 32 | #include "nid.h" |
| 32 | #include "atom.h" | 33 | #include "atom.h" |
| @@ -2097,15 +2098,9 @@ static int cayman_startup(struct radeon_device *rdev) | |||
| 2097 | return r; | 2098 | return r; |
| 2098 | } | 2099 | } |
| 2099 | 2100 | ||
| 2100 | if (ASIC_IS_DCE6(rdev)) { | 2101 | r = radeon_audio_init(rdev); |
| 2101 | r = dce6_audio_init(rdev); | 2102 | if (r) |
| 2102 | if (r) | 2103 | return r; |
| 2103 | return r; | ||
| 2104 | } else { | ||
| 2105 | r = r600_audio_init(rdev); | ||
| 2106 | if (r) | ||
| 2107 | return r; | ||
| 2108 | } | ||
| 2109 | 2104 | ||
| 2110 | return 0; | 2105 | return 0; |
| 2111 | } | 2106 | } |
| @@ -2140,10 +2135,7 @@ int cayman_resume(struct radeon_device *rdev) | |||
| 2140 | int cayman_suspend(struct radeon_device *rdev) | 2135 | int cayman_suspend(struct radeon_device *rdev) |
| 2141 | { | 2136 | { |
| 2142 | radeon_pm_suspend(rdev); | 2137 | radeon_pm_suspend(rdev); |
| 2143 | if (ASIC_IS_DCE6(rdev)) | 2138 | radeon_audio_fini(rdev); |
| 2144 | dce6_audio_fini(rdev); | ||
| 2145 | else | ||
| 2146 | r600_audio_fini(rdev); | ||
| 2147 | radeon_vm_manager_fini(rdev); | 2139 | radeon_vm_manager_fini(rdev); |
| 2148 | cayman_cp_enable(rdev, false); | 2140 | cayman_cp_enable(rdev, false); |
| 2149 | cayman_dma_stop(rdev); | 2141 | cayman_dma_stop(rdev); |
diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index 6d2f16cf2c1c..7bc9f8d9804a 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c | |||
| @@ -3862,11 +3862,13 @@ void ni_dpm_post_set_power_state(struct radeon_device *rdev) | |||
| 3862 | ni_update_current_ps(rdev, new_ps); | 3862 | ni_update_current_ps(rdev, new_ps); |
| 3863 | } | 3863 | } |
| 3864 | 3864 | ||
| 3865 | #if 0 | ||
| 3865 | void ni_dpm_reset_asic(struct radeon_device *rdev) | 3866 | void ni_dpm_reset_asic(struct radeon_device *rdev) |
| 3866 | { | 3867 | { |
| 3867 | ni_restrict_performance_levels_before_switch(rdev); | 3868 | ni_restrict_performance_levels_before_switch(rdev); |
| 3868 | rv770_set_boot_state(rdev); | 3869 | rv770_set_boot_state(rdev); |
| 3869 | } | 3870 | } |
| 3871 | #endif | ||
| 3870 | 3872 | ||
| 3871 | union power_info { | 3873 | union power_info { |
| 3872 | struct _ATOM_POWERPLAY_INFO info; | 3874 | struct _ATOM_POWERPLAY_INFO info; |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index ef5d6066fa5b..07a71a2488c9 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <drm/radeon_drm.h> | 33 | #include <drm/radeon_drm.h> |
| 34 | #include "radeon.h" | 34 | #include "radeon.h" |
| 35 | #include "radeon_asic.h" | 35 | #include "radeon_asic.h" |
| 36 | #include "radeon_audio.h" | ||
| 36 | #include "radeon_mode.h" | 37 | #include "radeon_mode.h" |
| 37 | #include "r600d.h" | 38 | #include "r600d.h" |
| 38 | #include "atom.h" | 39 | #include "atom.h" |
| @@ -3054,7 +3055,7 @@ static int r600_startup(struct radeon_device *rdev) | |||
| 3054 | return r; | 3055 | return r; |
| 3055 | } | 3056 | } |
| 3056 | 3057 | ||
| 3057 | r = r600_audio_init(rdev); | 3058 | r = radeon_audio_init(rdev); |
| 3058 | if (r) { | 3059 | if (r) { |
| 3059 | DRM_ERROR("radeon: audio init failed\n"); | 3060 | DRM_ERROR("radeon: audio init failed\n"); |
| 3060 | return r; | 3061 | return r; |
| @@ -3105,7 +3106,7 @@ int r600_resume(struct radeon_device *rdev) | |||
| 3105 | int r600_suspend(struct radeon_device *rdev) | 3106 | int r600_suspend(struct radeon_device *rdev) |
| 3106 | { | 3107 | { |
| 3107 | radeon_pm_suspend(rdev); | 3108 | radeon_pm_suspend(rdev); |
| 3108 | r600_audio_fini(rdev); | 3109 | radeon_audio_fini(rdev); |
| 3109 | r600_cp_stop(rdev); | 3110 | r600_cp_stop(rdev); |
| 3110 | if (rdev->has_uvd) { | 3111 | if (rdev->has_uvd) { |
| 3111 | uvd_v1_0_fini(rdev); | 3112 | uvd_v1_0_fini(rdev); |
| @@ -3224,7 +3225,7 @@ int r600_init(struct radeon_device *rdev) | |||
| 3224 | void r600_fini(struct radeon_device *rdev) | 3225 | void r600_fini(struct radeon_device *rdev) |
| 3225 | { | 3226 | { |
| 3226 | radeon_pm_fini(rdev); | 3227 | radeon_pm_fini(rdev); |
| 3227 | r600_audio_fini(rdev); | 3228 | radeon_audio_fini(rdev); |
| 3228 | r600_cp_fini(rdev); | 3229 | r600_cp_fini(rdev); |
| 3229 | r600_irq_fini(rdev); | 3230 | r600_irq_fini(rdev); |
| 3230 | if (rdev->has_uvd) { | 3231 | if (rdev->has_uvd) { |
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index b90dc0eb08e6..62c91ed669ce 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <drm/radeon_drm.h> | 29 | #include <drm/radeon_drm.h> |
| 30 | #include "radeon.h" | 30 | #include "radeon.h" |
| 31 | #include "radeon_asic.h" | 31 | #include "radeon_asic.h" |
| 32 | #include "radeon_audio.h" | ||
| 32 | #include "r600d.h" | 33 | #include "r600d.h" |
| 33 | #include "atom.h" | 34 | #include "atom.h" |
| 34 | 35 | ||
| @@ -55,30 +56,6 @@ enum r600_hdmi_iec_status_bits { | |||
| 55 | AUDIO_STATUS_LEVEL = 0x80 | 56 | AUDIO_STATUS_LEVEL = 0x80 |
| 56 | }; | 57 | }; |
| 57 | 58 | ||
| 58 | static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { | ||
| 59 | /* 32kHz 44.1kHz 48kHz */ | ||
| 60 | /* Clock N CTS N CTS N CTS */ | ||
| 61 | { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */ | ||
| 62 | { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ | ||
| 63 | { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ | ||
| 64 | { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ | ||
| 65 | { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ | ||
| 66 | { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ | ||
| 67 | { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */ | ||
| 68 | { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ | ||
| 69 | { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */ | ||
| 70 | { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ | ||
| 71 | }; | ||
| 72 | |||
| 73 | |||
| 74 | /* | ||
| 75 | * check if the chipset is supported | ||
| 76 | */ | ||
| 77 | static int r600_audio_chipset_supported(struct radeon_device *rdev) | ||
| 78 | { | ||
| 79 | return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev); | ||
| 80 | } | ||
| 81 | |||
| 82 | static struct r600_audio_pin r600_audio_status(struct radeon_device *rdev) | 59 | static struct r600_audio_pin r600_audio_status(struct radeon_device *rdev) |
| 83 | { | 60 | { |
| 84 | struct r600_audio_pin status; | 61 | struct r600_audio_pin status; |
| @@ -191,155 +168,56 @@ void r600_audio_enable(struct radeon_device *rdev, | |||
| 191 | WREG32(AZ_HOT_PLUG_CONTROL, tmp); | 168 | WREG32(AZ_HOT_PLUG_CONTROL, tmp); |
| 192 | } | 169 | } |
| 193 | 170 | ||
| 194 | /* | ||
| 195 | * initialize the audio vars | ||
| 196 | */ | ||
| 197 | int r600_audio_init(struct radeon_device *rdev) | ||
| 198 | { | ||
| 199 | if (!radeon_audio || !r600_audio_chipset_supported(rdev)) | ||
| 200 | return 0; | ||
| 201 | |||
| 202 | rdev->audio.enabled = true; | ||
| 203 | |||
| 204 | rdev->audio.num_pins = 1; | ||
| 205 | rdev->audio.pin[0].channels = -1; | ||
| 206 | rdev->audio.pin[0].rate = -1; | ||
| 207 | rdev->audio.pin[0].bits_per_sample = -1; | ||
| 208 | rdev->audio.pin[0].status_bits = 0; | ||
| 209 | rdev->audio.pin[0].category_code = 0; | ||
| 210 | rdev->audio.pin[0].id = 0; | ||
| 211 | /* disable audio. it will be set up later */ | ||
| 212 | r600_audio_enable(rdev, &rdev->audio.pin[0], 0); | ||
| 213 | |||
| 214 | return 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | /* | ||
| 218 | * release the audio timer | ||
| 219 | * TODO: How to do this correctly on SMP systems? | ||
| 220 | */ | ||
| 221 | void r600_audio_fini(struct radeon_device *rdev) | ||
| 222 | { | ||
| 223 | if (!rdev->audio.enabled) | ||
| 224 | return; | ||
| 225 | |||
| 226 | r600_audio_enable(rdev, &rdev->audio.pin[0], 0); | ||
| 227 | |||
| 228 | rdev->audio.enabled = false; | ||
| 229 | } | ||
| 230 | |||
| 231 | struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev) | 171 | struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev) |
| 232 | { | 172 | { |
| 233 | /* only one pin on 6xx-NI */ | 173 | /* only one pin on 6xx-NI */ |
| 234 | return &rdev->audio.pin[0]; | 174 | return &rdev->audio.pin[0]; |
| 235 | } | 175 | } |
| 236 | 176 | ||
| 237 | /* | 177 | void r600_hdmi_update_acr(struct drm_encoder *encoder, long offset, |
| 238 | * calculate CTS and N values if they are not found in the table | 178 | const struct radeon_hdmi_acr *acr) |
| 239 | */ | ||
| 240 | static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq) | ||
| 241 | { | ||
| 242 | int n, cts; | ||
| 243 | unsigned long div, mul; | ||
| 244 | |||
| 245 | /* Safe, but overly large values */ | ||
| 246 | n = 128 * freq; | ||
| 247 | cts = clock * 1000; | ||
| 248 | |||
| 249 | /* Smallest valid fraction */ | ||
| 250 | div = gcd(n, cts); | ||
| 251 | |||
| 252 | n /= div; | ||
| 253 | cts /= div; | ||
| 254 | |||
| 255 | /* | ||
| 256 | * The optimal N is 128*freq/1000. Calculate the closest larger | ||
| 257 | * value that doesn't truncate any bits. | ||
| 258 | */ | ||
| 259 | mul = ((128*freq/1000) + (n-1))/n; | ||
| 260 | |||
| 261 | n *= mul; | ||
| 262 | cts *= mul; | ||
| 263 | |||
| 264 | /* Check that we are in spec (not always possible) */ | ||
| 265 | if (n < (128*freq/1500)) | ||
| 266 | printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n"); | ||
| 267 | if (n > (128*freq/300)) | ||
| 268 | printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n"); | ||
| 269 | |||
| 270 | *N = n; | ||
| 271 | *CTS = cts; | ||
| 272 | |||
| 273 | DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n", | ||
| 274 | *N, *CTS, freq); | ||
| 275 | } | ||
| 276 | |||
| 277 | struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) | ||
| 278 | { | ||
| 279 | struct radeon_hdmi_acr res; | ||
| 280 | u8 i; | ||
| 281 | |||
| 282 | /* Precalculated values for common clocks */ | ||
| 283 | for (i = 0; i < ARRAY_SIZE(r600_hdmi_predefined_acr); i++) { | ||
| 284 | if (r600_hdmi_predefined_acr[i].clock == clock) | ||
| 285 | return r600_hdmi_predefined_acr[i]; | ||
| 286 | } | ||
| 287 | |||
| 288 | /* And odd clocks get manually calculated */ | ||
| 289 | r600_hdmi_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000); | ||
| 290 | r600_hdmi_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100); | ||
| 291 | r600_hdmi_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000); | ||
| 292 | |||
| 293 | return res; | ||
| 294 | } | ||
| 295 | |||
| 296 | /* | ||
| 297 | * update the N and CTS parameters for a given pixel clock rate | ||
| 298 | */ | ||
| 299 | void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) | ||
| 300 | { | 179 | { |
| 301 | struct drm_device *dev = encoder->dev; | 180 | struct drm_device *dev = encoder->dev; |
| 302 | struct radeon_device *rdev = dev->dev_private; | 181 | struct radeon_device *rdev = dev->dev_private; |
| 303 | struct radeon_hdmi_acr acr = r600_hdmi_acr(clock); | 182 | |
| 304 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 183 | /* DCE 3.0 uses register that's normally for CRC_CONTROL */ |
| 305 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 184 | uint32_t acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL : |
| 306 | uint32_t offset = dig->afmt->offset; | 185 | HDMI0_ACR_PACKET_CONTROL; |
| 186 | WREG32_P(acr_ctl + offset, | ||
| 187 | HDMI0_ACR_SOURCE | /* select SW CTS value */ | ||
| 188 | HDMI0_ACR_AUTO_SEND, /* allow hw to sent ACR packets when required */ | ||
| 189 | ~(HDMI0_ACR_SOURCE | | ||
| 190 | HDMI0_ACR_AUTO_SEND)); | ||
| 307 | 191 | ||
| 308 | WREG32_P(HDMI0_ACR_32_0 + offset, | 192 | WREG32_P(HDMI0_ACR_32_0 + offset, |
| 309 | HDMI0_ACR_CTS_32(acr.cts_32khz), | 193 | HDMI0_ACR_CTS_32(acr->cts_32khz), |
| 310 | ~HDMI0_ACR_CTS_32_MASK); | 194 | ~HDMI0_ACR_CTS_32_MASK); |
| 311 | WREG32_P(HDMI0_ACR_32_1 + offset, | 195 | WREG32_P(HDMI0_ACR_32_1 + offset, |
| 312 | HDMI0_ACR_N_32(acr.n_32khz), | 196 | HDMI0_ACR_N_32(acr->n_32khz), |
| 313 | ~HDMI0_ACR_N_32_MASK); | 197 | ~HDMI0_ACR_N_32_MASK); |
| 314 | 198 | ||
| 315 | WREG32_P(HDMI0_ACR_44_0 + offset, | 199 | WREG32_P(HDMI0_ACR_44_0 + offset, |
| 316 | HDMI0_ACR_CTS_44(acr.cts_44_1khz), | 200 | HDMI0_ACR_CTS_44(acr->cts_44_1khz), |
| 317 | ~HDMI0_ACR_CTS_44_MASK); | 201 | ~HDMI0_ACR_CTS_44_MASK); |
| 318 | WREG32_P(HDMI0_ACR_44_1 + offset, | 202 | WREG32_P(HDMI0_ACR_44_1 + offset, |
| 319 | HDMI0_ACR_N_44(acr.n_44_1khz), | 203 | HDMI0_ACR_N_44(acr->n_44_1khz), |
| 320 | ~HDMI0_ACR_N_44_MASK); | 204 | ~HDMI0_ACR_N_44_MASK); |
| 321 | 205 | ||
| 322 | WREG32_P(HDMI0_ACR_48_0 + offset, | 206 | WREG32_P(HDMI0_ACR_48_0 + offset, |
| 323 | HDMI0_ACR_CTS_48(acr.cts_48khz), | 207 | HDMI0_ACR_CTS_48(acr->cts_48khz), |
| 324 | ~HDMI0_ACR_CTS_48_MASK); | 208 | ~HDMI0_ACR_CTS_48_MASK); |
| 325 | WREG32_P(HDMI0_ACR_48_1 + offset, | 209 | WREG32_P(HDMI0_ACR_48_1 + offset, |
| 326 | HDMI0_ACR_N_48(acr.n_48khz), | 210 | HDMI0_ACR_N_48(acr->n_48khz), |
| 327 | ~HDMI0_ACR_N_48_MASK); | 211 | ~HDMI0_ACR_N_48_MASK); |
| 328 | } | 212 | } |
| 329 | 213 | ||
| 330 | /* | 214 | /* |
| 331 | * build a HDMI Video Info Frame | 215 | * build a HDMI Video Info Frame |
| 332 | */ | 216 | */ |
| 333 | void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, | 217 | void r600_set_avi_packet(struct radeon_device *rdev, u32 offset, |
| 334 | size_t size) | 218 | unsigned char *buffer, size_t size) |
| 335 | { | 219 | { |
| 336 | struct drm_device *dev = encoder->dev; | ||
| 337 | struct radeon_device *rdev = dev->dev_private; | ||
| 338 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 339 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 340 | uint32_t offset = dig->afmt->offset; | ||
| 341 | uint8_t *frame = buffer + 3; | 220 | uint8_t *frame = buffer + 3; |
| 342 | uint8_t *header = buffer; | ||
| 343 | 221 | ||
| 344 | WREG32(HDMI0_AVI_INFO0 + offset, | 222 | WREG32(HDMI0_AVI_INFO0 + offset, |
| 345 | frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); | 223 | 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, | |||
| 348 | WREG32(HDMI0_AVI_INFO2 + offset, | 226 | WREG32(HDMI0_AVI_INFO2 + offset, |
| 349 | frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24)); | 227 | frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24)); |
| 350 | WREG32(HDMI0_AVI_INFO3 + offset, | 228 | WREG32(HDMI0_AVI_INFO3 + offset, |
| 351 | frame[0xC] | (frame[0xD] << 8) | (header[1] << 24)); | 229 | frame[0xC] | (frame[0xD] << 8) | (buffer[1] << 24)); |
| 230 | |||
| 231 | WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset, | ||
| 232 | HDMI0_AVI_INFO_SEND | /* enable AVI info frames */ | ||
| 233 | HDMI0_AVI_INFO_CONT); /* send AVI info frames every frame/field */ | ||
| 234 | |||
| 235 | WREG32_OR(HDMI0_INFOFRAME_CONTROL1 + offset, | ||
| 236 | HDMI0_AVI_INFO_LINE(2)); /* anything other than 0 */ | ||
| 352 | } | 237 | } |
| 353 | 238 | ||
| 354 | /* | 239 | /* |
| @@ -425,188 +310,94 @@ void r600_hdmi_audio_workaround(struct drm_encoder *encoder) | |||
| 425 | value, ~HDMI0_AUDIO_TEST_EN); | 310 | value, ~HDMI0_AUDIO_TEST_EN); |
| 426 | } | 311 | } |
| 427 | 312 | ||
| 428 | void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock) | 313 | void r600_hdmi_audio_set_dto(struct radeon_device *rdev, |
| 314 | struct radeon_crtc *crtc, unsigned int clock) | ||
| 429 | { | 315 | { |
| 430 | struct drm_device *dev = encoder->dev; | 316 | struct radeon_encoder *radeon_encoder; |
| 431 | struct radeon_device *rdev = dev->dev_private; | 317 | struct radeon_encoder_atom_dig *dig; |
| 432 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 433 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 434 | u32 base_rate = 24000; | ||
| 435 | u32 max_ratio = clock / base_rate; | ||
| 436 | u32 dto_phase; | ||
| 437 | u32 dto_modulo = clock; | ||
| 438 | u32 wallclock_ratio; | ||
| 439 | u32 dto_cntl; | ||
| 440 | 318 | ||
| 441 | if (!dig || !dig->afmt) | 319 | if (!crtc) |
| 442 | return; | 320 | return; |
| 443 | 321 | ||
| 444 | if (max_ratio >= 8) { | 322 | radeon_encoder = to_radeon_encoder(crtc->encoder); |
| 445 | dto_phase = 192 * 1000; | 323 | dig = radeon_encoder->enc_priv; |
| 446 | wallclock_ratio = 3; | ||
| 447 | } else if (max_ratio >= 4) { | ||
| 448 | dto_phase = 96 * 1000; | ||
| 449 | wallclock_ratio = 2; | ||
| 450 | } else if (max_ratio >= 2) { | ||
| 451 | dto_phase = 48 * 1000; | ||
| 452 | wallclock_ratio = 1; | ||
| 453 | } else { | ||
| 454 | dto_phase = 24 * 1000; | ||
| 455 | wallclock_ratio = 0; | ||
| 456 | } | ||
| 457 | 324 | ||
| 458 | /* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT. | 325 | if (!dig) |
| 459 | * doesn't matter which one you use. Just use the first one. | 326 | return; |
| 460 | */ | 327 | |
| 461 | /* XXX two dtos; generally use dto0 for hdmi */ | 328 | if (dig->dig_encoder == 0) { |
| 462 | /* Express [24MHz / target pixel clock] as an exact rational | 329 | WREG32(DCCG_AUDIO_DTO0_PHASE, 24000 * 100); |
| 463 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE | 330 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100); |
| 464 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator | 331 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ |
| 465 | */ | ||
| 466 | if (ASIC_IS_DCE32(rdev)) { | ||
| 467 | if (dig->dig_encoder == 0) { | ||
| 468 | dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; | ||
| 469 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); | ||
| 470 | WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl); | ||
| 471 | WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase); | ||
| 472 | WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo); | ||
| 473 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ | ||
| 474 | } else { | ||
| 475 | dto_cntl = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; | ||
| 476 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); | ||
| 477 | WREG32(DCCG_AUDIO_DTO1_CNTL, dto_cntl); | ||
| 478 | WREG32(DCCG_AUDIO_DTO1_PHASE, dto_phase); | ||
| 479 | WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo); | ||
| 480 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ | ||
| 481 | } | ||
| 482 | } else { | 332 | } else { |
| 483 | /* according to the reg specs, this should DCE3.2 only, but in | 333 | WREG32(DCCG_AUDIO_DTO1_PHASE, 24000 * 100); |
| 484 | * practice it seems to cover DCE2.0/3.0/3.1 as well. | 334 | WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100); |
| 485 | */ | 335 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ |
| 486 | if (dig->dig_encoder == 0) { | ||
| 487 | WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100); | ||
| 488 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100); | ||
| 489 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ | ||
| 490 | } else { | ||
| 491 | WREG32(DCCG_AUDIO_DTO1_PHASE, base_rate * 100); | ||
| 492 | WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100); | ||
| 493 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ | ||
| 494 | } | ||
| 495 | } | 336 | } |
| 496 | } | 337 | } |
| 497 | 338 | ||
| 498 | /* | 339 | void r600_set_vbi_packet(struct drm_encoder *encoder, u32 offset) |
| 499 | * update the info frames with the data from the current display mode | ||
| 500 | */ | ||
| 501 | void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) | ||
| 502 | { | 340 | { |
| 503 | struct drm_device *dev = encoder->dev; | 341 | struct drm_device *dev = encoder->dev; |
| 504 | struct radeon_device *rdev = dev->dev_private; | 342 | struct radeon_device *rdev = dev->dev_private; |
| 505 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 506 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 507 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; | ||
| 508 | struct hdmi_avi_infoframe frame; | ||
| 509 | uint32_t offset; | ||
| 510 | uint32_t acr_ctl; | ||
| 511 | ssize_t err; | ||
| 512 | |||
| 513 | if (!dig || !dig->afmt) | ||
| 514 | return; | ||
| 515 | |||
| 516 | /* Silent, r600_hdmi_enable will raise WARN for us */ | ||
| 517 | if (!dig->afmt->enabled) | ||
| 518 | return; | ||
| 519 | offset = dig->afmt->offset; | ||
| 520 | 343 | ||
| 521 | /* disable audio prior to setting up hw */ | 344 | WREG32_OR(HDMI0_VBI_PACKET_CONTROL + offset, |
| 522 | dig->afmt->pin = r600_audio_get_pin(rdev); | 345 | HDMI0_NULL_SEND | /* send null packets when required */ |
| 523 | r600_audio_enable(rdev, dig->afmt->pin, 0xf); | 346 | HDMI0_GC_SEND | /* send general control packets */ |
| 347 | HDMI0_GC_CONT); /* send general control packets every frame */ | ||
| 348 | } | ||
| 524 | 349 | ||
| 525 | r600_audio_set_dto(encoder, mode->clock); | 350 | void r600_set_audio_packet(struct drm_encoder *encoder, u32 offset) |
| 351 | { | ||
| 352 | struct drm_device *dev = encoder->dev; | ||
| 353 | struct radeon_device *rdev = dev->dev_private; | ||
| 526 | 354 | ||
| 527 | WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, | 355 | WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, |
| 528 | HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ | 356 | HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ |
| 529 | HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ | 357 | HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ |
| 530 | HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */ | 358 | HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */ |
| 531 | HDMI0_60958_CS_UPDATE, /* allow 60958 channel status fields to be updated */ | 359 | HDMI0_60958_CS_UPDATE, /* allow 60958 channel status fields to be updated */ |
| 532 | ~(HDMI0_AUDIO_SAMPLE_SEND | | 360 | ~(HDMI0_AUDIO_SAMPLE_SEND | |
| 533 | HDMI0_AUDIO_DELAY_EN_MASK | | 361 | HDMI0_AUDIO_DELAY_EN_MASK | |
| 534 | HDMI0_AUDIO_PACKETS_PER_LINE_MASK | | 362 | HDMI0_AUDIO_PACKETS_PER_LINE_MASK | |
| 535 | HDMI0_60958_CS_UPDATE)); | 363 | HDMI0_60958_CS_UPDATE)); |
| 536 | |||
| 537 | /* DCE 3.0 uses register that's normally for CRC_CONTROL */ | ||
| 538 | acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL : | ||
| 539 | HDMI0_ACR_PACKET_CONTROL; | ||
| 540 | WREG32_P(acr_ctl + offset, | ||
| 541 | HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */ | ||
| 542 | HDMI0_ACR_AUTO_SEND, /* allow hw to sent ACR packets when required */ | ||
| 543 | ~(HDMI0_ACR_SOURCE | | ||
| 544 | HDMI0_ACR_AUTO_SEND)); | ||
| 545 | |||
| 546 | WREG32_OR(HDMI0_VBI_PACKET_CONTROL + offset, | ||
| 547 | HDMI0_NULL_SEND | /* send null packets when required */ | ||
| 548 | HDMI0_GC_SEND | /* send general control packets */ | ||
| 549 | HDMI0_GC_CONT); /* send general control packets every frame */ | ||
| 550 | 364 | ||
| 551 | WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset, | 365 | WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset, |
| 552 | HDMI0_AVI_INFO_SEND | /* enable AVI info frames */ | 366 | HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ |
| 553 | HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */ | 367 | HDMI0_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */ |
| 554 | HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ | ||
| 555 | HDMI0_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */ | ||
| 556 | 368 | ||
| 557 | WREG32_P(HDMI0_INFOFRAME_CONTROL1 + offset, | 369 | WREG32_P(HDMI0_INFOFRAME_CONTROL1 + offset, |
| 558 | HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */ | 370 | HDMI0_AUDIO_INFO_LINE(2), /* anything other than 0 */ |
| 559 | HDMI0_AUDIO_INFO_LINE(2), /* anything other than 0 */ | 371 | ~HDMI0_AUDIO_INFO_LINE_MASK); |
| 560 | ~(HDMI0_AVI_INFO_LINE_MASK | | ||
| 561 | HDMI0_AUDIO_INFO_LINE_MASK)); | ||
| 562 | |||
| 563 | WREG32_AND(HDMI0_GC + offset, | ||
| 564 | ~HDMI0_GC_AVMUTE); /* unset HDMI0_GC_AVMUTE */ | ||
| 565 | |||
| 566 | err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); | ||
| 567 | if (err < 0) { | ||
| 568 | DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); | ||
| 569 | return; | ||
| 570 | } | ||
| 571 | |||
| 572 | err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); | ||
| 573 | if (err < 0) { | ||
| 574 | DRM_ERROR("failed to pack AVI infoframe: %zd\n", err); | ||
| 575 | return; | ||
| 576 | } | ||
| 577 | |||
| 578 | r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer)); | ||
| 579 | |||
| 580 | /* fglrx duplicates INFOFRAME_CONTROL0 & INFOFRAME_CONTROL1 ops here */ | ||
| 581 | 372 | ||
| 582 | WREG32_AND(HDMI0_GENERIC_PACKET_CONTROL + offset, | 373 | WREG32_AND(HDMI0_GENERIC_PACKET_CONTROL + offset, |
| 583 | ~(HDMI0_GENERIC0_SEND | | 374 | ~(HDMI0_GENERIC0_SEND | |
| 584 | HDMI0_GENERIC0_CONT | | 375 | HDMI0_GENERIC0_CONT | |
| 585 | HDMI0_GENERIC0_UPDATE | | 376 | HDMI0_GENERIC0_UPDATE | |
| 586 | HDMI0_GENERIC1_SEND | | 377 | HDMI0_GENERIC1_SEND | |
| 587 | HDMI0_GENERIC1_CONT | | 378 | HDMI0_GENERIC1_CONT | |
| 588 | HDMI0_GENERIC0_LINE_MASK | | 379 | HDMI0_GENERIC0_LINE_MASK | |
| 589 | HDMI0_GENERIC1_LINE_MASK)); | 380 | HDMI0_GENERIC1_LINE_MASK)); |
| 590 | |||
| 591 | r600_hdmi_update_ACR(encoder, mode->clock); | ||
| 592 | 381 | ||
| 593 | WREG32_P(HDMI0_60958_0 + offset, | 382 | WREG32_P(HDMI0_60958_0 + offset, |
| 594 | HDMI0_60958_CS_CHANNEL_NUMBER_L(1), | 383 | HDMI0_60958_CS_CHANNEL_NUMBER_L(1), |
| 595 | ~(HDMI0_60958_CS_CHANNEL_NUMBER_L_MASK | | 384 | ~(HDMI0_60958_CS_CHANNEL_NUMBER_L_MASK | |
| 596 | HDMI0_60958_CS_CLOCK_ACCURACY_MASK)); | 385 | HDMI0_60958_CS_CLOCK_ACCURACY_MASK)); |
| 597 | 386 | ||
| 598 | WREG32_P(HDMI0_60958_1 + offset, | 387 | WREG32_P(HDMI0_60958_1 + offset, |
| 599 | HDMI0_60958_CS_CHANNEL_NUMBER_R(2), | 388 | HDMI0_60958_CS_CHANNEL_NUMBER_R(2), |
| 600 | ~HDMI0_60958_CS_CHANNEL_NUMBER_R_MASK); | 389 | ~HDMI0_60958_CS_CHANNEL_NUMBER_R_MASK); |
| 390 | } | ||
| 601 | 391 | ||
| 602 | /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ | 392 | void r600_set_mute(struct drm_encoder *encoder, u32 offset, bool mute) |
| 603 | WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF); | 393 | { |
| 604 | WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF); | 394 | struct drm_device *dev = encoder->dev; |
| 605 | WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001); | 395 | struct radeon_device *rdev = dev->dev_private; |
| 606 | WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001); | ||
| 607 | 396 | ||
| 608 | /* enable audio after to setting up hw */ | 397 | if (mute) |
| 609 | r600_audio_enable(rdev, dig->afmt->pin, 0xf); | 398 | WREG32_OR(HDMI0_GC + offset, HDMI0_GC_AVMUTE); |
| 399 | else | ||
| 400 | WREG32_AND(HDMI0_GC + offset, ~HDMI0_GC_AVMUTE); | ||
| 610 | } | 401 | } |
| 611 | 402 | ||
| 612 | /** | 403 | /** |
| @@ -692,7 +483,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder, bool enable) | |||
| 692 | return; | 483 | return; |
| 693 | 484 | ||
| 694 | if (!enable && dig->afmt->pin) { | 485 | if (!enable && dig->afmt->pin) { |
| 695 | r600_audio_enable(rdev, dig->afmt->pin, 0); | 486 | radeon_audio_enable(rdev, dig->afmt->pin, 0); |
| 696 | dig->afmt->pin = NULL; | 487 | dig->afmt->pin = NULL; |
| 697 | } | 488 | } |
| 698 | 489 | ||
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 54529b837afa..93e407b7e7a7 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -1757,6 +1757,9 @@ struct r600_audio { | |||
| 1757 | bool enabled; | 1757 | bool enabled; |
| 1758 | struct r600_audio_pin pin[RADEON_MAX_AFMT_BLOCKS]; | 1758 | struct r600_audio_pin pin[RADEON_MAX_AFMT_BLOCKS]; |
| 1759 | int num_pins; | 1759 | int num_pins; |
| 1760 | struct radeon_audio_funcs *hdmi_funcs; | ||
| 1761 | struct radeon_audio_funcs *dp_funcs; | ||
| 1762 | struct radeon_audio_basic_funcs *funcs; | ||
| 1760 | }; | 1763 | }; |
| 1761 | 1764 | ||
| 1762 | /* | 1765 | /* |
| @@ -1777,8 +1780,16 @@ void radeon_test_syncing(struct radeon_device *rdev); | |||
| 1777 | /* | 1780 | /* |
| 1778 | * MMU Notifier | 1781 | * MMU Notifier |
| 1779 | */ | 1782 | */ |
| 1783 | #if defined(CONFIG_MMU_NOTIFIER) | ||
| 1780 | int radeon_mn_register(struct radeon_bo *bo, unsigned long addr); | 1784 | int radeon_mn_register(struct radeon_bo *bo, unsigned long addr); |
| 1781 | void radeon_mn_unregister(struct radeon_bo *bo); | 1785 | void radeon_mn_unregister(struct radeon_bo *bo); |
| 1786 | #else | ||
| 1787 | static inline int radeon_mn_register(struct radeon_bo *bo, unsigned long addr) | ||
| 1788 | { | ||
| 1789 | return -ENODEV; | ||
| 1790 | } | ||
| 1791 | static inline void radeon_mn_unregister(struct radeon_bo *bo) {} | ||
| 1792 | #endif | ||
| 1782 | 1793 | ||
| 1783 | /* | 1794 | /* |
| 1784 | * Debugfs | 1795 | * Debugfs |
| @@ -1967,6 +1978,10 @@ struct radeon_asic { | |||
| 1967 | bool (*vblank_too_short)(struct radeon_device *rdev); | 1978 | bool (*vblank_too_short)(struct radeon_device *rdev); |
| 1968 | void (*powergate_uvd)(struct radeon_device *rdev, bool gate); | 1979 | void (*powergate_uvd)(struct radeon_device *rdev, bool gate); |
| 1969 | void (*enable_bapm)(struct radeon_device *rdev, bool enable); | 1980 | void (*enable_bapm)(struct radeon_device *rdev, bool enable); |
| 1981 | void (*fan_ctrl_set_mode)(struct radeon_device *rdev, u32 mode); | ||
| 1982 | u32 (*fan_ctrl_get_mode)(struct radeon_device *rdev); | ||
| 1983 | int (*set_fan_speed_percent)(struct radeon_device *rdev, u32 speed); | ||
| 1984 | int (*get_fan_speed_percent)(struct radeon_device *rdev, u32 *speed); | ||
| 1970 | } dpm; | 1985 | } dpm; |
| 1971 | /* pageflipping */ | 1986 | /* pageflipping */ |
| 1972 | struct { | 1987 | struct { |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 121aff6a3b41..f811ee14a237 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
| @@ -638,8 +638,6 @@ static struct radeon_asic rs600_asic = { | |||
| 638 | .wait_for_vblank = &avivo_wait_for_vblank, | 638 | .wait_for_vblank = &avivo_wait_for_vblank, |
| 639 | .set_backlight_level = &atombios_set_backlight_level, | 639 | .set_backlight_level = &atombios_set_backlight_level, |
| 640 | .get_backlight_level = &atombios_get_backlight_level, | 640 | .get_backlight_level = &atombios_get_backlight_level, |
| 641 | .hdmi_enable = &r600_hdmi_enable, | ||
| 642 | .hdmi_setmode = &r600_hdmi_setmode, | ||
| 643 | }, | 641 | }, |
| 644 | .copy = { | 642 | .copy = { |
| 645 | .blit = &r100_copy_blit, | 643 | .blit = &r100_copy_blit, |
| @@ -706,8 +704,6 @@ static struct radeon_asic rs690_asic = { | |||
| 706 | .wait_for_vblank = &avivo_wait_for_vblank, | 704 | .wait_for_vblank = &avivo_wait_for_vblank, |
| 707 | .set_backlight_level = &atombios_set_backlight_level, | 705 | .set_backlight_level = &atombios_set_backlight_level, |
| 708 | .get_backlight_level = &atombios_get_backlight_level, | 706 | .get_backlight_level = &atombios_get_backlight_level, |
| 709 | .hdmi_enable = &r600_hdmi_enable, | ||
| 710 | .hdmi_setmode = &r600_hdmi_setmode, | ||
| 711 | }, | 707 | }, |
| 712 | .copy = { | 708 | .copy = { |
| 713 | .blit = &r100_copy_blit, | 709 | .blit = &r100_copy_blit, |
| @@ -935,8 +931,6 @@ static struct radeon_asic r600_asic = { | |||
| 935 | .wait_for_vblank = &avivo_wait_for_vblank, | 931 | .wait_for_vblank = &avivo_wait_for_vblank, |
| 936 | .set_backlight_level = &atombios_set_backlight_level, | 932 | .set_backlight_level = &atombios_set_backlight_level, |
| 937 | .get_backlight_level = &atombios_get_backlight_level, | 933 | .get_backlight_level = &atombios_get_backlight_level, |
| 938 | .hdmi_enable = &r600_hdmi_enable, | ||
| 939 | .hdmi_setmode = &r600_hdmi_setmode, | ||
| 940 | }, | 934 | }, |
| 941 | .copy = { | 935 | .copy = { |
| 942 | .blit = &r600_copy_cpdma, | 936 | .blit = &r600_copy_cpdma, |
| @@ -1021,8 +1015,6 @@ static struct radeon_asic rv6xx_asic = { | |||
| 1021 | .wait_for_vblank = &avivo_wait_for_vblank, | 1015 | .wait_for_vblank = &avivo_wait_for_vblank, |
| 1022 | .set_backlight_level = &atombios_set_backlight_level, | 1016 | .set_backlight_level = &atombios_set_backlight_level, |
| 1023 | .get_backlight_level = &atombios_get_backlight_level, | 1017 | .get_backlight_level = &atombios_get_backlight_level, |
| 1024 | .hdmi_enable = &r600_hdmi_enable, | ||
| 1025 | .hdmi_setmode = &r600_hdmi_setmode, | ||
| 1026 | }, | 1018 | }, |
| 1027 | .copy = { | 1019 | .copy = { |
| 1028 | .blit = &r600_copy_cpdma, | 1020 | .blit = &r600_copy_cpdma, |
| @@ -1112,8 +1104,6 @@ static struct radeon_asic rs780_asic = { | |||
| 1112 | .wait_for_vblank = &avivo_wait_for_vblank, | 1104 | .wait_for_vblank = &avivo_wait_for_vblank, |
| 1113 | .set_backlight_level = &atombios_set_backlight_level, | 1105 | .set_backlight_level = &atombios_set_backlight_level, |
| 1114 | .get_backlight_level = &atombios_get_backlight_level, | 1106 | .get_backlight_level = &atombios_get_backlight_level, |
| 1115 | .hdmi_enable = &r600_hdmi_enable, | ||
| 1116 | .hdmi_setmode = &r600_hdmi_setmode, | ||
| 1117 | }, | 1107 | }, |
| 1118 | .copy = { | 1108 | .copy = { |
| 1119 | .blit = &r600_copy_cpdma, | 1109 | .blit = &r600_copy_cpdma, |
| @@ -1216,8 +1206,6 @@ static struct radeon_asic rv770_asic = { | |||
| 1216 | .wait_for_vblank = &avivo_wait_for_vblank, | 1206 | .wait_for_vblank = &avivo_wait_for_vblank, |
| 1217 | .set_backlight_level = &atombios_set_backlight_level, | 1207 | .set_backlight_level = &atombios_set_backlight_level, |
| 1218 | .get_backlight_level = &atombios_get_backlight_level, | 1208 | .get_backlight_level = &atombios_get_backlight_level, |
| 1219 | .hdmi_enable = &r600_hdmi_enable, | ||
| 1220 | .hdmi_setmode = &dce3_1_hdmi_setmode, | ||
| 1221 | }, | 1209 | }, |
| 1222 | .copy = { | 1210 | .copy = { |
| 1223 | .blit = &r600_copy_cpdma, | 1211 | .blit = &r600_copy_cpdma, |
| @@ -1334,8 +1322,6 @@ static struct radeon_asic evergreen_asic = { | |||
| 1334 | .wait_for_vblank = &dce4_wait_for_vblank, | 1322 | .wait_for_vblank = &dce4_wait_for_vblank, |
| 1335 | .set_backlight_level = &atombios_set_backlight_level, | 1323 | .set_backlight_level = &atombios_set_backlight_level, |
| 1336 | .get_backlight_level = &atombios_get_backlight_level, | 1324 | .get_backlight_level = &atombios_get_backlight_level, |
| 1337 | .hdmi_enable = &evergreen_hdmi_enable, | ||
| 1338 | .hdmi_setmode = &evergreen_hdmi_setmode, | ||
| 1339 | }, | 1325 | }, |
| 1340 | .copy = { | 1326 | .copy = { |
| 1341 | .blit = &r600_copy_cpdma, | 1327 | .blit = &r600_copy_cpdma, |
| @@ -1426,8 +1412,6 @@ static struct radeon_asic sumo_asic = { | |||
| 1426 | .wait_for_vblank = &dce4_wait_for_vblank, | 1412 | .wait_for_vblank = &dce4_wait_for_vblank, |
| 1427 | .set_backlight_level = &atombios_set_backlight_level, | 1413 | .set_backlight_level = &atombios_set_backlight_level, |
| 1428 | .get_backlight_level = &atombios_get_backlight_level, | 1414 | .get_backlight_level = &atombios_get_backlight_level, |
| 1429 | .hdmi_enable = &evergreen_hdmi_enable, | ||
| 1430 | .hdmi_setmode = &evergreen_hdmi_setmode, | ||
| 1431 | }, | 1415 | }, |
| 1432 | .copy = { | 1416 | .copy = { |
| 1433 | .blit = &r600_copy_cpdma, | 1417 | .blit = &r600_copy_cpdma, |
| @@ -1517,8 +1501,6 @@ static struct radeon_asic btc_asic = { | |||
| 1517 | .wait_for_vblank = &dce4_wait_for_vblank, | 1501 | .wait_for_vblank = &dce4_wait_for_vblank, |
| 1518 | .set_backlight_level = &atombios_set_backlight_level, | 1502 | .set_backlight_level = &atombios_set_backlight_level, |
| 1519 | .get_backlight_level = &atombios_get_backlight_level, | 1503 | .get_backlight_level = &atombios_get_backlight_level, |
| 1520 | .hdmi_enable = &evergreen_hdmi_enable, | ||
| 1521 | .hdmi_setmode = &evergreen_hdmi_setmode, | ||
| 1522 | }, | 1504 | }, |
| 1523 | .copy = { | 1505 | .copy = { |
| 1524 | .blit = &r600_copy_cpdma, | 1506 | .blit = &r600_copy_cpdma, |
| @@ -1663,8 +1645,6 @@ static struct radeon_asic cayman_asic = { | |||
| 1663 | .wait_for_vblank = &dce4_wait_for_vblank, | 1645 | .wait_for_vblank = &dce4_wait_for_vblank, |
| 1664 | .set_backlight_level = &atombios_set_backlight_level, | 1646 | .set_backlight_level = &atombios_set_backlight_level, |
| 1665 | .get_backlight_level = &atombios_get_backlight_level, | 1647 | .get_backlight_level = &atombios_get_backlight_level, |
| 1666 | .hdmi_enable = &evergreen_hdmi_enable, | ||
| 1667 | .hdmi_setmode = &evergreen_hdmi_setmode, | ||
| 1668 | }, | 1648 | }, |
| 1669 | .copy = { | 1649 | .copy = { |
| 1670 | .blit = &r600_copy_cpdma, | 1650 | .blit = &r600_copy_cpdma, |
| @@ -1766,8 +1746,6 @@ static struct radeon_asic trinity_asic = { | |||
| 1766 | .wait_for_vblank = &dce4_wait_for_vblank, | 1746 | .wait_for_vblank = &dce4_wait_for_vblank, |
| 1767 | .set_backlight_level = &atombios_set_backlight_level, | 1747 | .set_backlight_level = &atombios_set_backlight_level, |
| 1768 | .get_backlight_level = &atombios_get_backlight_level, | 1748 | .get_backlight_level = &atombios_get_backlight_level, |
| 1769 | .hdmi_enable = &evergreen_hdmi_enable, | ||
| 1770 | .hdmi_setmode = &evergreen_hdmi_setmode, | ||
| 1771 | }, | 1749 | }, |
| 1772 | .copy = { | 1750 | .copy = { |
| 1773 | .blit = &r600_copy_cpdma, | 1751 | .blit = &r600_copy_cpdma, |
| @@ -1899,8 +1877,6 @@ static struct radeon_asic si_asic = { | |||
| 1899 | .wait_for_vblank = &dce4_wait_for_vblank, | 1877 | .wait_for_vblank = &dce4_wait_for_vblank, |
| 1900 | .set_backlight_level = &atombios_set_backlight_level, | 1878 | .set_backlight_level = &atombios_set_backlight_level, |
| 1901 | .get_backlight_level = &atombios_get_backlight_level, | 1879 | .get_backlight_level = &atombios_get_backlight_level, |
| 1902 | .hdmi_enable = &evergreen_hdmi_enable, | ||
| 1903 | .hdmi_setmode = &evergreen_hdmi_setmode, | ||
| 1904 | }, | 1880 | }, |
| 1905 | .copy = { | 1881 | .copy = { |
| 1906 | .blit = &r600_copy_cpdma, | 1882 | .blit = &r600_copy_cpdma, |
| @@ -1953,6 +1929,10 @@ static struct radeon_asic si_asic = { | |||
| 1953 | .debugfs_print_current_performance_level = &si_dpm_debugfs_print_current_performance_level, | 1929 | .debugfs_print_current_performance_level = &si_dpm_debugfs_print_current_performance_level, |
| 1954 | .force_performance_level = &si_dpm_force_performance_level, | 1930 | .force_performance_level = &si_dpm_force_performance_level, |
| 1955 | .vblank_too_short = &ni_dpm_vblank_too_short, | 1931 | .vblank_too_short = &ni_dpm_vblank_too_short, |
| 1932 | .fan_ctrl_set_mode = &si_fan_ctrl_set_mode, | ||
| 1933 | .fan_ctrl_get_mode = &si_fan_ctrl_get_mode, | ||
| 1934 | .get_fan_speed_percent = &si_fan_ctrl_get_fan_speed_percent, | ||
| 1935 | .set_fan_speed_percent = &si_fan_ctrl_set_fan_speed_percent, | ||
| 1956 | }, | 1936 | }, |
| 1957 | .pflip = { | 1937 | .pflip = { |
| 1958 | .page_flip = &evergreen_page_flip, | 1938 | .page_flip = &evergreen_page_flip, |
| @@ -2062,8 +2042,6 @@ static struct radeon_asic ci_asic = { | |||
| 2062 | .wait_for_vblank = &dce4_wait_for_vblank, | 2042 | .wait_for_vblank = &dce4_wait_for_vblank, |
| 2063 | .set_backlight_level = &atombios_set_backlight_level, | 2043 | .set_backlight_level = &atombios_set_backlight_level, |
| 2064 | .get_backlight_level = &atombios_get_backlight_level, | 2044 | .get_backlight_level = &atombios_get_backlight_level, |
| 2065 | .hdmi_enable = &evergreen_hdmi_enable, | ||
| 2066 | .hdmi_setmode = &evergreen_hdmi_setmode, | ||
| 2067 | }, | 2045 | }, |
| 2068 | .copy = { | 2046 | .copy = { |
| 2069 | .blit = &cik_copy_cpdma, | 2047 | .blit = &cik_copy_cpdma, |
| @@ -2118,6 +2096,10 @@ static struct radeon_asic ci_asic = { | |||
| 2118 | .force_performance_level = &ci_dpm_force_performance_level, | 2096 | .force_performance_level = &ci_dpm_force_performance_level, |
| 2119 | .vblank_too_short = &ci_dpm_vblank_too_short, | 2097 | .vblank_too_short = &ci_dpm_vblank_too_short, |
| 2120 | .powergate_uvd = &ci_dpm_powergate_uvd, | 2098 | .powergate_uvd = &ci_dpm_powergate_uvd, |
| 2099 | .fan_ctrl_set_mode = &ci_fan_ctrl_set_mode, | ||
| 2100 | .fan_ctrl_get_mode = &ci_fan_ctrl_get_mode, | ||
| 2101 | .get_fan_speed_percent = &ci_fan_ctrl_get_fan_speed_percent, | ||
| 2102 | .set_fan_speed_percent = &ci_fan_ctrl_set_fan_speed_percent, | ||
| 2121 | }, | 2103 | }, |
| 2122 | .pflip = { | 2104 | .pflip = { |
| 2123 | .page_flip = &evergreen_page_flip, | 2105 | .page_flip = &evergreen_page_flip, |
| @@ -2169,8 +2151,6 @@ static struct radeon_asic kv_asic = { | |||
| 2169 | .wait_for_vblank = &dce4_wait_for_vblank, | 2151 | .wait_for_vblank = &dce4_wait_for_vblank, |
| 2170 | .set_backlight_level = &atombios_set_backlight_level, | 2152 | .set_backlight_level = &atombios_set_backlight_level, |
| 2171 | .get_backlight_level = &atombios_get_backlight_level, | 2153 | .get_backlight_level = &atombios_get_backlight_level, |
| 2172 | .hdmi_enable = &evergreen_hdmi_enable, | ||
| 2173 | .hdmi_setmode = &evergreen_hdmi_setmode, | ||
| 2174 | }, | 2154 | }, |
| 2175 | .copy = { | 2155 | .copy = { |
| 2176 | .blit = &cik_copy_cpdma, | 2156 | .blit = &cik_copy_cpdma, |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 2a45d548d5ec..4045a320a424 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
| @@ -390,7 +390,6 @@ void r600_irq_suspend(struct radeon_device *rdev); | |||
| 390 | void r600_disable_interrupts(struct radeon_device *rdev); | 390 | void r600_disable_interrupts(struct radeon_device *rdev); |
| 391 | void r600_rlc_stop(struct radeon_device *rdev); | 391 | void r600_rlc_stop(struct radeon_device *rdev); |
| 392 | /* r600 audio */ | 392 | /* r600 audio */ |
| 393 | int r600_audio_init(struct radeon_device *rdev); | ||
| 394 | void r600_audio_fini(struct radeon_device *rdev); | 393 | void r600_audio_fini(struct radeon_device *rdev); |
| 395 | void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock); | 394 | void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock); |
| 396 | void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, | 395 | 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); | |||
| 399 | void r600_hdmi_audio_workaround(struct drm_encoder *encoder); | 398 | void r600_hdmi_audio_workaround(struct drm_encoder *encoder); |
| 400 | int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); | 399 | int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); |
| 401 | void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); | 400 | void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); |
| 402 | void r600_hdmi_enable(struct drm_encoder *encoder, bool enable); | ||
| 403 | void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); | ||
| 404 | int r600_mc_wait_for_idle(struct radeon_device *rdev); | 401 | int r600_mc_wait_for_idle(struct radeon_device *rdev); |
| 405 | u32 r600_get_xclk(struct radeon_device *rdev); | 402 | u32 r600_get_xclk(struct radeon_device *rdev); |
| 406 | uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev); | 403 | 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, | |||
| 469 | u32 rv770_get_xclk(struct radeon_device *rdev); | 466 | u32 rv770_get_xclk(struct radeon_device *rdev); |
| 470 | int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); | 467 | int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); |
| 471 | int rv770_get_temp(struct radeon_device *rdev); | 468 | int rv770_get_temp(struct radeon_device *rdev); |
| 472 | /* hdmi */ | ||
| 473 | void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); | ||
| 474 | /* rv7xx pm */ | 469 | /* rv7xx pm */ |
| 475 | int rv770_dpm_init(struct radeon_device *rdev); | 470 | int rv770_dpm_init(struct radeon_device *rdev); |
| 476 | int rv770_dpm_enable(struct radeon_device *rdev); | 471 | int rv770_dpm_enable(struct radeon_device *rdev); |
| @@ -540,8 +535,6 @@ struct radeon_fence *evergreen_copy_dma(struct radeon_device *rdev, | |||
| 540 | uint64_t src_offset, uint64_t dst_offset, | 535 | uint64_t src_offset, uint64_t dst_offset, |
| 541 | unsigned num_gpu_pages, | 536 | unsigned num_gpu_pages, |
| 542 | struct reservation_object *resv); | 537 | struct reservation_object *resv); |
| 543 | void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable); | ||
| 544 | void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); | ||
| 545 | int evergreen_get_temp(struct radeon_device *rdev); | 538 | int evergreen_get_temp(struct radeon_device *rdev); |
| 546 | int sumo_get_temp(struct radeon_device *rdev); | 539 | int sumo_get_temp(struct radeon_device *rdev); |
| 547 | int tn_get_temp(struct radeon_device *rdev); | 540 | int tn_get_temp(struct radeon_device *rdev); |
| @@ -680,7 +673,6 @@ void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable); | |||
| 680 | 673 | ||
| 681 | /* DCE6 - SI */ | 674 | /* DCE6 - SI */ |
| 682 | void dce6_bandwidth_update(struct radeon_device *rdev); | 675 | void dce6_bandwidth_update(struct radeon_device *rdev); |
| 683 | int dce6_audio_init(struct radeon_device *rdev); | ||
| 684 | void dce6_audio_fini(struct radeon_device *rdev); | 676 | void dce6_audio_fini(struct radeon_device *rdev); |
| 685 | 677 | ||
| 686 | /* | 678 | /* |
| @@ -744,6 +736,12 @@ void si_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, | |||
| 744 | struct seq_file *m); | 736 | struct seq_file *m); |
| 745 | int si_dpm_force_performance_level(struct radeon_device *rdev, | 737 | int si_dpm_force_performance_level(struct radeon_device *rdev, |
| 746 | enum radeon_dpm_forced_level level); | 738 | enum radeon_dpm_forced_level level); |
| 739 | int si_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, | ||
| 740 | u32 *speed); | ||
| 741 | int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, | ||
| 742 | u32 speed); | ||
| 743 | u32 si_fan_ctrl_get_mode(struct radeon_device *rdev); | ||
| 744 | void si_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode); | ||
| 747 | 745 | ||
| 748 | /* DCE8 - CIK */ | 746 | /* DCE8 - CIK */ |
| 749 | void dce8_bandwidth_update(struct radeon_device *rdev); | 747 | void dce8_bandwidth_update(struct radeon_device *rdev); |
| @@ -861,6 +859,13 @@ int ci_dpm_force_performance_level(struct radeon_device *rdev, | |||
| 861 | bool ci_dpm_vblank_too_short(struct radeon_device *rdev); | 859 | bool ci_dpm_vblank_too_short(struct radeon_device *rdev); |
| 862 | void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); | 860 | void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); |
| 863 | 861 | ||
| 862 | int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, | ||
| 863 | u32 *speed); | ||
| 864 | int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, | ||
| 865 | u32 speed); | ||
| 866 | u32 ci_fan_ctrl_get_mode(struct radeon_device *rdev); | ||
| 867 | void ci_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode); | ||
| 868 | |||
| 864 | int kv_dpm_init(struct radeon_device *rdev); | 869 | int kv_dpm_init(struct radeon_device *rdev); |
| 865 | int kv_dpm_enable(struct radeon_device *rdev); | 870 | int kv_dpm_enable(struct radeon_device *rdev); |
| 866 | int kv_dpm_late_enable(struct radeon_device *rdev); | 871 | int kv_dpm_late_enable(struct radeon_device *rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c new file mode 100644 index 000000000000..a3ceef6d9632 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_audio.c | |||
| @@ -0,0 +1,766 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2014 Advanced Micro Devices, Inc. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included in | ||
| 12 | * all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 21 | * | ||
| 22 | * Authors: Slava Grigorev <slava.grigorev@amd.com> | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <linux/gcd.h> | ||
| 26 | #include <drm/drmP.h> | ||
| 27 | #include <drm/drm_crtc.h> | ||
| 28 | #include "radeon.h" | ||
| 29 | #include "atom.h" | ||
| 30 | #include "radeon_audio.h" | ||
| 31 | |||
| 32 | void r600_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin, | ||
| 33 | u8 enable_mask); | ||
| 34 | void dce4_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin, | ||
| 35 | u8 enable_mask); | ||
| 36 | void dce6_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin, | ||
| 37 | u8 enable_mask); | ||
| 38 | u32 dce6_endpoint_rreg(struct radeon_device *rdev, u32 offset, u32 reg); | ||
| 39 | void dce6_endpoint_wreg(struct radeon_device *rdev, | ||
| 40 | u32 offset, u32 reg, u32 v); | ||
| 41 | void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder, | ||
| 42 | struct cea_sad *sads, int sad_count); | ||
| 43 | void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder, | ||
| 44 | struct cea_sad *sads, int sad_count); | ||
| 45 | void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, | ||
| 46 | struct cea_sad *sads, int sad_count); | ||
| 47 | void dce3_2_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, | ||
| 48 | u8 *sadb, int sad_count); | ||
| 49 | void dce3_2_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, | ||
| 50 | u8 *sadb, int sad_count); | ||
| 51 | void dce4_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, | ||
| 52 | u8 *sadb, int sad_count); | ||
| 53 | void dce4_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, | ||
| 54 | u8 *sadb, int sad_count); | ||
| 55 | void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, | ||
| 56 | u8 *sadb, int sad_count); | ||
| 57 | void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, | ||
| 58 | u8 *sadb, int sad_count); | ||
| 59 | void dce4_afmt_write_latency_fields(struct drm_encoder *encoder, | ||
| 60 | struct drm_connector *connector, struct drm_display_mode *mode); | ||
| 61 | void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, | ||
| 62 | struct drm_connector *connector, struct drm_display_mode *mode); | ||
| 63 | struct r600_audio_pin* r600_audio_get_pin(struct radeon_device *rdev); | ||
| 64 | struct r600_audio_pin* dce6_audio_get_pin(struct radeon_device *rdev); | ||
| 65 | void dce6_afmt_select_pin(struct drm_encoder *encoder); | ||
| 66 | void r600_hdmi_audio_set_dto(struct radeon_device *rdev, | ||
| 67 | struct radeon_crtc *crtc, unsigned int clock); | ||
| 68 | void dce3_2_audio_set_dto(struct radeon_device *rdev, | ||
| 69 | struct radeon_crtc *crtc, unsigned int clock); | ||
| 70 | void dce4_hdmi_audio_set_dto(struct radeon_device *rdev, | ||
| 71 | struct radeon_crtc *crtc, unsigned int clock); | ||
| 72 | void dce4_dp_audio_set_dto(struct radeon_device *rdev, | ||
| 73 | struct radeon_crtc *crtc, unsigned int clock); | ||
| 74 | void dce6_hdmi_audio_set_dto(struct radeon_device *rdev, | ||
| 75 | struct radeon_crtc *crtc, unsigned int clock); | ||
| 76 | void dce6_dp_audio_set_dto(struct radeon_device *rdev, | ||
| 77 | struct radeon_crtc *crtc, unsigned int clock); | ||
| 78 | void r600_set_avi_packet(struct radeon_device *rdev, u32 offset, | ||
| 79 | unsigned char *buffer, size_t size); | ||
| 80 | void evergreen_set_avi_packet(struct radeon_device *rdev, u32 offset, | ||
| 81 | unsigned char *buffer, size_t size); | ||
| 82 | void r600_hdmi_update_acr(struct drm_encoder *encoder, long offset, | ||
| 83 | const struct radeon_hdmi_acr *acr); | ||
| 84 | void dce3_2_hdmi_update_acr(struct drm_encoder *encoder, long offset, | ||
| 85 | const struct radeon_hdmi_acr *acr); | ||
| 86 | void evergreen_hdmi_update_acr(struct drm_encoder *encoder, long offset, | ||
| 87 | const struct radeon_hdmi_acr *acr); | ||
| 88 | void r600_set_vbi_packet(struct drm_encoder *encoder, u32 offset); | ||
| 89 | void dce4_set_vbi_packet(struct drm_encoder *encoder, u32 offset); | ||
| 90 | void dce4_hdmi_set_color_depth(struct drm_encoder *encoder, | ||
| 91 | u32 offset, int bpc); | ||
| 92 | void r600_set_audio_packet(struct drm_encoder *encoder, u32 offset); | ||
| 93 | void dce3_2_set_audio_packet(struct drm_encoder *encoder, u32 offset); | ||
| 94 | void dce4_set_audio_packet(struct drm_encoder *encoder, u32 offset); | ||
| 95 | void r600_set_mute(struct drm_encoder *encoder, u32 offset, bool mute); | ||
| 96 | void dce3_2_set_mute(struct drm_encoder *encoder, u32 offset, bool mute); | ||
| 97 | void dce4_set_mute(struct drm_encoder *encoder, u32 offset, bool mute); | ||
| 98 | static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, | ||
| 99 | struct drm_display_mode *mode); | ||
| 100 | static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, | ||
| 101 | struct drm_display_mode *mode); | ||
| 102 | void r600_hdmi_enable(struct drm_encoder *encoder, bool enable); | ||
| 103 | void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable); | ||
| 104 | void evergreen_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable); | ||
| 105 | void dce6_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable); | ||
| 106 | |||
| 107 | static const u32 pin_offsets[7] = | ||
| 108 | { | ||
| 109 | (0x5e00 - 0x5e00), | ||
| 110 | (0x5e18 - 0x5e00), | ||
| 111 | (0x5e30 - 0x5e00), | ||
| 112 | (0x5e48 - 0x5e00), | ||
| 113 | (0x5e60 - 0x5e00), | ||
| 114 | (0x5e78 - 0x5e00), | ||
| 115 | (0x5e90 - 0x5e00), | ||
| 116 | }; | ||
| 117 | |||
| 118 | static u32 radeon_audio_rreg(struct radeon_device *rdev, u32 offset, u32 reg) | ||
| 119 | { | ||
| 120 | return RREG32(reg); | ||
| 121 | } | ||
| 122 | |||
| 123 | static void radeon_audio_wreg(struct radeon_device *rdev, u32 offset, | ||
| 124 | u32 reg, u32 v) | ||
| 125 | { | ||
| 126 | WREG32(reg, v); | ||
| 127 | } | ||
| 128 | |||
| 129 | static struct radeon_audio_basic_funcs r600_funcs = { | ||
| 130 | .endpoint_rreg = radeon_audio_rreg, | ||
| 131 | .endpoint_wreg = radeon_audio_wreg, | ||
| 132 | .enable = r600_audio_enable, | ||
| 133 | }; | ||
| 134 | |||
| 135 | static struct radeon_audio_basic_funcs dce32_funcs = { | ||
| 136 | .endpoint_rreg = radeon_audio_rreg, | ||
| 137 | .endpoint_wreg = radeon_audio_wreg, | ||
| 138 | .enable = r600_audio_enable, | ||
| 139 | }; | ||
| 140 | |||
| 141 | static struct radeon_audio_basic_funcs dce4_funcs = { | ||
| 142 | .endpoint_rreg = radeon_audio_rreg, | ||
| 143 | .endpoint_wreg = radeon_audio_wreg, | ||
| 144 | .enable = dce4_audio_enable, | ||
| 145 | }; | ||
| 146 | |||
| 147 | static struct radeon_audio_basic_funcs dce6_funcs = { | ||
| 148 | .endpoint_rreg = dce6_endpoint_rreg, | ||
| 149 | .endpoint_wreg = dce6_endpoint_wreg, | ||
| 150 | .enable = dce6_audio_enable, | ||
| 151 | }; | ||
| 152 | |||
| 153 | static struct radeon_audio_funcs r600_hdmi_funcs = { | ||
| 154 | .get_pin = r600_audio_get_pin, | ||
| 155 | .set_dto = r600_hdmi_audio_set_dto, | ||
| 156 | .update_acr = r600_hdmi_update_acr, | ||
| 157 | .set_vbi_packet = r600_set_vbi_packet, | ||
| 158 | .set_avi_packet = r600_set_avi_packet, | ||
| 159 | .set_audio_packet = r600_set_audio_packet, | ||
| 160 | .set_mute = r600_set_mute, | ||
| 161 | .mode_set = radeon_audio_hdmi_mode_set, | ||
| 162 | .dpms = r600_hdmi_enable, | ||
| 163 | }; | ||
| 164 | |||
| 165 | static struct radeon_audio_funcs dce32_hdmi_funcs = { | ||
| 166 | .get_pin = r600_audio_get_pin, | ||
| 167 | .write_sad_regs = dce3_2_afmt_write_sad_regs, | ||
| 168 | .write_speaker_allocation = dce3_2_afmt_hdmi_write_speaker_allocation, | ||
| 169 | .set_dto = dce3_2_audio_set_dto, | ||
| 170 | .update_acr = dce3_2_hdmi_update_acr, | ||
| 171 | .set_vbi_packet = r600_set_vbi_packet, | ||
| 172 | .set_avi_packet = r600_set_avi_packet, | ||
| 173 | .set_audio_packet = dce3_2_set_audio_packet, | ||
| 174 | .set_mute = dce3_2_set_mute, | ||
| 175 | .mode_set = radeon_audio_hdmi_mode_set, | ||
| 176 | .dpms = r600_hdmi_enable, | ||
| 177 | }; | ||
| 178 | |||
| 179 | static struct radeon_audio_funcs dce32_dp_funcs = { | ||
| 180 | .get_pin = r600_audio_get_pin, | ||
| 181 | .write_sad_regs = dce3_2_afmt_write_sad_regs, | ||
| 182 | .write_speaker_allocation = dce3_2_afmt_dp_write_speaker_allocation, | ||
| 183 | .set_dto = dce3_2_audio_set_dto, | ||
| 184 | .set_avi_packet = r600_set_avi_packet, | ||
| 185 | .set_audio_packet = dce3_2_set_audio_packet, | ||
| 186 | }; | ||
| 187 | |||
| 188 | static struct radeon_audio_funcs dce4_hdmi_funcs = { | ||
| 189 | .get_pin = r600_audio_get_pin, | ||
| 190 | .write_sad_regs = evergreen_hdmi_write_sad_regs, | ||
| 191 | .write_speaker_allocation = dce4_afmt_hdmi_write_speaker_allocation, | ||
| 192 | .write_latency_fields = dce4_afmt_write_latency_fields, | ||
| 193 | .set_dto = dce4_hdmi_audio_set_dto, | ||
| 194 | .update_acr = evergreen_hdmi_update_acr, | ||
| 195 | .set_vbi_packet = dce4_set_vbi_packet, | ||
| 196 | .set_color_depth = dce4_hdmi_set_color_depth, | ||
| 197 | .set_avi_packet = evergreen_set_avi_packet, | ||
| 198 | .set_audio_packet = dce4_set_audio_packet, | ||
| 199 | .set_mute = dce4_set_mute, | ||
| 200 | .mode_set = radeon_audio_hdmi_mode_set, | ||
| 201 | .dpms = evergreen_hdmi_enable, | ||
| 202 | }; | ||
| 203 | |||
| 204 | static struct radeon_audio_funcs dce4_dp_funcs = { | ||
| 205 | .get_pin = r600_audio_get_pin, | ||
| 206 | .write_sad_regs = evergreen_hdmi_write_sad_regs, | ||
| 207 | .write_speaker_allocation = dce4_afmt_dp_write_speaker_allocation, | ||
| 208 | .write_latency_fields = dce4_afmt_write_latency_fields, | ||
| 209 | .set_dto = dce4_dp_audio_set_dto, | ||
| 210 | .set_avi_packet = evergreen_set_avi_packet, | ||
| 211 | .set_audio_packet = dce4_set_audio_packet, | ||
| 212 | .mode_set = radeon_audio_dp_mode_set, | ||
| 213 | .dpms = evergreen_enable_dp_audio_packets, | ||
| 214 | }; | ||
| 215 | |||
| 216 | static struct radeon_audio_funcs dce6_hdmi_funcs = { | ||
| 217 | .select_pin = dce6_afmt_select_pin, | ||
| 218 | .get_pin = dce6_audio_get_pin, | ||
| 219 | .write_sad_regs = dce6_afmt_write_sad_regs, | ||
| 220 | .write_speaker_allocation = dce6_afmt_hdmi_write_speaker_allocation, | ||
| 221 | .write_latency_fields = dce6_afmt_write_latency_fields, | ||
| 222 | .set_dto = dce6_hdmi_audio_set_dto, | ||
| 223 | .update_acr = evergreen_hdmi_update_acr, | ||
| 224 | .set_vbi_packet = dce4_set_vbi_packet, | ||
| 225 | .set_color_depth = dce4_hdmi_set_color_depth, | ||
| 226 | .set_avi_packet = evergreen_set_avi_packet, | ||
| 227 | .set_audio_packet = dce4_set_audio_packet, | ||
| 228 | .set_mute = dce4_set_mute, | ||
| 229 | .mode_set = radeon_audio_hdmi_mode_set, | ||
| 230 | .dpms = evergreen_hdmi_enable, | ||
| 231 | }; | ||
| 232 | |||
| 233 | static struct radeon_audio_funcs dce6_dp_funcs = { | ||
| 234 | .select_pin = dce6_afmt_select_pin, | ||
| 235 | .get_pin = dce6_audio_get_pin, | ||
| 236 | .write_sad_regs = dce6_afmt_write_sad_regs, | ||
| 237 | .write_speaker_allocation = dce6_afmt_dp_write_speaker_allocation, | ||
| 238 | .write_latency_fields = dce6_afmt_write_latency_fields, | ||
| 239 | .set_dto = dce6_dp_audio_set_dto, | ||
| 240 | .set_avi_packet = evergreen_set_avi_packet, | ||
| 241 | .set_audio_packet = dce4_set_audio_packet, | ||
| 242 | .mode_set = radeon_audio_dp_mode_set, | ||
| 243 | .dpms = dce6_enable_dp_audio_packets, | ||
| 244 | }; | ||
| 245 | |||
| 246 | static void radeon_audio_interface_init(struct radeon_device *rdev) | ||
| 247 | { | ||
| 248 | if (ASIC_IS_DCE6(rdev)) { | ||
| 249 | rdev->audio.funcs = &dce6_funcs; | ||
| 250 | rdev->audio.hdmi_funcs = &dce6_hdmi_funcs; | ||
| 251 | rdev->audio.dp_funcs = &dce6_dp_funcs; | ||
| 252 | } else if (ASIC_IS_DCE4(rdev)) { | ||
| 253 | rdev->audio.funcs = &dce4_funcs; | ||
| 254 | rdev->audio.hdmi_funcs = &dce4_hdmi_funcs; | ||
| 255 | rdev->audio.dp_funcs = &dce4_dp_funcs; | ||
| 256 | } else if (ASIC_IS_DCE32(rdev)) { | ||
| 257 | rdev->audio.funcs = &dce32_funcs; | ||
| 258 | rdev->audio.hdmi_funcs = &dce32_hdmi_funcs; | ||
| 259 | rdev->audio.dp_funcs = &dce32_dp_funcs; | ||
| 260 | } else { | ||
| 261 | rdev->audio.funcs = &r600_funcs; | ||
| 262 | rdev->audio.hdmi_funcs = &r600_hdmi_funcs; | ||
| 263 | rdev->audio.dp_funcs = 0; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | static int radeon_audio_chipset_supported(struct radeon_device *rdev) | ||
| 268 | { | ||
| 269 | return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev); | ||
| 270 | } | ||
| 271 | |||
| 272 | int radeon_audio_init(struct radeon_device *rdev) | ||
| 273 | { | ||
| 274 | int i; | ||
| 275 | |||
| 276 | if (!radeon_audio || !radeon_audio_chipset_supported(rdev)) | ||
| 277 | return 0; | ||
| 278 | |||
| 279 | rdev->audio.enabled = true; | ||
| 280 | |||
| 281 | if (ASIC_IS_DCE83(rdev)) /* KB: 2 streams, 3 endpoints */ | ||
| 282 | rdev->audio.num_pins = 3; | ||
| 283 | else if (ASIC_IS_DCE81(rdev)) /* KV: 4 streams, 7 endpoints */ | ||
| 284 | rdev->audio.num_pins = 7; | ||
| 285 | else if (ASIC_IS_DCE8(rdev)) /* BN/HW: 6 streams, 7 endpoints */ | ||
| 286 | rdev->audio.num_pins = 7; | ||
| 287 | else if (ASIC_IS_DCE64(rdev)) /* OL: 2 streams, 2 endpoints */ | ||
| 288 | rdev->audio.num_pins = 2; | ||
| 289 | else if (ASIC_IS_DCE61(rdev)) /* TN: 4 streams, 6 endpoints */ | ||
| 290 | rdev->audio.num_pins = 6; | ||
| 291 | else if (ASIC_IS_DCE6(rdev)) /* SI: 6 streams, 6 endpoints */ | ||
| 292 | rdev->audio.num_pins = 6; | ||
| 293 | else | ||
| 294 | rdev->audio.num_pins = 1; | ||
| 295 | |||
| 296 | for (i = 0; i < rdev->audio.num_pins; i++) { | ||
| 297 | rdev->audio.pin[i].channels = -1; | ||
| 298 | rdev->audio.pin[i].rate = -1; | ||
| 299 | rdev->audio.pin[i].bits_per_sample = -1; | ||
| 300 | rdev->audio.pin[i].status_bits = 0; | ||
| 301 | rdev->audio.pin[i].category_code = 0; | ||
| 302 | rdev->audio.pin[i].connected = false; | ||
| 303 | rdev->audio.pin[i].offset = pin_offsets[i]; | ||
| 304 | rdev->audio.pin[i].id = i; | ||
| 305 | } | ||
| 306 | |||
| 307 | radeon_audio_interface_init(rdev); | ||
| 308 | |||
| 309 | /* disable audio. it will be set up later */ | ||
| 310 | for (i = 0; i < rdev->audio.num_pins; i++) | ||
| 311 | radeon_audio_enable(rdev, &rdev->audio.pin[i], false); | ||
| 312 | |||
| 313 | return 0; | ||
| 314 | } | ||
| 315 | |||
| 316 | u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev, u32 offset, u32 reg) | ||
| 317 | { | ||
| 318 | if (rdev->audio.funcs->endpoint_rreg) | ||
| 319 | return rdev->audio.funcs->endpoint_rreg(rdev, offset, reg); | ||
| 320 | |||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | |||
| 324 | void radeon_audio_endpoint_wreg(struct radeon_device *rdev, u32 offset, | ||
| 325 | u32 reg, u32 v) | ||
| 326 | { | ||
| 327 | if (rdev->audio.funcs->endpoint_wreg) | ||
| 328 | rdev->audio.funcs->endpoint_wreg(rdev, offset, reg, v); | ||
| 329 | } | ||
| 330 | |||
| 331 | static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) | ||
| 332 | { | ||
| 333 | struct radeon_encoder *radeon_encoder; | ||
| 334 | struct drm_connector *connector; | ||
| 335 | struct radeon_connector *radeon_connector = NULL; | ||
| 336 | struct cea_sad *sads; | ||
| 337 | int sad_count; | ||
| 338 | |||
| 339 | list_for_each_entry(connector, | ||
| 340 | &encoder->dev->mode_config.connector_list, head) { | ||
| 341 | if (connector->encoder == encoder) { | ||
| 342 | radeon_connector = to_radeon_connector(connector); | ||
| 343 | break; | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | if (!radeon_connector) { | ||
| 348 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
| 349 | return; | ||
| 350 | } | ||
| 351 | |||
| 352 | sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads); | ||
| 353 | if (sad_count <= 0) { | ||
| 354 | DRM_ERROR("Couldn't read SADs: %d\n", sad_count); | ||
| 355 | return; | ||
| 356 | } | ||
| 357 | BUG_ON(!sads); | ||
| 358 | |||
| 359 | radeon_encoder = to_radeon_encoder(encoder); | ||
| 360 | |||
| 361 | if (radeon_encoder->audio && radeon_encoder->audio->write_sad_regs) | ||
| 362 | radeon_encoder->audio->write_sad_regs(encoder, sads, sad_count); | ||
| 363 | |||
| 364 | kfree(sads); | ||
| 365 | } | ||
| 366 | |||
| 367 | static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder) | ||
| 368 | { | ||
| 369 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 370 | struct drm_connector *connector; | ||
| 371 | struct radeon_connector *radeon_connector = NULL; | ||
| 372 | u8 *sadb = NULL; | ||
| 373 | int sad_count; | ||
| 374 | |||
| 375 | list_for_each_entry(connector, | ||
| 376 | &encoder->dev->mode_config.connector_list, head) { | ||
| 377 | if (connector->encoder == encoder) { | ||
| 378 | radeon_connector = to_radeon_connector(connector); | ||
| 379 | break; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | if (!radeon_connector) { | ||
| 384 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
| 385 | return; | ||
| 386 | } | ||
| 387 | |||
| 388 | sad_count = drm_edid_to_speaker_allocation( | ||
| 389 | radeon_connector_edid(connector), &sadb); | ||
| 390 | if (sad_count < 0) { | ||
| 391 | DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", | ||
| 392 | sad_count); | ||
| 393 | sad_count = 0; | ||
| 394 | } | ||
| 395 | |||
| 396 | if (radeon_encoder->audio && radeon_encoder->audio->write_speaker_allocation) | ||
| 397 | radeon_encoder->audio->write_speaker_allocation(encoder, sadb, sad_count); | ||
| 398 | |||
| 399 | kfree(sadb); | ||
| 400 | } | ||
| 401 | |||
| 402 | static void radeon_audio_write_latency_fields(struct drm_encoder *encoder, | ||
| 403 | struct drm_display_mode *mode) | ||
| 404 | { | ||
| 405 | struct radeon_encoder *radeon_encoder; | ||
| 406 | struct drm_connector *connector; | ||
| 407 | struct radeon_connector *radeon_connector = 0; | ||
| 408 | |||
| 409 | list_for_each_entry(connector, | ||
| 410 | &encoder->dev->mode_config.connector_list, head) { | ||
| 411 | if (connector->encoder == encoder) { | ||
| 412 | radeon_connector = to_radeon_connector(connector); | ||
| 413 | break; | ||
| 414 | } | ||
| 415 | } | ||
| 416 | |||
| 417 | if (!radeon_connector) { | ||
| 418 | DRM_ERROR("Couldn't find encoder's connector\n"); | ||
| 419 | return; | ||
| 420 | } | ||
| 421 | |||
| 422 | radeon_encoder = to_radeon_encoder(encoder); | ||
| 423 | |||
| 424 | if (radeon_encoder->audio && radeon_encoder->audio->write_latency_fields) | ||
| 425 | radeon_encoder->audio->write_latency_fields(encoder, connector, mode); | ||
| 426 | } | ||
| 427 | |||
| 428 | struct r600_audio_pin* radeon_audio_get_pin(struct drm_encoder *encoder) | ||
| 429 | { | ||
| 430 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 431 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 432 | |||
| 433 | if (radeon_encoder->audio && radeon_encoder->audio->get_pin) | ||
| 434 | return radeon_encoder->audio->get_pin(rdev); | ||
| 435 | |||
| 436 | return NULL; | ||
| 437 | } | ||
| 438 | |||
| 439 | static void radeon_audio_select_pin(struct drm_encoder *encoder) | ||
| 440 | { | ||
| 441 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 442 | |||
| 443 | if (radeon_encoder->audio && radeon_encoder->audio->select_pin) | ||
| 444 | radeon_encoder->audio->select_pin(encoder); | ||
| 445 | } | ||
| 446 | |||
| 447 | void radeon_audio_enable(struct radeon_device *rdev, | ||
| 448 | struct r600_audio_pin *pin, u8 enable_mask) | ||
| 449 | { | ||
| 450 | if (rdev->audio.funcs->enable) | ||
| 451 | rdev->audio.funcs->enable(rdev, pin, enable_mask); | ||
| 452 | } | ||
| 453 | |||
| 454 | void radeon_audio_detect(struct drm_connector *connector, | ||
| 455 | enum drm_connector_status status) | ||
| 456 | { | ||
| 457 | struct radeon_device *rdev; | ||
| 458 | struct radeon_encoder *radeon_encoder; | ||
| 459 | struct radeon_encoder_atom_dig *dig; | ||
| 460 | |||
| 461 | if (!connector || !connector->encoder) | ||
| 462 | return; | ||
| 463 | |||
| 464 | rdev = connector->encoder->dev->dev_private; | ||
| 465 | radeon_encoder = to_radeon_encoder(connector->encoder); | ||
| 466 | dig = radeon_encoder->enc_priv; | ||
| 467 | |||
| 468 | if (status == connector_status_connected) { | ||
| 469 | struct radeon_connector *radeon_connector; | ||
| 470 | int sink_type; | ||
| 471 | |||
| 472 | if (!drm_detect_monitor_audio(radeon_connector_edid(connector))) { | ||
| 473 | radeon_encoder->audio = NULL; | ||
| 474 | return; | ||
| 475 | } | ||
| 476 | |||
| 477 | radeon_connector = to_radeon_connector(connector); | ||
| 478 | sink_type = radeon_dp_getsinktype(radeon_connector); | ||
| 479 | |||
| 480 | if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort && | ||
| 481 | sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) | ||
| 482 | radeon_encoder->audio = rdev->audio.dp_funcs; | ||
| 483 | else | ||
| 484 | radeon_encoder->audio = rdev->audio.hdmi_funcs; | ||
| 485 | |||
| 486 | radeon_audio_write_speaker_allocation(connector->encoder); | ||
| 487 | radeon_audio_write_sad_regs(connector->encoder); | ||
| 488 | if (connector->encoder->crtc) | ||
| 489 | radeon_audio_write_latency_fields(connector->encoder, | ||
| 490 | &connector->encoder->crtc->mode); | ||
| 491 | radeon_audio_enable(rdev, dig->afmt->pin, 0xf); | ||
| 492 | } else { | ||
| 493 | radeon_audio_enable(rdev, dig->afmt->pin, 0); | ||
| 494 | } | ||
| 495 | } | ||
| 496 | |||
| 497 | void radeon_audio_fini(struct radeon_device *rdev) | ||
| 498 | { | ||
| 499 | int i; | ||
| 500 | |||
| 501 | if (!rdev->audio.enabled) | ||
| 502 | return; | ||
| 503 | |||
| 504 | for (i = 0; i < rdev->audio.num_pins; i++) | ||
| 505 | radeon_audio_enable(rdev, &rdev->audio.pin[i], false); | ||
| 506 | |||
| 507 | rdev->audio.enabled = false; | ||
| 508 | } | ||
| 509 | |||
| 510 | static void radeon_audio_set_dto(struct drm_encoder *encoder, unsigned int clock) | ||
| 511 | { | ||
| 512 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 513 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 514 | struct radeon_crtc *crtc = to_radeon_crtc(encoder->crtc); | ||
| 515 | |||
| 516 | if (radeon_encoder->audio && radeon_encoder->audio->set_dto) | ||
| 517 | radeon_encoder->audio->set_dto(rdev, crtc, clock); | ||
| 518 | } | ||
| 519 | |||
| 520 | static int radeon_audio_set_avi_packet(struct drm_encoder *encoder, | ||
| 521 | struct drm_display_mode *mode) | ||
| 522 | { | ||
| 523 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 524 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 525 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 526 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; | ||
| 527 | struct hdmi_avi_infoframe frame; | ||
| 528 | int err; | ||
| 529 | |||
| 530 | err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); | ||
| 531 | if (err < 0) { | ||
| 532 | DRM_ERROR("failed to setup AVI infoframe: %d\n", err); | ||
| 533 | return err; | ||
| 534 | } | ||
| 535 | |||
| 536 | err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); | ||
| 537 | if (err < 0) { | ||
| 538 | DRM_ERROR("failed to pack AVI infoframe: %d\n", err); | ||
| 539 | return err; | ||
| 540 | } | ||
| 541 | |||
| 542 | if (dig && dig->afmt && | ||
| 543 | radeon_encoder->audio && radeon_encoder->audio->set_avi_packet) | ||
| 544 | radeon_encoder->audio->set_avi_packet(rdev, dig->afmt->offset, | ||
| 545 | buffer, sizeof(buffer)); | ||
| 546 | |||
| 547 | return 0; | ||
| 548 | } | ||
| 549 | |||
| 550 | /* | ||
| 551 | * calculate CTS and N values if they are not found in the table | ||
| 552 | */ | ||
| 553 | static void radeon_audio_calc_cts(unsigned int clock, int *CTS, int *N, int freq) | ||
| 554 | { | ||
| 555 | int n, cts; | ||
| 556 | unsigned long div, mul; | ||
| 557 | |||
| 558 | /* Safe, but overly large values */ | ||
| 559 | n = 128 * freq; | ||
| 560 | cts = clock * 1000; | ||
| 561 | |||
| 562 | /* Smallest valid fraction */ | ||
| 563 | div = gcd(n, cts); | ||
| 564 | |||
| 565 | n /= div; | ||
| 566 | cts /= div; | ||
| 567 | |||
| 568 | /* | ||
| 569 | * The optimal N is 128*freq/1000. Calculate the closest larger | ||
| 570 | * value that doesn't truncate any bits. | ||
| 571 | */ | ||
| 572 | mul = ((128*freq/1000) + (n-1))/n; | ||
| 573 | |||
| 574 | n *= mul; | ||
| 575 | cts *= mul; | ||
| 576 | |||
| 577 | /* Check that we are in spec (not always possible) */ | ||
| 578 | if (n < (128*freq/1500)) | ||
| 579 | printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n"); | ||
| 580 | if (n > (128*freq/300)) | ||
| 581 | printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n"); | ||
| 582 | |||
| 583 | *N = n; | ||
| 584 | *CTS = cts; | ||
| 585 | |||
| 586 | DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n", | ||
| 587 | *N, *CTS, freq); | ||
| 588 | } | ||
| 589 | |||
| 590 | static const struct radeon_hdmi_acr* radeon_audio_acr(unsigned int clock) | ||
| 591 | { | ||
| 592 | static struct radeon_hdmi_acr res; | ||
| 593 | u8 i; | ||
| 594 | |||
| 595 | static const struct radeon_hdmi_acr hdmi_predefined_acr[] = { | ||
| 596 | /* 32kHz 44.1kHz 48kHz */ | ||
| 597 | /* Clock N CTS N CTS N CTS */ | ||
| 598 | { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */ | ||
| 599 | { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ | ||
| 600 | { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ | ||
| 601 | { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ | ||
| 602 | { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ | ||
| 603 | { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ | ||
| 604 | { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */ | ||
| 605 | { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ | ||
| 606 | { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */ | ||
| 607 | { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ | ||
| 608 | }; | ||
| 609 | |||
| 610 | /* Precalculated values for common clocks */ | ||
| 611 | for (i = 0; i < ARRAY_SIZE(hdmi_predefined_acr); i++) | ||
| 612 | if (hdmi_predefined_acr[i].clock == clock) | ||
| 613 | return &hdmi_predefined_acr[i]; | ||
| 614 | |||
| 615 | /* And odd clocks get manually calculated */ | ||
| 616 | radeon_audio_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000); | ||
| 617 | radeon_audio_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100); | ||
| 618 | radeon_audio_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000); | ||
| 619 | |||
| 620 | return &res; | ||
| 621 | } | ||
| 622 | |||
| 623 | /* | ||
| 624 | * update the N and CTS parameters for a given pixel clock rate | ||
| 625 | */ | ||
| 626 | static void radeon_audio_update_acr(struct drm_encoder *encoder, unsigned int clock) | ||
| 627 | { | ||
| 628 | const struct radeon_hdmi_acr *acr = radeon_audio_acr(clock); | ||
| 629 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 630 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 631 | |||
| 632 | if (!dig || !dig->afmt) | ||
| 633 | return; | ||
| 634 | |||
| 635 | if (radeon_encoder->audio && radeon_encoder->audio->update_acr) | ||
| 636 | radeon_encoder->audio->update_acr(encoder, dig->afmt->offset, acr); | ||
| 637 | } | ||
| 638 | |||
| 639 | static void radeon_audio_set_vbi_packet(struct drm_encoder *encoder) | ||
| 640 | { | ||
| 641 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 642 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 643 | |||
| 644 | if (!dig || !dig->afmt) | ||
| 645 | return; | ||
| 646 | |||
| 647 | if (radeon_encoder->audio && radeon_encoder->audio->set_vbi_packet) | ||
| 648 | radeon_encoder->audio->set_vbi_packet(encoder, dig->afmt->offset); | ||
| 649 | } | ||
| 650 | |||
| 651 | static void radeon_hdmi_set_color_depth(struct drm_encoder *encoder) | ||
| 652 | { | ||
| 653 | int bpc = 8; | ||
| 654 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 655 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 656 | |||
| 657 | if (!dig || !dig->afmt) | ||
| 658 | return; | ||
| 659 | |||
| 660 | if (encoder->crtc) { | ||
| 661 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 662 | bpc = radeon_crtc->bpc; | ||
| 663 | } | ||
| 664 | |||
| 665 | if (radeon_encoder->audio && radeon_encoder->audio->set_color_depth) | ||
| 666 | radeon_encoder->audio->set_color_depth(encoder, dig->afmt->offset, bpc); | ||
| 667 | } | ||
| 668 | |||
| 669 | static void radeon_audio_set_audio_packet(struct drm_encoder *encoder) | ||
| 670 | { | ||
| 671 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 672 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 673 | |||
| 674 | if (!dig || !dig->afmt) | ||
| 675 | return; | ||
| 676 | |||
| 677 | if (radeon_encoder->audio && radeon_encoder->audio->set_audio_packet) | ||
| 678 | radeon_encoder->audio->set_audio_packet(encoder, dig->afmt->offset); | ||
| 679 | } | ||
| 680 | |||
| 681 | static void radeon_audio_set_mute(struct drm_encoder *encoder, bool mute) | ||
| 682 | { | ||
| 683 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 684 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 685 | |||
| 686 | if (!dig || !dig->afmt) | ||
| 687 | return; | ||
| 688 | |||
| 689 | if (radeon_encoder->audio && radeon_encoder->audio->set_mute) | ||
| 690 | radeon_encoder->audio->set_mute(encoder, dig->afmt->offset, mute); | ||
| 691 | } | ||
| 692 | |||
| 693 | /* | ||
| 694 | * update the info frames with the data from the current display mode | ||
| 695 | */ | ||
| 696 | static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, | ||
| 697 | struct drm_display_mode *mode) | ||
| 698 | { | ||
| 699 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 700 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 701 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 702 | |||
| 703 | if (!dig || !dig->afmt) | ||
| 704 | return; | ||
| 705 | |||
| 706 | /* disable audio prior to setting up hw */ | ||
| 707 | dig->afmt->pin = radeon_audio_get_pin(encoder); | ||
| 708 | radeon_audio_enable(rdev, dig->afmt->pin, 0); | ||
| 709 | |||
| 710 | radeon_audio_set_dto(encoder, mode->clock); | ||
| 711 | radeon_audio_set_vbi_packet(encoder); | ||
| 712 | radeon_hdmi_set_color_depth(encoder); | ||
| 713 | radeon_audio_set_mute(encoder, false); | ||
| 714 | radeon_audio_update_acr(encoder, mode->clock); | ||
| 715 | radeon_audio_set_audio_packet(encoder); | ||
| 716 | radeon_audio_select_pin(encoder); | ||
| 717 | |||
| 718 | if (radeon_audio_set_avi_packet(encoder, mode) < 0) | ||
| 719 | return; | ||
| 720 | |||
| 721 | /* enable audio after to setting up hw */ | ||
| 722 | radeon_audio_enable(rdev, dig->afmt->pin, 0xf); | ||
| 723 | } | ||
| 724 | |||
| 725 | static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, | ||
| 726 | struct drm_display_mode *mode) | ||
| 727 | { | ||
| 728 | struct drm_device *dev = encoder->dev; | ||
| 729 | struct radeon_device *rdev = dev->dev_private; | ||
| 730 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 731 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
| 732 | |||
| 733 | if (!dig || !dig->afmt) | ||
| 734 | return; | ||
| 735 | |||
| 736 | /* disable audio prior to setting up hw */ | ||
| 737 | dig->afmt->pin = radeon_audio_get_pin(encoder); | ||
| 738 | radeon_audio_enable(rdev, dig->afmt->pin, 0); | ||
| 739 | |||
| 740 | radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10); | ||
| 741 | radeon_audio_set_audio_packet(encoder); | ||
| 742 | radeon_audio_select_pin(encoder); | ||
| 743 | |||
| 744 | if (radeon_audio_set_avi_packet(encoder, mode) < 0) | ||
| 745 | return; | ||
| 746 | |||
| 747 | /* enable audio after to setting up hw */ | ||
| 748 | radeon_audio_enable(rdev, dig->afmt->pin, 0xf); | ||
| 749 | } | ||
| 750 | |||
| 751 | void radeon_audio_mode_set(struct drm_encoder *encoder, | ||
| 752 | struct drm_display_mode *mode) | ||
| 753 | { | ||
| 754 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 755 | |||
| 756 | if (radeon_encoder->audio && radeon_encoder->audio->mode_set) | ||
| 757 | radeon_encoder->audio->mode_set(encoder, mode); | ||
| 758 | } | ||
| 759 | |||
| 760 | void radeon_audio_dpms(struct drm_encoder *encoder, int mode) | ||
| 761 | { | ||
| 762 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 763 | |||
| 764 | if (radeon_encoder->audio && radeon_encoder->audio->dpms) | ||
| 765 | radeon_encoder->audio->dpms(encoder, mode == DRM_MODE_DPMS_ON); | ||
| 766 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_audio.h b/drivers/gpu/drm/radeon/radeon_audio.h new file mode 100644 index 000000000000..c92d059ab204 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_audio.h | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2014 Advanced Micro Devices, Inc. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included in | ||
| 12 | * all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 21 | * | ||
| 22 | * Authors: Slava Grigorev <slava.grigorev@amd.com> | ||
| 23 | */ | ||
| 24 | |||
| 25 | #ifndef __RADEON_AUDIO_H__ | ||
| 26 | #define __RADEON_AUDIO_H__ | ||
| 27 | |||
| 28 | #include <linux/types.h> | ||
| 29 | |||
| 30 | #define RREG32_ENDPOINT(block, reg) \ | ||
| 31 | radeon_audio_endpoint_rreg(rdev, (block), (reg)) | ||
| 32 | #define WREG32_ENDPOINT(block, reg, v) \ | ||
| 33 | radeon_audio_endpoint_wreg(rdev, (block), (reg), (v)) | ||
| 34 | |||
| 35 | struct radeon_audio_basic_funcs | ||
| 36 | { | ||
| 37 | u32 (*endpoint_rreg)(struct radeon_device *rdev, u32 offset, u32 reg); | ||
| 38 | void (*endpoint_wreg)(struct radeon_device *rdev, | ||
| 39 | u32 offset, u32 reg, u32 v); | ||
| 40 | void (*enable)(struct radeon_device *rdev, | ||
| 41 | struct r600_audio_pin *pin, u8 enable_mask); | ||
| 42 | }; | ||
| 43 | |||
| 44 | struct radeon_audio_funcs | ||
| 45 | { | ||
| 46 | void (*select_pin)(struct drm_encoder *encoder); | ||
| 47 | struct r600_audio_pin* (*get_pin)(struct radeon_device *rdev); | ||
| 48 | void (*write_latency_fields)(struct drm_encoder *encoder, | ||
| 49 | struct drm_connector *connector, struct drm_display_mode *mode); | ||
| 50 | void (*write_sad_regs)(struct drm_encoder *encoder, | ||
| 51 | struct cea_sad *sads, int sad_count); | ||
| 52 | void (*write_speaker_allocation)(struct drm_encoder *encoder, | ||
| 53 | u8 *sadb, int sad_count); | ||
| 54 | void (*set_dto)(struct radeon_device *rdev, | ||
| 55 | struct radeon_crtc *crtc, unsigned int clock); | ||
| 56 | void (*update_acr)(struct drm_encoder *encoder, long offset, | ||
| 57 | const struct radeon_hdmi_acr *acr); | ||
| 58 | void (*set_vbi_packet)(struct drm_encoder *encoder, u32 offset); | ||
| 59 | void (*set_color_depth)(struct drm_encoder *encoder, u32 offset, int bpc); | ||
| 60 | void (*set_avi_packet)(struct radeon_device *rdev, u32 offset, | ||
| 61 | unsigned char *buffer, size_t size); | ||
| 62 | void (*set_audio_packet)(struct drm_encoder *encoder, u32 offset); | ||
| 63 | void (*set_mute)(struct drm_encoder *encoder, u32 offset, bool mute); | ||
| 64 | void (*mode_set)(struct drm_encoder *encoder, | ||
| 65 | struct drm_display_mode *mode); | ||
| 66 | void (*dpms)(struct drm_encoder *encoder, bool mode); | ||
| 67 | }; | ||
| 68 | |||
| 69 | int radeon_audio_init(struct radeon_device *rdev); | ||
| 70 | void radeon_audio_detect(struct drm_connector *connector, | ||
| 71 | enum drm_connector_status status); | ||
| 72 | u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev, | ||
| 73 | u32 offset, u32 reg); | ||
| 74 | void radeon_audio_endpoint_wreg(struct radeon_device *rdev, | ||
| 75 | u32 offset, u32 reg, u32 v); | ||
| 76 | struct r600_audio_pin *radeon_audio_get_pin(struct drm_encoder *encoder); | ||
| 77 | void radeon_audio_enable(struct radeon_device *rdev, | ||
| 78 | struct r600_audio_pin *pin, u8 enable_mask); | ||
| 79 | void radeon_audio_fini(struct radeon_device *rdev); | ||
| 80 | void radeon_audio_mode_set(struct drm_encoder *encoder, | ||
| 81 | struct drm_display_mode *mode); | ||
| 82 | void radeon_audio_dpms(struct drm_encoder *encoder, int mode); | ||
| 83 | |||
| 84 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 26baa9c05f6c..27def67cb6be 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <drm/drm_fb_helper.h> | 29 | #include <drm/drm_fb_helper.h> |
| 30 | #include <drm/radeon_drm.h> | 30 | #include <drm/radeon_drm.h> |
| 31 | #include "radeon.h" | 31 | #include "radeon.h" |
| 32 | #include "radeon_audio.h" | ||
| 32 | #include "atom.h" | 33 | #include "atom.h" |
| 33 | 34 | ||
| 34 | #include <linux/pm_runtime.h> | 35 | #include <linux/pm_runtime.h> |
| @@ -1332,6 +1333,9 @@ out: | |||
| 1332 | /* updated in get modes as well since we need to know if it's analog or digital */ | 1333 | /* updated in get modes as well since we need to know if it's analog or digital */ |
| 1333 | radeon_connector_update_scratch_regs(connector, ret); | 1334 | radeon_connector_update_scratch_regs(connector, ret); |
| 1334 | 1335 | ||
| 1336 | if (radeon_audio != 0) | ||
| 1337 | radeon_audio_detect(connector, ret); | ||
| 1338 | |||
| 1335 | exit: | 1339 | exit: |
| 1336 | pm_runtime_mark_last_busy(connector->dev->dev); | 1340 | pm_runtime_mark_last_busy(connector->dev->dev); |
| 1337 | pm_runtime_put_autosuspend(connector->dev->dev); | 1341 | pm_runtime_put_autosuspend(connector->dev->dev); |
| @@ -1654,6 +1658,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force) | |||
| 1654 | } | 1658 | } |
| 1655 | 1659 | ||
| 1656 | radeon_connector_update_scratch_regs(connector, ret); | 1660 | radeon_connector_update_scratch_regs(connector, ret); |
| 1661 | |||
| 1662 | if (radeon_audio != 0) | ||
| 1663 | radeon_audio_detect(connector, ret); | ||
| 1664 | |||
| 1657 | out: | 1665 | out: |
| 1658 | pm_runtime_mark_last_busy(connector->dev->dev); | 1666 | pm_runtime_mark_last_busy(connector->dev->dev); |
| 1659 | pm_runtime_put_autosuspend(connector->dev->dev); | 1667 | pm_runtime_put_autosuspend(connector->dev->dev); |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 4f50fb0e3d93..5d684beb48d3 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -88,9 +88,10 @@ | |||
| 88 | * 2.39.0 - Add INFO query for number of active CUs | 88 | * 2.39.0 - Add INFO query for number of active CUs |
| 89 | * 2.40.0 - Add RADEON_GEM_GTT_WC/UC, flush HDP cache before submitting | 89 | * 2.40.0 - Add RADEON_GEM_GTT_WC/UC, flush HDP cache before submitting |
| 90 | * CS to GPU on >= r600 | 90 | * CS to GPU on >= r600 |
| 91 | * 2.41.0 - evergreen/cayman: Add SET_BASE/DRAW_INDIRECT command parsing support | ||
| 91 | */ | 92 | */ |
| 92 | #define KMS_DRIVER_MAJOR 2 | 93 | #define KMS_DRIVER_MAJOR 2 |
| 93 | #define KMS_DRIVER_MINOR 40 | 94 | #define KMS_DRIVER_MINOR 41 |
| 94 | #define KMS_DRIVER_PATCHLEVEL 0 | 95 | #define KMS_DRIVER_PATCHLEVEL 0 |
| 95 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); | 96 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); |
| 96 | int radeon_driver_unload_kms(struct drm_device *dev); | 97 | int radeon_driver_unload_kms(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 3000bc4c136b..ea276ff6d174 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
| @@ -428,16 +428,6 @@ void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state) | |||
| 428 | fb_set_suspend(rdev->mode_info.rfbdev->helper.fbdev, state); | 428 | fb_set_suspend(rdev->mode_info.rfbdev->helper.fbdev, state); |
| 429 | } | 429 | } |
| 430 | 430 | ||
| 431 | int radeon_fbdev_total_size(struct radeon_device *rdev) | ||
| 432 | { | ||
| 433 | struct radeon_bo *robj; | ||
| 434 | int size = 0; | ||
| 435 | |||
| 436 | robj = gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj); | ||
| 437 | size += radeon_bo_size(robj); | ||
| 438 | return size; | ||
| 439 | } | ||
| 440 | |||
| 441 | bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj) | 431 | bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj) |
| 442 | { | 432 | { |
| 443 | if (robj == gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj)) | 433 | if (robj == gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj)) |
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index add622008407..9590bcd321c0 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c | |||
| @@ -1048,11 +1048,6 @@ struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, | |||
| 1048 | return NULL; | 1048 | return NULL; |
| 1049 | } | 1049 | } |
| 1050 | 1050 | ||
| 1051 | struct drm_encoder *radeon_best_encoder(struct drm_connector *connector) | ||
| 1052 | { | ||
| 1053 | return NULL; | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus, | 1051 | void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus, |
| 1057 | u8 slave_addr, | 1052 | u8 slave_addr, |
| 1058 | u8 addr, | 1053 | u8 addr, |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 390db897f322..920a8be8abad 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
| @@ -449,6 +449,7 @@ struct radeon_encoder { | |||
| 449 | int audio_polling_active; | 449 | int audio_polling_active; |
| 450 | bool is_ext_encoder; | 450 | bool is_ext_encoder; |
| 451 | u16 caps; | 451 | u16 caps; |
| 452 | struct radeon_audio_funcs *audio; | ||
| 452 | }; | 453 | }; |
| 453 | 454 | ||
| 454 | struct radeon_connector_atom_dig { | 455 | struct radeon_connector_atom_dig { |
| @@ -745,8 +746,6 @@ extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connec | |||
| 745 | extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); | 746 | extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); |
| 746 | extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux); | 747 | extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux); |
| 747 | 748 | ||
| 748 | extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); | ||
| 749 | |||
| 750 | extern bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev, | 749 | extern bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev, |
| 751 | struct radeon_atom_ss *ss, | 750 | struct radeon_atom_ss *ss, |
| 752 | int id); | 751 | int id); |
| @@ -925,7 +924,6 @@ void dce8_program_fmt(struct drm_encoder *encoder); | |||
| 925 | int radeon_fbdev_init(struct radeon_device *rdev); | 924 | int radeon_fbdev_init(struct radeon_device *rdev); |
| 926 | void radeon_fbdev_fini(struct radeon_device *rdev); | 925 | void radeon_fbdev_fini(struct radeon_device *rdev); |
| 927 | void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state); | 926 | void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state); |
| 928 | int radeon_fbdev_total_size(struct radeon_device *rdev); | ||
| 929 | bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj); | 927 | bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj); |
| 930 | 928 | ||
| 931 | void radeon_fb_output_poll_changed(struct radeon_device *rdev); | 929 | void radeon_fb_output_poll_changed(struct radeon_device *rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 86fc56434b28..1d955776f4d0 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
| @@ -576,12 +576,6 @@ int radeon_bo_list_validate(struct radeon_device *rdev, | |||
| 576 | return 0; | 576 | return 0; |
| 577 | } | 577 | } |
| 578 | 578 | ||
| 579 | int radeon_bo_fbdev_mmap(struct radeon_bo *bo, | ||
| 580 | struct vm_area_struct *vma) | ||
| 581 | { | ||
| 582 | return ttm_fbdev_mmap(vma, &bo->tbo); | ||
| 583 | } | ||
| 584 | |||
| 585 | int radeon_bo_get_surface_reg(struct radeon_bo *bo) | 579 | int radeon_bo_get_surface_reg(struct radeon_bo *bo) |
| 586 | { | 580 | { |
| 587 | struct radeon_device *rdev = bo->rdev; | 581 | struct radeon_device *rdev = bo->rdev; |
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 3b0b377f76cb..d8d295ee7c12 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h | |||
| @@ -143,8 +143,6 @@ extern void radeon_bo_fini(struct radeon_device *rdev); | |||
| 143 | extern int radeon_bo_list_validate(struct radeon_device *rdev, | 143 | extern int radeon_bo_list_validate(struct radeon_device *rdev, |
| 144 | struct ww_acquire_ctx *ticket, | 144 | struct ww_acquire_ctx *ticket, |
| 145 | struct list_head *head, int ring); | 145 | struct list_head *head, int ring); |
| 146 | extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo, | ||
| 147 | struct vm_area_struct *vma); | ||
| 148 | extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo, | 146 | extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo, |
| 149 | u32 tiling_flags, u32 pitch); | 147 | u32 tiling_flags, u32 pitch); |
| 150 | extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo, | 148 | extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo, |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index f7da8fe96a66..91e1bd246cad 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include "radeon.h" | 24 | #include "radeon.h" |
| 25 | #include "avivod.h" | 25 | #include "avivod.h" |
| 26 | #include "atom.h" | 26 | #include "atom.h" |
| 27 | #include "r600_dpm.h" | ||
| 27 | #include <linux/power_supply.h> | 28 | #include <linux/power_supply.h> |
| 28 | #include <linux/hwmon.h> | 29 | #include <linux/hwmon.h> |
| 29 | #include <linux/hwmon-sysfs.h> | 30 | #include <linux/hwmon-sysfs.h> |
| @@ -554,6 +555,96 @@ fail: | |||
| 554 | return count; | 555 | return count; |
| 555 | } | 556 | } |
| 556 | 557 | ||
| 558 | static ssize_t radeon_hwmon_get_pwm1_enable(struct device *dev, | ||
| 559 | struct device_attribute *attr, | ||
| 560 | char *buf) | ||
| 561 | { | ||
| 562 | struct radeon_device *rdev = dev_get_drvdata(dev); | ||
| 563 | u32 pwm_mode = 0; | ||
| 564 | |||
| 565 | if (rdev->asic->dpm.fan_ctrl_get_mode) | ||
| 566 | pwm_mode = rdev->asic->dpm.fan_ctrl_get_mode(rdev); | ||
| 567 | |||
| 568 | /* never 0 (full-speed), fuse or smc-controlled always */ | ||
| 569 | return sprintf(buf, "%i\n", pwm_mode == FDO_PWM_MODE_STATIC ? 1 : 2); | ||
| 570 | } | ||
| 571 | |||
| 572 | static ssize_t radeon_hwmon_set_pwm1_enable(struct device *dev, | ||
| 573 | struct device_attribute *attr, | ||
| 574 | const char *buf, | ||
| 575 | size_t count) | ||
| 576 | { | ||
| 577 | struct radeon_device *rdev = dev_get_drvdata(dev); | ||
| 578 | int err; | ||
| 579 | int value; | ||
| 580 | |||
| 581 | if(!rdev->asic->dpm.fan_ctrl_set_mode) | ||
| 582 | return -EINVAL; | ||
| 583 | |||
| 584 | err = kstrtoint(buf, 10, &value); | ||
| 585 | if (err) | ||
| 586 | return err; | ||
| 587 | |||
| 588 | switch(value) { | ||
| 589 | case 1: /* manual, percent-based */ | ||
| 590 | rdev->asic->dpm.fan_ctrl_set_mode(rdev, FDO_PWM_MODE_STATIC); | ||
| 591 | break; | ||
| 592 | default: /* disable */ | ||
| 593 | rdev->asic->dpm.fan_ctrl_set_mode(rdev, 0); | ||
| 594 | break; | ||
| 595 | } | ||
| 596 | |||
| 597 | return count; | ||
| 598 | } | ||
| 599 | |||
| 600 | static ssize_t radeon_hwmon_get_pwm1_min(struct device *dev, | ||
| 601 | struct device_attribute *attr, | ||
| 602 | char *buf) | ||
| 603 | { | ||
| 604 | return sprintf(buf, "%i\n", 0); | ||
| 605 | } | ||
| 606 | |||
| 607 | static ssize_t radeon_hwmon_get_pwm1_max(struct device *dev, | ||
| 608 | struct device_attribute *attr, | ||
| 609 | char *buf) | ||
| 610 | { | ||
| 611 | return sprintf(buf, "%i\n", 100); /* pwm uses percent-based fan-control */ | ||
| 612 | } | ||
| 613 | |||
| 614 | static ssize_t radeon_hwmon_set_pwm1(struct device *dev, | ||
| 615 | struct device_attribute *attr, | ||
| 616 | const char *buf, size_t count) | ||
| 617 | { | ||
| 618 | struct radeon_device *rdev = dev_get_drvdata(dev); | ||
| 619 | int err; | ||
| 620 | u32 value; | ||
| 621 | |||
| 622 | err = kstrtou32(buf, 10, &value); | ||
| 623 | if (err) | ||
| 624 | return err; | ||
| 625 | |||
| 626 | err = rdev->asic->dpm.set_fan_speed_percent(rdev, value); | ||
| 627 | if (err) | ||
| 628 | return err; | ||
| 629 | |||
| 630 | return count; | ||
| 631 | } | ||
| 632 | |||
| 633 | static ssize_t radeon_hwmon_get_pwm1(struct device *dev, | ||
| 634 | struct device_attribute *attr, | ||
| 635 | char *buf) | ||
| 636 | { | ||
| 637 | struct radeon_device *rdev = dev_get_drvdata(dev); | ||
| 638 | int err; | ||
| 639 | u32 speed; | ||
| 640 | |||
| 641 | err = rdev->asic->dpm.get_fan_speed_percent(rdev, &speed); | ||
| 642 | if (err) | ||
| 643 | return err; | ||
| 644 | |||
| 645 | return sprintf(buf, "%i\n", speed); | ||
| 646 | } | ||
| 647 | |||
| 557 | static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile); | 648 | static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile); |
| 558 | static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method); | 649 | static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method); |
| 559 | static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, radeon_get_dpm_state, radeon_set_dpm_state); | 650 | 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, | |||
| 601 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, radeon_hwmon_show_temp, NULL, 0); | 692 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, radeon_hwmon_show_temp, NULL, 0); |
| 602 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 0); | 693 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 0); |
| 603 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 1); | 694 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 1); |
| 695 | static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, radeon_hwmon_get_pwm1, radeon_hwmon_set_pwm1, 0); | ||
| 696 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, radeon_hwmon_get_pwm1_enable, radeon_hwmon_set_pwm1_enable, 0); | ||
| 697 | static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, radeon_hwmon_get_pwm1_min, NULL, 0); | ||
| 698 | static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, radeon_hwmon_get_pwm1_max, NULL, 0); | ||
| 699 | |||
| 604 | 700 | ||
| 605 | static struct attribute *hwmon_attributes[] = { | 701 | static struct attribute *hwmon_attributes[] = { |
| 606 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 702 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
| 607 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | 703 | &sensor_dev_attr_temp1_crit.dev_attr.attr, |
| 608 | &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, | 704 | &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, |
| 705 | &sensor_dev_attr_pwm1.dev_attr.attr, | ||
| 706 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
| 707 | &sensor_dev_attr_pwm1_min.dev_attr.attr, | ||
| 708 | &sensor_dev_attr_pwm1_max.dev_attr.attr, | ||
| 609 | NULL | 709 | NULL |
| 610 | }; | 710 | }; |
| 611 | 711 | ||
| @@ -614,6 +714,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, | |||
| 614 | { | 714 | { |
| 615 | struct device *dev = container_of(kobj, struct device, kobj); | 715 | struct device *dev = container_of(kobj, struct device, kobj); |
| 616 | struct radeon_device *rdev = dev_get_drvdata(dev); | 716 | struct radeon_device *rdev = dev_get_drvdata(dev); |
| 717 | umode_t effective_mode = attr->mode; | ||
| 617 | 718 | ||
| 618 | /* Skip limit attributes if DPM is not enabled */ | 719 | /* Skip limit attributes if DPM is not enabled */ |
| 619 | if (rdev->pm.pm_method != PM_METHOD_DPM && | 720 | if (rdev->pm.pm_method != PM_METHOD_DPM && |
| @@ -621,7 +722,35 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, | |||
| 621 | attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr)) | 722 | attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr)) |
| 622 | return 0; | 723 | return 0; |
| 623 | 724 | ||
| 624 | return attr->mode; | 725 | /* Skip fan attributes if fan is not present */ |
| 726 | if (rdev->pm.no_fan && | ||
| 727 | (attr == &sensor_dev_attr_pwm1.dev_attr.attr || | ||
| 728 | attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || | ||
| 729 | attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || | ||
| 730 | attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) | ||
| 731 | return 0; | ||
| 732 | |||
| 733 | /* mask fan attributes if we have no bindings for this asic to expose */ | ||
| 734 | if ((!rdev->asic->dpm.get_fan_speed_percent && | ||
| 735 | attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */ | ||
| 736 | (!rdev->asic->dpm.fan_ctrl_get_mode && | ||
| 737 | attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't query state */ | ||
| 738 | effective_mode &= ~S_IRUGO; | ||
| 739 | |||
| 740 | if ((!rdev->asic->dpm.set_fan_speed_percent && | ||
| 741 | attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't manage fan */ | ||
| 742 | (!rdev->asic->dpm.fan_ctrl_set_mode && | ||
| 743 | attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */ | ||
| 744 | effective_mode &= ~S_IWUSR; | ||
| 745 | |||
| 746 | /* hide max/min values if we can't both query and manage the fan */ | ||
| 747 | if ((!rdev->asic->dpm.set_fan_speed_percent && | ||
| 748 | !rdev->asic->dpm.get_fan_speed_percent) && | ||
| 749 | (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || | ||
| 750 | attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) | ||
| 751 | return 0; | ||
| 752 | |||
| 753 | return effective_mode; | ||
| 625 | } | 754 | } |
| 626 | 755 | ||
| 627 | static const struct attribute_group hwmon_attrgroup = { | 756 | static const struct attribute_group hwmon_attrgroup = { |
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 9acb1c3c005b..68f154a451c0 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <drm/drmP.h> | 38 | #include <drm/drmP.h> |
| 39 | #include "radeon.h" | 39 | #include "radeon.h" |
| 40 | #include "radeon_asic.h" | 40 | #include "radeon_asic.h" |
| 41 | #include "radeon_audio.h" | ||
| 41 | #include "atom.h" | 42 | #include "atom.h" |
| 42 | #include "rs600d.h" | 43 | #include "rs600d.h" |
| 43 | 44 | ||
| @@ -1012,7 +1013,7 @@ static int rs600_startup(struct radeon_device *rdev) | |||
| 1012 | return r; | 1013 | return r; |
| 1013 | } | 1014 | } |
| 1014 | 1015 | ||
| 1015 | r = r600_audio_init(rdev); | 1016 | r = radeon_audio_init(rdev); |
| 1016 | if (r) { | 1017 | if (r) { |
| 1017 | dev_err(rdev->dev, "failed initializing audio\n"); | 1018 | dev_err(rdev->dev, "failed initializing audio\n"); |
| 1018 | return r; | 1019 | return r; |
| @@ -1053,7 +1054,7 @@ int rs600_resume(struct radeon_device *rdev) | |||
| 1053 | int rs600_suspend(struct radeon_device *rdev) | 1054 | int rs600_suspend(struct radeon_device *rdev) |
| 1054 | { | 1055 | { |
| 1055 | radeon_pm_suspend(rdev); | 1056 | radeon_pm_suspend(rdev); |
| 1056 | r600_audio_fini(rdev); | 1057 | radeon_audio_fini(rdev); |
| 1057 | r100_cp_disable(rdev); | 1058 | r100_cp_disable(rdev); |
| 1058 | radeon_wb_disable(rdev); | 1059 | radeon_wb_disable(rdev); |
| 1059 | rs600_irq_disable(rdev); | 1060 | rs600_irq_disable(rdev); |
| @@ -1064,7 +1065,7 @@ int rs600_suspend(struct radeon_device *rdev) | |||
| 1064 | void rs600_fini(struct radeon_device *rdev) | 1065 | void rs600_fini(struct radeon_device *rdev) |
| 1065 | { | 1066 | { |
| 1066 | radeon_pm_fini(rdev); | 1067 | radeon_pm_fini(rdev); |
| 1067 | r600_audio_fini(rdev); | 1068 | radeon_audio_fini(rdev); |
| 1068 | r100_cp_fini(rdev); | 1069 | r100_cp_fini(rdev); |
| 1069 | radeon_wb_fini(rdev); | 1070 | radeon_wb_fini(rdev); |
| 1070 | radeon_ib_pool_fini(rdev); | 1071 | radeon_ib_pool_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 0a2d36e81108..516ca27cfa12 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <drm/drmP.h> | 28 | #include <drm/drmP.h> |
| 29 | #include "radeon.h" | 29 | #include "radeon.h" |
| 30 | #include "radeon_asic.h" | 30 | #include "radeon_asic.h" |
| 31 | #include "radeon_audio.h" | ||
| 31 | #include "atom.h" | 32 | #include "atom.h" |
| 32 | #include "rs690d.h" | 33 | #include "rs690d.h" |
| 33 | 34 | ||
| @@ -729,7 +730,7 @@ static int rs690_startup(struct radeon_device *rdev) | |||
| 729 | return r; | 730 | return r; |
| 730 | } | 731 | } |
| 731 | 732 | ||
| 732 | r = r600_audio_init(rdev); | 733 | r = radeon_audio_init(rdev); |
| 733 | if (r) { | 734 | if (r) { |
| 734 | dev_err(rdev->dev, "failed initializing audio\n"); | 735 | dev_err(rdev->dev, "failed initializing audio\n"); |
| 735 | return r; | 736 | return r; |
| @@ -770,7 +771,7 @@ int rs690_resume(struct radeon_device *rdev) | |||
| 770 | int rs690_suspend(struct radeon_device *rdev) | 771 | int rs690_suspend(struct radeon_device *rdev) |
| 771 | { | 772 | { |
| 772 | radeon_pm_suspend(rdev); | 773 | radeon_pm_suspend(rdev); |
| 773 | r600_audio_fini(rdev); | 774 | radeon_audio_fini(rdev); |
| 774 | r100_cp_disable(rdev); | 775 | r100_cp_disable(rdev); |
| 775 | radeon_wb_disable(rdev); | 776 | radeon_wb_disable(rdev); |
| 776 | rs600_irq_disable(rdev); | 777 | rs600_irq_disable(rdev); |
| @@ -781,7 +782,7 @@ int rs690_suspend(struct radeon_device *rdev) | |||
| 781 | void rs690_fini(struct radeon_device *rdev) | 782 | void rs690_fini(struct radeon_device *rdev) |
| 782 | { | 783 | { |
| 783 | radeon_pm_fini(rdev); | 784 | radeon_pm_fini(rdev); |
| 784 | r600_audio_fini(rdev); | 785 | radeon_audio_fini(rdev); |
| 785 | r100_cp_fini(rdev); | 786 | r100_cp_fini(rdev); |
| 786 | radeon_wb_fini(rdev); | 787 | radeon_wb_fini(rdev); |
| 787 | radeon_ib_pool_fini(rdev); | 788 | radeon_ib_pool_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 372016e266d0..01ee96acb398 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <drm/drmP.h> | 30 | #include <drm/drmP.h> |
| 31 | #include "radeon.h" | 31 | #include "radeon.h" |
| 32 | #include "radeon_asic.h" | 32 | #include "radeon_asic.h" |
| 33 | #include "radeon_audio.h" | ||
| 33 | #include <drm/radeon_drm.h> | 34 | #include <drm/radeon_drm.h> |
| 34 | #include "rv770d.h" | 35 | #include "rv770d.h" |
| 35 | #include "atom.h" | 36 | #include "atom.h" |
| @@ -1788,7 +1789,7 @@ static int rv770_startup(struct radeon_device *rdev) | |||
| 1788 | return r; | 1789 | return r; |
| 1789 | } | 1790 | } |
| 1790 | 1791 | ||
| 1791 | r = r600_audio_init(rdev); | 1792 | r = radeon_audio_init(rdev); |
| 1792 | if (r) { | 1793 | if (r) { |
| 1793 | DRM_ERROR("radeon: audio init failed\n"); | 1794 | DRM_ERROR("radeon: audio init failed\n"); |
| 1794 | return r; | 1795 | return r; |
| @@ -1829,7 +1830,7 @@ int rv770_resume(struct radeon_device *rdev) | |||
| 1829 | int rv770_suspend(struct radeon_device *rdev) | 1830 | int rv770_suspend(struct radeon_device *rdev) |
| 1830 | { | 1831 | { |
| 1831 | radeon_pm_suspend(rdev); | 1832 | radeon_pm_suspend(rdev); |
| 1832 | r600_audio_fini(rdev); | 1833 | radeon_audio_fini(rdev); |
| 1833 | uvd_v1_0_fini(rdev); | 1834 | uvd_v1_0_fini(rdev); |
| 1834 | radeon_uvd_suspend(rdev); | 1835 | radeon_uvd_suspend(rdev); |
| 1835 | r700_cp_stop(rdev); | 1836 | r700_cp_stop(rdev); |
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index 755a8f96fe46..306732641b23 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c | |||
| @@ -231,6 +231,7 @@ u8 rv770_get_seq_value(struct radeon_device *rdev, | |||
| 231 | MC_CG_SEQ_DRAMCONF_S0 : MC_CG_SEQ_DRAMCONF_S1; | 231 | MC_CG_SEQ_DRAMCONF_S0 : MC_CG_SEQ_DRAMCONF_S1; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | #if 0 | ||
| 234 | int rv770_read_smc_soft_register(struct radeon_device *rdev, | 235 | int rv770_read_smc_soft_register(struct radeon_device *rdev, |
| 235 | u16 reg_offset, u32 *value) | 236 | u16 reg_offset, u32 *value) |
| 236 | { | 237 | { |
| @@ -240,6 +241,7 @@ int rv770_read_smc_soft_register(struct radeon_device *rdev, | |||
| 240 | pi->soft_regs_start + reg_offset, | 241 | pi->soft_regs_start + reg_offset, |
| 241 | value, pi->sram_end); | 242 | value, pi->sram_end); |
| 242 | } | 243 | } |
| 244 | #endif | ||
| 243 | 245 | ||
| 244 | int rv770_write_smc_soft_register(struct radeon_device *rdev, | 246 | int rv770_write_smc_soft_register(struct radeon_device *rdev, |
| 245 | u16 reg_offset, u32 value) | 247 | u16 reg_offset, u32 value) |
| @@ -2075,6 +2077,7 @@ int rv770_dpm_set_power_state(struct radeon_device *rdev) | |||
| 2075 | return 0; | 2077 | return 0; |
| 2076 | } | 2078 | } |
| 2077 | 2079 | ||
| 2080 | #if 0 | ||
| 2078 | void rv770_dpm_reset_asic(struct radeon_device *rdev) | 2081 | void rv770_dpm_reset_asic(struct radeon_device *rdev) |
| 2079 | { | 2082 | { |
| 2080 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | 2083 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); |
| @@ -2087,6 +2090,7 @@ void rv770_dpm_reset_asic(struct radeon_device *rdev) | |||
| 2087 | if (pi->dcodt) | 2090 | if (pi->dcodt) |
| 2088 | rv770_program_dcodt_after_state_switch(rdev, boot_ps, boot_ps); | 2091 | rv770_program_dcodt_after_state_switch(rdev, boot_ps, boot_ps); |
| 2089 | } | 2092 | } |
| 2093 | #endif | ||
| 2090 | 2094 | ||
| 2091 | void rv770_dpm_setup_asic(struct radeon_device *rdev) | 2095 | void rv770_dpm_setup_asic(struct radeon_device *rdev) |
| 2092 | { | 2096 | { |
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.h b/drivers/gpu/drm/radeon/rv770_dpm.h index f776634840c9..d12beab7f3e6 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.h +++ b/drivers/gpu/drm/radeon/rv770_dpm.h | |||
| @@ -278,8 +278,6 @@ void rv770_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev, | |||
| 278 | void rv770_get_engine_memory_ss(struct radeon_device *rdev); | 278 | void rv770_get_engine_memory_ss(struct radeon_device *rdev); |
| 279 | 279 | ||
| 280 | /* smc */ | 280 | /* smc */ |
| 281 | int rv770_read_smc_soft_register(struct radeon_device *rdev, | ||
| 282 | u16 reg_offset, u32 *value); | ||
| 283 | int rv770_write_smc_soft_register(struct radeon_device *rdev, | 281 | int rv770_write_smc_soft_register(struct radeon_device *rdev, |
| 284 | u16 reg_offset, u32 value); | 282 | u16 reg_offset, u32 value); |
| 285 | 283 | ||
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 5d89b874a1a2..73107fe9e46f 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <drm/drmP.h> | 27 | #include <drm/drmP.h> |
| 28 | #include "radeon.h" | 28 | #include "radeon.h" |
| 29 | #include "radeon_asic.h" | 29 | #include "radeon_asic.h" |
| 30 | #include "radeon_audio.h" | ||
| 30 | #include <drm/radeon_drm.h> | 31 | #include <drm/radeon_drm.h> |
| 31 | #include "sid.h" | 32 | #include "sid.h" |
| 32 | #include "atom.h" | 33 | #include "atom.h" |
| @@ -6869,7 +6870,7 @@ static int si_startup(struct radeon_device *rdev) | |||
| 6869 | return r; | 6870 | return r; |
| 6870 | } | 6871 | } |
| 6871 | 6872 | ||
| 6872 | r = dce6_audio_init(rdev); | 6873 | r = radeon_audio_init(rdev); |
| 6873 | if (r) | 6874 | if (r) |
| 6874 | return r; | 6875 | return r; |
| 6875 | 6876 | ||
| @@ -6908,7 +6909,7 @@ int si_resume(struct radeon_device *rdev) | |||
| 6908 | int si_suspend(struct radeon_device *rdev) | 6909 | int si_suspend(struct radeon_device *rdev) |
| 6909 | { | 6910 | { |
| 6910 | radeon_pm_suspend(rdev); | 6911 | radeon_pm_suspend(rdev); |
| 6911 | dce6_audio_fini(rdev); | 6912 | radeon_audio_fini(rdev); |
| 6912 | radeon_vm_manager_fini(rdev); | 6913 | radeon_vm_manager_fini(rdev); |
| 6913 | si_cp_enable(rdev, false); | 6914 | si_cp_enable(rdev, false); |
| 6914 | cayman_dma_stop(rdev); | 6915 | cayman_dma_stop(rdev); |
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index eff8a6444956..7be11651b7e6 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c | |||
| @@ -1756,6 +1756,9 @@ static int si_calculate_sclk_params(struct radeon_device *rdev, | |||
| 1756 | u32 engine_clock, | 1756 | u32 engine_clock, |
| 1757 | SISLANDS_SMC_SCLK_VALUE *sclk); | 1757 | SISLANDS_SMC_SCLK_VALUE *sclk); |
| 1758 | 1758 | ||
| 1759 | static void si_thermal_start_smc_fan_control(struct radeon_device *rdev); | ||
| 1760 | static void si_fan_ctrl_set_default_mode(struct radeon_device *rdev); | ||
| 1761 | |||
| 1759 | static struct si_power_info *si_get_pi(struct radeon_device *rdev) | 1762 | static struct si_power_info *si_get_pi(struct radeon_device *rdev) |
| 1760 | { | 1763 | { |
| 1761 | struct si_power_info *pi = rdev->pm.dpm.priv; | 1764 | struct si_power_info *pi = rdev->pm.dpm.priv; |
| @@ -3359,11 +3362,13 @@ int si_dpm_force_performance_level(struct radeon_device *rdev, | |||
| 3359 | return 0; | 3362 | return 0; |
| 3360 | } | 3363 | } |
| 3361 | 3364 | ||
| 3365 | #if 0 | ||
| 3362 | static int si_set_boot_state(struct radeon_device *rdev) | 3366 | static int si_set_boot_state(struct radeon_device *rdev) |
| 3363 | { | 3367 | { |
| 3364 | return (si_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ? | 3368 | return (si_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ? |
| 3365 | 0 : -EINVAL; | 3369 | 0 : -EINVAL; |
| 3366 | } | 3370 | } |
| 3371 | #endif | ||
| 3367 | 3372 | ||
| 3368 | static int si_set_sw_state(struct radeon_device *rdev) | 3373 | static int si_set_sw_state(struct radeon_device *rdev) |
| 3369 | { | 3374 | { |
| @@ -5973,6 +5978,10 @@ static int si_thermal_setup_fan_table(struct radeon_device *rdev) | |||
| 5973 | slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); | 5978 | slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); |
| 5974 | slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); | 5979 | slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); |
| 5975 | 5980 | ||
| 5981 | fan_table.temp_min = cpu_to_be16((50 + rdev->pm.dpm.fan.t_min) / 100); | ||
| 5982 | fan_table.temp_med = cpu_to_be16((50 + rdev->pm.dpm.fan.t_med) / 100); | ||
| 5983 | fan_table.temp_max = cpu_to_be16((50 + rdev->pm.dpm.fan.t_max) / 100); | ||
| 5984 | |||
| 5976 | fan_table.slope1 = cpu_to_be16(slope1); | 5985 | fan_table.slope1 = cpu_to_be16(slope1); |
| 5977 | fan_table.slope2 = cpu_to_be16(slope2); | 5986 | fan_table.slope2 = cpu_to_be16(slope2); |
| 5978 | 5987 | ||
| @@ -6012,29 +6021,35 @@ static int si_thermal_setup_fan_table(struct radeon_device *rdev) | |||
| 6012 | 6021 | ||
| 6013 | static int si_fan_ctrl_start_smc_fan_control(struct radeon_device *rdev) | 6022 | static int si_fan_ctrl_start_smc_fan_control(struct radeon_device *rdev) |
| 6014 | { | 6023 | { |
| 6024 | struct si_power_info *si_pi = si_get_pi(rdev); | ||
| 6015 | PPSMC_Result ret; | 6025 | PPSMC_Result ret; |
| 6016 | 6026 | ||
| 6017 | ret = si_send_msg_to_smc(rdev, PPSMC_StartFanControl); | 6027 | ret = si_send_msg_to_smc(rdev, PPSMC_StartFanControl); |
| 6018 | if (ret == PPSMC_Result_OK) | 6028 | if (ret == PPSMC_Result_OK) { |
| 6029 | si_pi->fan_is_controlled_by_smc = true; | ||
| 6019 | return 0; | 6030 | return 0; |
| 6020 | else | 6031 | } else { |
| 6021 | return -EINVAL; | 6032 | return -EINVAL; |
| 6033 | } | ||
| 6022 | } | 6034 | } |
| 6023 | 6035 | ||
| 6024 | static int si_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev) | 6036 | static int si_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev) |
| 6025 | { | 6037 | { |
| 6038 | struct si_power_info *si_pi = si_get_pi(rdev); | ||
| 6026 | PPSMC_Result ret; | 6039 | PPSMC_Result ret; |
| 6027 | 6040 | ||
| 6028 | ret = si_send_msg_to_smc(rdev, PPSMC_StopFanControl); | 6041 | ret = si_send_msg_to_smc(rdev, PPSMC_StopFanControl); |
| 6029 | if (ret == PPSMC_Result_OK) | 6042 | |
| 6043 | if (ret == PPSMC_Result_OK) { | ||
| 6044 | si_pi->fan_is_controlled_by_smc = false; | ||
| 6030 | return 0; | 6045 | return 0; |
| 6031 | else | 6046 | } else { |
| 6032 | return -EINVAL; | 6047 | return -EINVAL; |
| 6048 | } | ||
| 6033 | } | 6049 | } |
| 6034 | 6050 | ||
| 6035 | #if 0 | 6051 | int si_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, |
| 6036 | static int si_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, | 6052 | u32 *speed) |
| 6037 | u32 *speed) | ||
| 6038 | { | 6053 | { |
| 6039 | u32 duty, duty100; | 6054 | u32 duty, duty100; |
| 6040 | u64 tmp64; | 6055 | u64 tmp64; |
| @@ -6058,9 +6073,10 @@ static int si_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, | |||
| 6058 | return 0; | 6073 | return 0; |
| 6059 | } | 6074 | } |
| 6060 | 6075 | ||
| 6061 | static int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, | 6076 | int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, |
| 6062 | u32 speed) | 6077 | u32 speed) |
| 6063 | { | 6078 | { |
| 6079 | struct si_power_info *si_pi = si_get_pi(rdev); | ||
| 6064 | u32 tmp; | 6080 | u32 tmp; |
| 6065 | u32 duty, duty100; | 6081 | u32 duty, duty100; |
| 6066 | u64 tmp64; | 6082 | u64 tmp64; |
| @@ -6068,11 +6084,11 @@ static int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, | |||
| 6068 | if (rdev->pm.no_fan) | 6084 | if (rdev->pm.no_fan) |
| 6069 | return -ENOENT; | 6085 | return -ENOENT; |
| 6070 | 6086 | ||
| 6071 | if (speed > 100) | 6087 | if (si_pi->fan_is_controlled_by_smc) |
| 6072 | return -EINVAL; | 6088 | return -EINVAL; |
| 6073 | 6089 | ||
| 6074 | if (rdev->pm.dpm.fan.ucode_fan_control) | 6090 | if (speed > 100) |
| 6075 | si_fan_ctrl_stop_smc_fan_control(rdev); | 6091 | return -EINVAL; |
| 6076 | 6092 | ||
| 6077 | duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; | 6093 | duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; |
| 6078 | 6094 | ||
| @@ -6087,11 +6103,38 @@ static int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, | |||
| 6087 | tmp |= FDO_STATIC_DUTY(duty); | 6103 | tmp |= FDO_STATIC_DUTY(duty); |
| 6088 | WREG32(CG_FDO_CTRL0, tmp); | 6104 | WREG32(CG_FDO_CTRL0, tmp); |
| 6089 | 6105 | ||
| 6090 | si_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC); | ||
| 6091 | |||
| 6092 | return 0; | 6106 | return 0; |
| 6093 | } | 6107 | } |
| 6094 | 6108 | ||
| 6109 | void si_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode) | ||
| 6110 | { | ||
| 6111 | if (mode) { | ||
| 6112 | /* stop auto-manage */ | ||
| 6113 | if (rdev->pm.dpm.fan.ucode_fan_control) | ||
| 6114 | si_fan_ctrl_stop_smc_fan_control(rdev); | ||
| 6115 | si_fan_ctrl_set_static_mode(rdev, mode); | ||
| 6116 | } else { | ||
| 6117 | /* restart auto-manage */ | ||
| 6118 | if (rdev->pm.dpm.fan.ucode_fan_control) | ||
| 6119 | si_thermal_start_smc_fan_control(rdev); | ||
| 6120 | else | ||
| 6121 | si_fan_ctrl_set_default_mode(rdev); | ||
| 6122 | } | ||
| 6123 | } | ||
| 6124 | |||
| 6125 | u32 si_fan_ctrl_get_mode(struct radeon_device *rdev) | ||
| 6126 | { | ||
| 6127 | struct si_power_info *si_pi = si_get_pi(rdev); | ||
| 6128 | u32 tmp; | ||
| 6129 | |||
| 6130 | if (si_pi->fan_is_controlled_by_smc) | ||
| 6131 | return 0; | ||
| 6132 | |||
| 6133 | tmp = RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK; | ||
| 6134 | return (tmp >> FDO_PWM_MODE_SHIFT); | ||
| 6135 | } | ||
| 6136 | |||
| 6137 | #if 0 | ||
| 6095 | static int si_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev, | 6138 | static int si_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev, |
| 6096 | u32 *speed) | 6139 | u32 *speed) |
| 6097 | { | 6140 | { |
| @@ -6538,13 +6581,14 @@ void si_dpm_post_set_power_state(struct radeon_device *rdev) | |||
| 6538 | ni_update_current_ps(rdev, new_ps); | 6581 | ni_update_current_ps(rdev, new_ps); |
| 6539 | } | 6582 | } |
| 6540 | 6583 | ||
| 6541 | 6584 | #if 0 | |
| 6542 | void si_dpm_reset_asic(struct radeon_device *rdev) | 6585 | void si_dpm_reset_asic(struct radeon_device *rdev) |
| 6543 | { | 6586 | { |
| 6544 | si_restrict_performance_levels_before_switch(rdev); | 6587 | si_restrict_performance_levels_before_switch(rdev); |
| 6545 | si_disable_ulv(rdev); | 6588 | si_disable_ulv(rdev); |
| 6546 | si_set_boot_state(rdev); | 6589 | si_set_boot_state(rdev); |
| 6547 | } | 6590 | } |
| 6591 | #endif | ||
| 6548 | 6592 | ||
| 6549 | void si_dpm_display_configuration_changed(struct radeon_device *rdev) | 6593 | void si_dpm_display_configuration_changed(struct radeon_device *rdev) |
| 6550 | { | 6594 | { |
| @@ -6912,7 +6956,6 @@ int si_dpm_init(struct radeon_device *rdev) | |||
| 6912 | rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac; | 6956 | rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac; |
| 6913 | 6957 | ||
| 6914 | si_pi->fan_ctrl_is_in_default_mode = true; | 6958 | si_pi->fan_ctrl_is_in_default_mode = true; |
| 6915 | rdev->pm.dpm.fan.ucode_fan_control = false; | ||
| 6916 | 6959 | ||
| 6917 | return 0; | 6960 | return 0; |
| 6918 | } | 6961 | } |
diff --git a/drivers/gpu/drm/radeon/si_dpm.h b/drivers/gpu/drm/radeon/si_dpm.h index d16bb1b5f10f..1032a68be792 100644 --- a/drivers/gpu/drm/radeon/si_dpm.h +++ b/drivers/gpu/drm/radeon/si_dpm.h | |||
| @@ -202,6 +202,7 @@ struct si_power_info { | |||
| 202 | bool fan_ctrl_is_in_default_mode; | 202 | bool fan_ctrl_is_in_default_mode; |
| 203 | u32 t_min; | 203 | u32 t_min; |
| 204 | u32 fan_ctrl_default_mode; | 204 | u32 fan_ctrl_default_mode; |
| 205 | bool fan_is_controlled_by_smc; | ||
| 205 | }; | 206 | }; |
| 206 | 207 | ||
| 207 | #define SISLANDS_INITIAL_STATE_ARB_INDEX 0 | 208 | #define SISLANDS_INITIAL_STATE_ARB_INDEX 0 |
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 84999242c747..cbd91d226f3c 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
| @@ -901,6 +901,16 @@ | |||
| 901 | /* 0x6e98, 0x7a98, 0x10698, 0x11298, 0x11e98, 0x12a98 */ | 901 | /* 0x6e98, 0x7a98, 0x10698, 0x11298, 0x11e98, 0x12a98 */ |
| 902 | #define CRTC_STATUS_FRAME_COUNT 0x6e98 | 902 | #define CRTC_STATUS_FRAME_COUNT 0x6e98 |
| 903 | 903 | ||
| 904 | /* Audio clocks */ | ||
| 905 | #define DCCG_AUDIO_DTO_SOURCE 0x05ac | ||
| 906 | # define DCCG_AUDIO_DTO0_SOURCE_SEL(x) ((x) << 0) /* crtc0 - crtc5 */ | ||
| 907 | # define DCCG_AUDIO_DTO_SEL (1 << 4) /* 0=dto0 1=dto1 */ | ||
| 908 | |||
| 909 | #define DCCG_AUDIO_DTO0_PHASE 0x05b0 | ||
| 910 | #define DCCG_AUDIO_DTO0_MODULE 0x05b4 | ||
| 911 | #define DCCG_AUDIO_DTO1_PHASE 0x05b8 | ||
| 912 | #define DCCG_AUDIO_DTO1_MODULE 0x05bc | ||
| 913 | |||
| 904 | #define AFMT_AUDIO_SRC_CONTROL 0x713c | 914 | #define AFMT_AUDIO_SRC_CONTROL 0x713c |
| 905 | #define AFMT_AUDIO_SRC_SELECT(x) (((x) & 7) << 0) | 915 | #define AFMT_AUDIO_SRC_SELECT(x) (((x) & 7) << 0) |
| 906 | /* AFMT_AUDIO_SRC_SELECT | 916 | /* AFMT_AUDIO_SRC_SELECT |
diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c index 1f8a8833e1be..25fd4ced36c8 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.c +++ b/drivers/gpu/drm/radeon/sumo_dpm.c | |||
| @@ -1338,6 +1338,7 @@ void sumo_dpm_post_set_power_state(struct radeon_device *rdev) | |||
| 1338 | sumo_update_current_ps(rdev, new_ps); | 1338 | sumo_update_current_ps(rdev, new_ps); |
| 1339 | } | 1339 | } |
| 1340 | 1340 | ||
| 1341 | #if 0 | ||
| 1341 | void sumo_dpm_reset_asic(struct radeon_device *rdev) | 1342 | void sumo_dpm_reset_asic(struct radeon_device *rdev) |
| 1342 | { | 1343 | { |
| 1343 | sumo_program_bootup_state(rdev); | 1344 | sumo_program_bootup_state(rdev); |
| @@ -1349,6 +1350,7 @@ void sumo_dpm_reset_asic(struct radeon_device *rdev) | |||
| 1349 | sumo_set_forced_mode_enabled(rdev); | 1350 | sumo_set_forced_mode_enabled(rdev); |
| 1350 | sumo_set_forced_mode_disabled(rdev); | 1351 | sumo_set_forced_mode_disabled(rdev); |
| 1351 | } | 1352 | } |
| 1353 | #endif | ||
| 1352 | 1354 | ||
| 1353 | void sumo_dpm_setup_asic(struct radeon_device *rdev) | 1355 | void sumo_dpm_setup_asic(struct radeon_device *rdev) |
| 1354 | { | 1356 | { |
| @@ -1537,6 +1539,7 @@ u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev, | |||
| 1537 | return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit; | 1539 | return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit; |
| 1538 | } | 1540 | } |
| 1539 | 1541 | ||
| 1542 | #if 0 | ||
| 1540 | u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev, | 1543 | u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev, |
| 1541 | struct sumo_vid_mapping_table *vid_mapping_table, | 1544 | struct sumo_vid_mapping_table *vid_mapping_table, |
| 1542 | u32 vid_7bit) | 1545 | u32 vid_7bit) |
| @@ -1550,6 +1553,7 @@ u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev, | |||
| 1550 | 1553 | ||
| 1551 | return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit; | 1554 | return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit; |
| 1552 | } | 1555 | } |
| 1556 | #endif | ||
| 1553 | 1557 | ||
| 1554 | static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev, | 1558 | static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev, |
| 1555 | u32 vid_2bit) | 1559 | u32 vid_2bit) |
diff --git a/drivers/gpu/drm/radeon/sumo_dpm.h b/drivers/gpu/drm/radeon/sumo_dpm.h index db1ea32a907b..07dda299c784 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.h +++ b/drivers/gpu/drm/radeon/sumo_dpm.h | |||
| @@ -202,9 +202,6 @@ void sumo_construct_vid_mapping_table(struct radeon_device *rdev, | |||
| 202 | u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev, | 202 | u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev, |
| 203 | struct sumo_vid_mapping_table *vid_mapping_table, | 203 | struct sumo_vid_mapping_table *vid_mapping_table, |
| 204 | u32 vid_2bit); | 204 | u32 vid_2bit); |
| 205 | u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev, | ||
| 206 | struct sumo_vid_mapping_table *vid_mapping_table, | ||
| 207 | u32 vid_7bit); | ||
| 208 | u32 sumo_get_sleep_divider_from_id(u32 id); | 205 | u32 sumo_get_sleep_divider_from_id(u32 id); |
| 209 | u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev, | 206 | u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev, |
| 210 | u32 sclk, | 207 | u32 sclk, |
diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c index b4ec5c4e7969..38dacb7a3689 100644 --- a/drivers/gpu/drm/radeon/trinity_dpm.c +++ b/drivers/gpu/drm/radeon/trinity_dpm.c | |||
| @@ -1269,6 +1269,7 @@ void trinity_dpm_setup_asic(struct radeon_device *rdev) | |||
| 1269 | trinity_release_mutex(rdev); | 1269 | trinity_release_mutex(rdev); |
| 1270 | } | 1270 | } |
| 1271 | 1271 | ||
| 1272 | #if 0 | ||
| 1272 | void trinity_dpm_reset_asic(struct radeon_device *rdev) | 1273 | void trinity_dpm_reset_asic(struct radeon_device *rdev) |
| 1273 | { | 1274 | { |
| 1274 | struct trinity_power_info *pi = trinity_get_pi(rdev); | 1275 | struct trinity_power_info *pi = trinity_get_pi(rdev); |
| @@ -1284,6 +1285,7 @@ void trinity_dpm_reset_asic(struct radeon_device *rdev) | |||
| 1284 | } | 1285 | } |
| 1285 | trinity_release_mutex(rdev); | 1286 | trinity_release_mutex(rdev); |
| 1286 | } | 1287 | } |
| 1288 | #endif | ||
| 1287 | 1289 | ||
| 1288 | static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev, | 1290 | static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev, |
| 1289 | u32 vid_2bit) | 1291 | u32 vid_2bit) |
