Rev 2005 | Rev 3192 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2005 | Rev 2997 | ||
---|---|---|---|
Line 27... | Line 27... | ||
27 | #include "radeon.h" |
27 | #include "radeon.h" |
28 | #include "radeon_reg.h" |
28 | #include "radeon_reg.h" |
29 | #include "radeon_asic.h" |
29 | #include "radeon_asic.h" |
30 | #include "atom.h" |
30 | #include "atom.h" |
Line -... | Line 31... | ||
- | 31 | ||
- | 32 | /* |
|
- | 33 | * check if enc_priv stores radeon_encoder_atom_dig |
|
- | 34 | */ |
|
- | 35 | static bool radeon_dig_encoder(struct drm_encoder *encoder) |
|
31 | 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; |
|
Line 32... | Line 53... | ||
32 | #define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */ |
53 | } |
33 | 54 | ||
34 | /* |
55 | /* |
35 | * check if the chipset is supported |
56 | * check if the chipset is supported |
36 | */ |
57 | */ |
37 | static int r600_audio_chipset_supported(struct radeon_device *rdev) |
58 | static int r600_audio_chipset_supported(struct radeon_device *rdev) |
38 | { |
59 | { |
39 | return (rdev->family >= CHIP_R600 && rdev->family < CHIP_CEDAR) |
60 | return (rdev->family >= CHIP_R600 && !ASIC_IS_DCE6(rdev)) |
40 | || rdev->family == CHIP_RS600 |
61 | || rdev->family == CHIP_RS600 |
41 | || rdev->family == CHIP_RS690 |
62 | || rdev->family == CHIP_RS690 |
Line 42... | Line -... | ||
42 | || rdev->family == CHIP_RS740; |
- | |
43 | } |
- | |
44 | - | ||
45 | /* |
63 | || rdev->family == CHIP_RS740; |
46 | * current number of channels |
64 | } |
47 | */ |
65 | |
48 | int r600_audio_channels(struct radeon_device *rdev) |
66 | struct r600_audio r600_audio_status(struct radeon_device *rdev) |
Line 49... | Line -... | ||
49 | { |
- | |
50 | return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1; |
- | |
51 | } |
- | |
52 | - | ||
53 | /* |
- | |
54 | * current bits per sample |
67 | { |
55 | */ |
- | |
56 | int r600_audio_bits_per_sample(struct radeon_device *rdev) |
- | |
57 | { |
- | |
58 | uint32_t value = (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4; |
- | |
59 | switch (value) { |
- | |
60 | case 0x0: return 8; |
- | |
61 | case 0x1: return 16; |
- | |
Line 62... | Line 68... | ||
62 | case 0x2: return 20; |
68 | struct r600_audio status; |
63 | case 0x3: return 24; |
69 | uint32_t value; |
Line -... | Line 70... | ||
- | 70 | ||
- | 71 | value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); |
|
- | 72 | ||
- | 73 | /* number of channels */ |
|
64 | case 0x4: return 32; |
74 | status.channels = (value & 0x7) + 1; |
- | 75 | ||
- | 76 | /* bits per sample */ |
|
- | 77 | switch ((value & 0xF0) >> 4) { |
|
- | 78 | case 0x0: |
|
- | 79 | status.bits_per_sample = 8; |
|
- | 80 | break; |
|
- | 81 | case 0x1: |
|
- | 82 | status.bits_per_sample = 16; |
|
- | 83 | break; |
|
- | 84 | case 0x2: |
|
- | 85 | status.bits_per_sample = 20; |
|
- | 86 | break; |
|
- | 87 | case 0x3: |
|
- | 88 | status.bits_per_sample = 24; |
|
- | 89 | break; |
|
- | 90 | case 0x4: |
|
65 | } |
91 | status.bits_per_sample = 32; |
Line 66... | Line -... | ||
66 | - | ||
67 | dev_err(rdev->dev, "Unknown bits per sample 0x%x using 16 instead\n", |
92 | break; |
68 | (int)value); |
- | |
69 | - | ||
70 | return 16; |
- | |
71 | } |
- | |
72 | - | ||
73 | /* |
- | |
74 | * current sampling rate in HZ |
93 | default: |
75 | */ |
94 | dev_err(rdev->dev, "Unknown bits per sample 0x%x, using 16\n", |
76 | int r600_audio_rate(struct radeon_device *rdev) |
95 | (int)value); |
77 | { |
96 | status.bits_per_sample = 16; |
- | 97 | } |
|
- | 98 | ||
Line 78... | Line 99... | ||
78 | uint32_t value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); |
99 | /* current sampling rate in HZ */ |
79 | uint32_t result; |
- | |
Line 80... | Line 100... | ||
80 | 100 | if (value & 0x4000) |
|
81 | if (value & 0x4000) |
- | |
- | 101 | status.rate = 44100; |
|
Line 82... | Line -... | ||
82 | result = 44100; |
- | |
83 | else |
102 | else |
84 | result = 48000; |
- | |
85 | - | ||
86 | result *= ((value >> 11) & 0x7) + 1; |
- | |
87 | result /= ((value >> 8) & 0x7) + 1; |
103 | status.rate = 48000; |
88 | - | ||
Line 89... | Line -... | ||
89 | return result; |
- | |
90 | } |
104 | status.rate *= ((value >> 11) & 0x7) + 1; |
91 | - | ||
92 | /* |
- | |
93 | * iec 60958 status bits |
- | |
94 | */ |
- | |
95 | uint8_t r600_audio_status_bits(struct radeon_device *rdev) |
105 | status.rate /= ((value >> 8) & 0x7) + 1; |
Line 96... | Line 106... | ||
96 | { |
106 | |
97 | return RREG32(R600_AUDIO_STATUS_BITS) & 0xff; |
107 | value = RREG32(R600_AUDIO_STATUS_BITS); |
98 | } |
108 | |
99 | 109 | /* iec 60958 status bits */ |
|
100 | /* |
110 | status.status_bits = value & 0xff; |
101 | * iec 60958 category code |
111 | |
- | 112 | /* iec 60958 category code */ |
|
102 | */ |
113 | status.category_code = (value >> 8) & 0xff; |
103 | uint8_t r600_audio_category_code(struct radeon_device *rdev) |
- | |
104 | { |
- | |
105 | return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff; |
- | |
106 | } |
- | |
107 | 114 | ||
108 | /* |
- | |
109 | * update all hdmi interfaces with current audio parameters |
- | |
110 | */ |
115 | return status; |
111 | static void r600_audio_update_hdmi(unsigned long param) |
116 | } |
Line 112... | Line 117... | ||
112 | { |
117 | |
113 | struct radeon_device *rdev = (struct radeon_device *)param; |
118 | /* |
114 | struct drm_device *dev = rdev->ddev; |
119 | * update all hdmi interfaces with current audio parameters |
115 | 120 | */ |
|
116 | int channels = r600_audio_channels(rdev); |
121 | void r600_audio_update_hdmi(struct work_struct *work) |
117 | int rate = r600_audio_rate(rdev); |
- | |
118 | int bps = r600_audio_bits_per_sample(rdev); |
- | |
119 | uint8_t status_bits = r600_audio_status_bits(rdev); |
122 | { |
120 | uint8_t category_code = r600_audio_category_code(rdev); |
123 | struct radeon_device *rdev = container_of(work, struct radeon_device, |
121 | - | ||
122 | struct drm_encoder *encoder; |
- | |
123 | int changes = 0, still_going = 0; |
- | |
124 | 124 | audio_work); |
|
Line 125... | Line 125... | ||
125 | changes |= channels != rdev->audio_channels; |
125 | struct drm_device *dev = rdev->ddev; |
126 | changes |= rate != rdev->audio_rate; |
126 | struct r600_audio audio_status = r600_audio_status(rdev); |
127 | changes |= bps != rdev->audio_bits_per_sample; |
127 | struct drm_encoder *encoder; |
128 | changes |= status_bits != rdev->audio_status_bits; |
128 | bool changed = false; |
129 | changes |= category_code != rdev->audio_category_code; |
129 | |
130 | 130 | if (rdev->audio_status.channels != audio_status.channels || |
|
131 | if (changes) { |
- | |
132 | rdev->audio_channels = channels; |
- | |
133 | rdev->audio_rate = rate; |
- | |
134 | rdev->audio_bits_per_sample = bps; |
131 | rdev->audio_status.rate != audio_status.rate || |
Line 135... | Line 132... | ||
135 | rdev->audio_status_bits = status_bits; |
132 | rdev->audio_status.bits_per_sample != audio_status.bits_per_sample || |
136 | rdev->audio_category_code = category_code; |
133 | rdev->audio_status.status_bits != audio_status.status_bits || |
137 | } |
134 | rdev->audio_status.category_code != audio_status.category_code) { |
138 | 135 | rdev->audio_status = audio_status; |
|
139 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
136 | changed = true; |
- | 137 | } |
|
140 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
138 | |
- | 139 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
|
- | 140 | if (!radeon_dig_encoder(encoder)) |
|
- | 141 | continue; |
|
- | 142 | if (changed || r600_hdmi_buffer_status_changed(encoder)) |
|
- | 143 | r600_hdmi_update_audio_settings(encoder); |
|
- | 144 | } |
|
- | 145 | } |
|
- | 146 | ||
141 | still_going |= radeon_encoder->audio_polling_active; |
147 | /* |
- | 148 | * turn on/off audio engine |
|
142 | if (changes || r600_hdmi_buffer_status_changed(encoder)) |
149 | */ |
143 | r600_hdmi_update_audio_settings(encoder); |
150 | static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) |
Line 144... | Line 151... | ||
144 | } |
151 | { |
145 | 152 | u32 value = 0; |
|
146 | // mod_timer(&rdev->audio_timer, |
153 | DRM_INFO("%s audio support\n", enable ? "Enabling" : "Disabling"); |
147 | // jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL)); |
154 | if (ASIC_IS_DCE4(rdev)) { |
148 | } |
155 | if (enable) { |
149 | 156 | value |= 0x81000000; /* Required to enable audio */ |
|
150 | /* |
157 | value |= 0x0e1000f0; /* fglrx sets that too */ |
Line 151... | Line 158... | ||
151 | * turn on/off audio engine |
158 | } |
Line 152... | Line 159... | ||
152 | */ |
159 | WREG32(EVERGREEN_AUDIO_ENABLE, value); |
153 | static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable) |
160 | } else { |
154 | { |
161 | WREG32_P(R600_AUDIO_ENABLE, |
155 | DRM_INFO("%s audio support\n", enable ? "Enabling" : "Disabling"); |
162 | enable ? 0x81000000 : 0x0, ~0x81000000); |
156 | WREG32_P(R600_AUDIO_ENABLE, enable ? 0x81000000 : 0x0, ~0x81000000); |
163 | } |
157 | rdev->audio_enabled = enable; |
- | |
158 | } |
- | |
159 | - | ||
160 | /* |
- | |
161 | * initialize the audio vars and register the update timer |
- | |
162 | */ |
- | |
163 | int r600_audio_init(struct radeon_device *rdev) |
- | |
Line 164... | Line 164... | ||
164 | { |
164 | rdev->audio_enabled = enable; |
165 | if (!radeon_audio || !r600_audio_chipset_supported(rdev)) |
165 | } |
Line 166... | Line 166... | ||
166 | return 0; |
166 | |
Line 190... | Line 190... | ||
190 | { |
190 | { |
191 | struct drm_device *dev = encoder->dev; |
191 | struct drm_device *dev = encoder->dev; |
192 | struct radeon_device *rdev = dev->dev_private; |
192 | struct radeon_device *rdev = dev->dev_private; |
193 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
193 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
194 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
194 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
- | 195 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); |
|
195 | int base_rate = 48000; |
196 | int base_rate = 48000; |
Line 196... | Line 197... | ||
196 | 197 | ||
197 | switch (radeon_encoder->encoder_id) { |
198 | switch (radeon_encoder->encoder_id) { |
198 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: |
199 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: |
Line 209... | Line 210... | ||
209 | dev_err(rdev->dev, "Unsupported encoder type 0x%02X\n", |
210 | dev_err(rdev->dev, "Unsupported encoder type 0x%02X\n", |
210 | radeon_encoder->encoder_id); |
211 | radeon_encoder->encoder_id); |
211 | return; |
212 | return; |
212 | } |
213 | } |
Line -... | Line 214... | ||
- | 214 | ||
- | 215 | if (ASIC_IS_DCE4(rdev)) { |
|
- | 216 | /* TODO: other PLLs? */ |
|
- | 217 | WREG32(EVERGREEN_AUDIO_PLL1_MUL, base_rate * 10); |
|
- | 218 | WREG32(EVERGREEN_AUDIO_PLL1_DIV, clock * 10); |
|
- | 219 | WREG32(EVERGREEN_AUDIO_PLL1_UNK, 0x00000071); |
|
- | 220 | ||
- | 221 | /* Select DTO source */ |
|
- | 222 | WREG32(0x5ac, radeon_crtc->crtc_id); |
|
213 | 223 | } else { |
|
214 | switch (dig->dig_encoder) { |
224 | switch (dig->dig_encoder) { |
215 | case 0: |
225 | case 0: |
216 | WREG32(R600_AUDIO_PLL1_MUL, base_rate * 50); |
226 | WREG32(R600_AUDIO_PLL1_MUL, base_rate * 50); |
217 | WREG32(R600_AUDIO_PLL1_DIV, clock * 100); |
227 | WREG32(R600_AUDIO_PLL1_DIV, clock * 100); |
Line 222... | Line 232... | ||
222 | WREG32(R600_AUDIO_PLL2_MUL, base_rate * 50); |
232 | WREG32(R600_AUDIO_PLL2_MUL, base_rate * 50); |
223 | WREG32(R600_AUDIO_PLL2_DIV, clock * 100); |
233 | WREG32(R600_AUDIO_PLL2_DIV, clock * 100); |
224 | WREG32(R600_AUDIO_CLK_SRCSEL, 1); |
234 | WREG32(R600_AUDIO_CLK_SRCSEL, 1); |
225 | break; |
235 | break; |
226 | default: |
236 | default: |
- | 237 | dev_err(rdev->dev, |
|
227 | dev_err(rdev->dev, "Unsupported DIG on encoder 0x%02X\n", |
238 | "Unsupported DIG on encoder 0x%02X\n", |
228 | radeon_encoder->encoder_id); |
239 | radeon_encoder->encoder_id); |
229 | return; |
240 | return; |
230 | } |
241 | } |
231 | } |
242 | } |
- | 243 | } |
|
Line 232... | Line 244... | ||
232 | 244 | ||
233 | /* |
245 | /* |
234 | * release the audio timer |
246 | * release the audio timer |
235 | * TODO: How to do this correctly on SMP systems? |
247 | * TODO: How to do this correctly on SMP systems? |
236 | */ |
248 | */ |
237 | void r600_audio_fini(struct radeon_device *rdev) |
249 | void r600_audio_fini(struct radeon_device *rdev) |
238 | { |
250 | { |
239 | if (!rdev->audio_enabled) |
251 | if (!rdev->audio_enabled) |
Line 240... | Line -... | ||
240 | return; |
- | |
241 | - | ||
242 | // del_timer(&rdev->audio_timer); |
252 | return; |
243 | 253 |