r600_audio.c revision 254885
1/* 2 * Copyright 2008 Advanced Micro Devices, Inc. 3 * Copyright 2008 Red Hat Inc. 4 * Copyright 2009 Christian K��nig. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: Christian K��nig 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/dev/drm2/radeon/r600_audio.c 254885 2013-08-25 19:37:15Z dumbbell $"); 29 30#include <dev/drm2/drmP.h> 31#include "radeon.h" 32#include "radeon_reg.h" 33#include "radeon_asic.h" 34#include "atom.h" 35 36/* 37 * check if enc_priv stores radeon_encoder_atom_dig 38 */ 39static bool radeon_dig_encoder(struct drm_encoder *encoder) 40{ 41 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 42 switch (radeon_encoder->encoder_id) { 43 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 44 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 45 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 46 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 47 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 48 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 49 case ENCODER_OBJECT_ID_INTERNAL_DDI: 50 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 51 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 52 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 53 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 54 return true; 55 } 56 return false; 57} 58 59/* 60 * check if the chipset is supported 61 */ 62static int r600_audio_chipset_supported(struct radeon_device *rdev) 63{ 64 return (rdev->family >= CHIP_R600 && !ASIC_IS_DCE6(rdev)) 65 || rdev->family == CHIP_RS600 66 || rdev->family == CHIP_RS690 67 || rdev->family == CHIP_RS740; 68} 69 70struct r600_audio r600_audio_status(struct radeon_device *rdev) 71{ 72 struct r600_audio status; 73 uint32_t value; 74 75 value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); 76 77 /* number of channels */ 78 status.channels = (value & 0x7) + 1; 79 80 /* bits per sample */ 81 switch ((value & 0xF0) >> 4) { 82 case 0x0: 83 status.bits_per_sample = 8; 84 break; 85 case 0x1: 86 status.bits_per_sample = 16; 87 break; 88 case 0x2: 89 status.bits_per_sample = 20; 90 break; 91 case 0x3: 92 status.bits_per_sample = 24; 93 break; 94 case 0x4: 95 status.bits_per_sample = 32; 96 break; 97 default: 98 dev_err(rdev->dev, "Unknown bits per sample 0x%x, using 16\n", 99 (int)value); 100 status.bits_per_sample = 16; 101 } 102 103 /* current sampling rate in HZ */ 104 if (value & 0x4000) 105 status.rate = 44100; 106 else 107 status.rate = 48000; 108 status.rate *= ((value >> 11) & 0x7) + 1; 109 status.rate /= ((value >> 8) & 0x7) + 1; 110 111 value = RREG32(R600_AUDIO_STATUS_BITS); 112 113 /* iec 60958 status bits */ 114 status.status_bits = value & 0xff; 115 116 /* iec 60958 category code */ 117 status.category_code = (value >> 8) & 0xff; 118 119 return status; 120} 121 122/* 123 * update all hdmi interfaces with current audio parameters 124 */ 125void r600_audio_update_hdmi(void *arg, int pending) 126{ 127 struct radeon_device *rdev = arg; 128 struct drm_device *dev = rdev->ddev; 129 struct r600_audio audio_status = r600_audio_status(rdev); 130 struct drm_encoder *encoder; 131 bool changed = false; 132 133 if (rdev->audio_status.channels != audio_status.channels || 134 rdev->audio_status.rate != audio_status.rate || 135 rdev->audio_status.bits_per_sample != audio_status.bits_per_sample || 136 rdev->audio_status.status_bits != audio_status.status_bits || 137 rdev->audio_status.category_code != audio_status.category_code) { 138 rdev->audio_status = audio_status; 139 changed = true; 140 } 141 142 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 143 if (!radeon_dig_encoder(encoder)) 144 continue; 145 if (changed || r600_hdmi_buffer_status_changed(encoder)) 146 r600_hdmi_update_audio_settings(encoder); 147 } 148} 149 150/* 151 * turn on/off audio engine 152 */ 153static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) 154{ 155 u32 value = 0; 156 DRM_INFO("%s audio support\n", enable ? "Enabling" : "Disabling"); 157 if (ASIC_IS_DCE4(rdev)) { 158 if (enable) { 159 value |= 0x81000000; /* Required to enable audio */ 160 value |= 0x0e1000f0; /* fglrx sets that too */ 161 } 162 WREG32(EVERGREEN_AUDIO_ENABLE, value); 163 } else { 164 WREG32_P(R600_AUDIO_ENABLE, 165 enable ? 0x81000000 : 0x0, ~0x81000000); 166 } 167 rdev->audio_enabled = enable; 168} 169 170/* 171 * initialize the audio vars 172 */ 173int r600_audio_init(struct radeon_device *rdev) 174{ 175 if (!radeon_audio || !r600_audio_chipset_supported(rdev)) 176 return 0; 177 178 r600_audio_engine_enable(rdev, true); 179 180 rdev->audio_status.channels = -1; 181 rdev->audio_status.rate = -1; 182 rdev->audio_status.bits_per_sample = -1; 183 rdev->audio_status.status_bits = 0; 184 rdev->audio_status.category_code = 0; 185 186 return 0; 187} 188 189/* 190 * atach the audio codec to the clock source of the encoder 191 */ 192void r600_audio_set_clock(struct drm_encoder *encoder, int clock) 193{ 194 struct drm_device *dev = encoder->dev; 195 struct radeon_device *rdev = dev->dev_private; 196 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 197 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 198 struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 199 int base_rate = 48000; 200 201 switch (radeon_encoder->encoder_id) { 202 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 203 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 204 WREG32_P(R600_AUDIO_TIMING, 0, ~0x301); 205 break; 206 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 207 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 208 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 209 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 210 WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301); 211 break; 212 default: 213 dev_err(rdev->dev, "Unsupported encoder type 0x%02X\n", 214 radeon_encoder->encoder_id); 215 return; 216 } 217 218 if (ASIC_IS_DCE4(rdev)) { 219 /* TODO: other PLLs? */ 220 WREG32(EVERGREEN_AUDIO_PLL1_MUL, base_rate * 10); 221 WREG32(EVERGREEN_AUDIO_PLL1_DIV, clock * 10); 222 WREG32(EVERGREEN_AUDIO_PLL1_UNK, 0x00000071); 223 224 /* Select DTO source */ 225 WREG32(0x5ac, radeon_crtc->crtc_id); 226 } else { 227 switch (dig->dig_encoder) { 228 case 0: 229 WREG32(R600_AUDIO_PLL1_MUL, base_rate * 50); 230 WREG32(R600_AUDIO_PLL1_DIV, clock * 100); 231 WREG32(R600_AUDIO_CLK_SRCSEL, 0); 232 break; 233 234 case 1: 235 WREG32(R600_AUDIO_PLL2_MUL, base_rate * 50); 236 WREG32(R600_AUDIO_PLL2_DIV, clock * 100); 237 WREG32(R600_AUDIO_CLK_SRCSEL, 1); 238 break; 239 default: 240 dev_err(rdev->dev, 241 "Unsupported DIG on encoder 0x%02X\n", 242 radeon_encoder->encoder_id); 243 return; 244 } 245 } 246} 247 248/* 249 * release the audio timer 250 * TODO: How to do this correctly on SMP systems? 251 */ 252void r600_audio_fini(struct radeon_device *rdev) 253{ 254 if (!rdev->audio_enabled) 255 return; 256 257 r600_audio_engine_enable(rdev, false); 258} 259