Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.15-rc4 207 lines 5.7 kB view raw
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 <drm/drmP.h> 27#include "radeon.h" 28#include "radeon_reg.h" 29#include "radeon_asic.h" 30#include "atom.h" 31 32/* 33 * check if enc_priv stores radeon_encoder_atom_dig 34 */ 35static bool radeon_dig_encoder(struct drm_encoder *encoder) 36{ 37 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 38 switch (radeon_encoder->encoder_id) { 39 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 40 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 41 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 42 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 43 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 44 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 45 case ENCODER_OBJECT_ID_INTERNAL_DDI: 46 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 47 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 48 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 49 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 50 return true; 51 } 52 return false; 53} 54 55/* 56 * check if the chipset is supported 57 */ 58static int r600_audio_chipset_supported(struct radeon_device *rdev) 59{ 60 return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev); 61} 62 63struct r600_audio_pin r600_audio_status(struct radeon_device *rdev) 64{ 65 struct r600_audio_pin status; 66 uint32_t value; 67 68 value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); 69 70 /* number of channels */ 71 status.channels = (value & 0x7) + 1; 72 73 /* bits per sample */ 74 switch ((value & 0xF0) >> 4) { 75 case 0x0: 76 status.bits_per_sample = 8; 77 break; 78 case 0x1: 79 status.bits_per_sample = 16; 80 break; 81 case 0x2: 82 status.bits_per_sample = 20; 83 break; 84 case 0x3: 85 status.bits_per_sample = 24; 86 break; 87 case 0x4: 88 status.bits_per_sample = 32; 89 break; 90 default: 91 dev_err(rdev->dev, "Unknown bits per sample 0x%x, using 16\n", 92 (int)value); 93 status.bits_per_sample = 16; 94 } 95 96 /* current sampling rate in HZ */ 97 if (value & 0x4000) 98 status.rate = 44100; 99 else 100 status.rate = 48000; 101 status.rate *= ((value >> 11) & 0x7) + 1; 102 status.rate /= ((value >> 8) & 0x7) + 1; 103 104 value = RREG32(R600_AUDIO_STATUS_BITS); 105 106 /* iec 60958 status bits */ 107 status.status_bits = value & 0xff; 108 109 /* iec 60958 category code */ 110 status.category_code = (value >> 8) & 0xff; 111 112 return status; 113} 114 115/* 116 * update all hdmi interfaces with current audio parameters 117 */ 118void r600_audio_update_hdmi(struct work_struct *work) 119{ 120 struct radeon_device *rdev = container_of(work, struct radeon_device, 121 audio_work); 122 struct drm_device *dev = rdev->ddev; 123 struct r600_audio_pin audio_status = r600_audio_status(rdev); 124 struct drm_encoder *encoder; 125 bool changed = false; 126 127 if (rdev->audio.pin[0].channels != audio_status.channels || 128 rdev->audio.pin[0].rate != audio_status.rate || 129 rdev->audio.pin[0].bits_per_sample != audio_status.bits_per_sample || 130 rdev->audio.pin[0].status_bits != audio_status.status_bits || 131 rdev->audio.pin[0].category_code != audio_status.category_code) { 132 rdev->audio.pin[0] = audio_status; 133 changed = true; 134 } 135 136 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 137 if (!radeon_dig_encoder(encoder)) 138 continue; 139 if (changed || r600_hdmi_buffer_status_changed(encoder)) 140 r600_hdmi_update_audio_settings(encoder); 141 } 142} 143 144/* enable the audio stream */ 145void r600_audio_enable(struct radeon_device *rdev, 146 struct r600_audio_pin *pin, 147 bool enable) 148{ 149 u32 value = 0; 150 151 if (!pin) 152 return; 153 154 if (ASIC_IS_DCE4(rdev)) { 155 if (enable) { 156 value |= 0x81000000; /* Required to enable audio */ 157 value |= 0x0e1000f0; /* fglrx sets that too */ 158 } 159 WREG32(EVERGREEN_AUDIO_ENABLE, value); 160 } else { 161 WREG32_P(R600_AUDIO_ENABLE, 162 enable ? 0x81000000 : 0x0, ~0x81000000); 163 } 164} 165 166/* 167 * initialize the audio vars 168 */ 169int r600_audio_init(struct radeon_device *rdev) 170{ 171 if (!radeon_audio || !r600_audio_chipset_supported(rdev)) 172 return 0; 173 174 rdev->audio.enabled = true; 175 176 rdev->audio.num_pins = 1; 177 rdev->audio.pin[0].channels = -1; 178 rdev->audio.pin[0].rate = -1; 179 rdev->audio.pin[0].bits_per_sample = -1; 180 rdev->audio.pin[0].status_bits = 0; 181 rdev->audio.pin[0].category_code = 0; 182 rdev->audio.pin[0].id = 0; 183 /* disable audio. it will be set up later */ 184 r600_audio_enable(rdev, &rdev->audio.pin[0], false); 185 186 return 0; 187} 188 189/* 190 * release the audio timer 191 * TODO: How to do this correctly on SMP systems? 192 */ 193void r600_audio_fini(struct radeon_device *rdev) 194{ 195 if (!rdev->audio.enabled) 196 return; 197 198 r600_audio_enable(rdev, &rdev->audio.pin[0], false); 199 200 rdev->audio.enabled = false; 201} 202 203struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev) 204{ 205 /* only one pin on 6xx-NI */ 206 return &rdev->audio.pin[0]; 207}