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#include "drmP.h" 27#include "radeon.h" 28#include "radeon_reg.h" 29#include "atom.h" 30 31#define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */ 32 33/* 34 * check if the chipset is supported 35 */ 36static int r600_audio_chipset_supported(struct radeon_device *rdev) 37{ 38 return (rdev->family >= CHIP_R600 && rdev->family < CHIP_CEDAR) 39 || rdev->family == CHIP_RS600 40 || rdev->family == CHIP_RS690 41 || rdev->family == CHIP_RS740; 42} 43 44/* 45 * current number of channels 46 */ 47int r600_audio_channels(struct radeon_device *rdev) 48{ 49 return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1; 50} 51 52/* 53 * current bits per sample 54 */ 55int r600_audio_bits_per_sample(struct radeon_device *rdev) 56{ 57 uint32_t value = (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4; 58 switch (value) { 59 case 0x0: return 8; 60 case 0x1: return 16; 61 case 0x2: return 20; 62 case 0x3: return 24; 63 case 0x4: return 32; 64 } 65 66 dev_err(rdev->dev, "Unknown bits per sample 0x%x using 16 instead\n", 67 (int)value); 68 69 return 16; 70} 71 72/* 73 * current sampling rate in HZ 74 */ 75int r600_audio_rate(struct radeon_device *rdev) 76{ 77 uint32_t value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); 78 uint32_t result; 79 80 if (value & 0x4000) 81 result = 44100; 82 else 83 result = 48000; 84 85 result *= ((value >> 11) & 0x7) + 1; 86 result /= ((value >> 8) & 0x7) + 1; 87 88 return result; 89} 90 91/* 92 * iec 60958 status bits 93 */ 94uint8_t r600_audio_status_bits(struct radeon_device *rdev) 95{ 96 return RREG32(R600_AUDIO_STATUS_BITS) & 0xff; 97} 98 99/* 100 * iec 60958 category code 101 */ 102uint8_t r600_audio_category_code(struct radeon_device *rdev) 103{ 104 return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff; 105} 106 107/* 108 * schedule next audio update event 109 */ 110void r600_audio_schedule_polling(struct radeon_device *rdev) 111{ 112 mod_timer(&rdev->audio_timer, 113 jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); 114} 115 116/* 117 * update all hdmi interfaces with current audio parameters 118 */ 119static void r600_audio_update_hdmi(unsigned long param) 120{ 121 struct radeon_device *rdev = (struct radeon_device *)param; 122 struct drm_device *dev = rdev->ddev; 123 124 int channels = r600_audio_channels(rdev); 125 int rate = r600_audio_rate(rdev); 126 int bps = r600_audio_bits_per_sample(rdev); 127 uint8_t status_bits = r600_audio_status_bits(rdev); 128 uint8_t category_code = r600_audio_category_code(rdev); 129 130 struct drm_encoder *encoder; 131 int changes = 0, still_going = 0; 132 133 changes |= channels != rdev->audio_channels; 134 changes |= rate != rdev->audio_rate; 135 changes |= bps != rdev->audio_bits_per_sample; 136 changes |= status_bits != rdev->audio_status_bits; 137 changes |= category_code != rdev->audio_category_code; 138 139 if (changes) { 140 rdev->audio_channels = channels; 141 rdev->audio_rate = rate; 142 rdev->audio_bits_per_sample = bps; 143 rdev->audio_status_bits = status_bits; 144 rdev->audio_category_code = category_code; 145 } 146 147 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 148 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 149 still_going |= radeon_encoder->audio_polling_active; 150 if (changes || r600_hdmi_buffer_status_changed(encoder)) 151 r600_hdmi_update_audio_settings(encoder); 152 } 153 154 if (still_going) 155 r600_audio_schedule_polling(rdev); 156} 157 158/* 159 * turn on/off audio engine 160 */ 161static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) 162{ 163 DRM_INFO("%s audio support\n", enable ? "Enabling" : "Disabling"); 164 WREG32_P(R600_AUDIO_ENABLE, enable ? 0x81000000 : 0x0, ~0x81000000); 165 rdev->audio_enabled = enable; 166} 167 168/* 169 * initialize the audio vars and register the update timer 170 */ 171int r600_audio_init(struct radeon_device *rdev) 172{ 173 if (!radeon_audio || !r600_audio_chipset_supported(rdev)) 174 return 0; 175 176 r600_audio_engine_enable(rdev, true); 177 178 rdev->audio_channels = -1; 179 rdev->audio_rate = -1; 180 rdev->audio_bits_per_sample = -1; 181 rdev->audio_status_bits = 0; 182 rdev->audio_category_code = 0; 183 184 setup_timer( 185 &rdev->audio_timer, 186 r600_audio_update_hdmi, 187 (unsigned long)rdev); 188 189 return 0; 190} 191 192/* 193 * enable the polling timer, to check for status changes 194 */ 195void r600_audio_enable_polling(struct drm_encoder *encoder) 196{ 197 struct drm_device *dev = encoder->dev; 198 struct radeon_device *rdev = dev->dev_private; 199 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 200 201 DRM_DEBUG("r600_audio_enable_polling: %d\n", 202 radeon_encoder->audio_polling_active); 203 if (radeon_encoder->audio_polling_active) 204 return; 205 206 radeon_encoder->audio_polling_active = 1; 207 if (rdev->audio_enabled) 208 mod_timer(&rdev->audio_timer, jiffies + 1); 209} 210 211/* 212 * disable the polling timer, so we get no more status updates 213 */ 214void r600_audio_disable_polling(struct drm_encoder *encoder) 215{ 216 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 217 DRM_DEBUG("r600_audio_disable_polling: %d\n", 218 radeon_encoder->audio_polling_active); 219 radeon_encoder->audio_polling_active = 0; 220} 221 222/* 223 * atach the audio codec to the clock source of the encoder 224 */ 225void r600_audio_set_clock(struct drm_encoder *encoder, int clock) 226{ 227 struct drm_device *dev = encoder->dev; 228 struct radeon_device *rdev = dev->dev_private; 229 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 230 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 231 int base_rate = 48000; 232 233 switch (radeon_encoder->encoder_id) { 234 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 235 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 236 WREG32_P(R600_AUDIO_TIMING, 0, ~0x301); 237 break; 238 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 239 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 240 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 241 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 242 WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301); 243 break; 244 default: 245 dev_err(rdev->dev, "Unsupported encoder type 0x%02X\n", 246 radeon_encoder->encoder_id); 247 return; 248 } 249 250 switch (dig->dig_encoder) { 251 case 0: 252 WREG32(R600_AUDIO_PLL1_MUL, base_rate * 50); 253 WREG32(R600_AUDIO_PLL1_DIV, clock * 100); 254 WREG32(R600_AUDIO_CLK_SRCSEL, 0); 255 break; 256 257 case 1: 258 WREG32(R600_AUDIO_PLL2_MUL, base_rate * 50); 259 WREG32(R600_AUDIO_PLL2_DIV, clock * 100); 260 WREG32(R600_AUDIO_CLK_SRCSEL, 1); 261 break; 262 default: 263 dev_err(rdev->dev, "Unsupported DIG on encoder 0x%02X\n", 264 radeon_encoder->encoder_id); 265 return; 266 } 267} 268 269/* 270 * release the audio timer 271 * TODO: How to do this correctly on SMP systems? 272 */ 273void r600_audio_fini(struct radeon_device *rdev) 274{ 275 if (!rdev->audio_enabled) 276 return; 277 278 del_timer(&rdev->audio_timer); 279 280 r600_audio_engine_enable(rdev, false); 281} 282