~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/gpu/drm/radeon/r600_audio.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno, Martin Michlmayr
  • Date: 2011-04-06 13:53:30 UTC
  • mfrom: (43.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110406135330-wjufxhd0tvn3zx4z
Tags: 2.6.38-3
[ Ben Hutchings ]
* [ppc64] Add to linux-tools package architectures (Closes: #620124)
* [amd64] Save cr4 to mmu_cr4_features at boot time (Closes: #620284)
* appletalk: Fix bugs introduced when removing use of BKL
* ALSA: Fix yet another race in disconnection
* cciss: Fix lost command issue
* ath9k: Fix kernel panic in AR2427
* ses: Avoid kernel panic when lun 0 is not mapped
* PCI/ACPI: Report ASPM support to BIOS if not disabled from command line

[ Aurelien Jarno ]
* rtlwifi: fix build when PCI is not enabled.

[ Martin Michlmayr ]
* rtlwifi: Eliminate udelay calls with too large values (Closes: #620204)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 */
 
36
static 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
 */
 
47
int 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
 */
 
55
int 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
 */
 
75
int 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
 */
 
94
uint8_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
 */
 
102
uint8_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
 */
 
110
void 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
 */
 
119
static 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
 */
 
161
static 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
 */
 
171
int 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
 */
 
195
void 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
 */
 
214
void 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
 */
 
225
void 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
 */
 
273
void 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
}