aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r600_audio.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-24 15:42:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-24 15:42:54 -0400
commitf2fde3a65e88330017b816faf2ef75f141d21375 (patch)
tree57152ab5756e7ed1c58742e7e16f13a45ff11f21 /drivers/gpu/drm/radeon/r600_audio.c
parent28f3d717618156c0dcd2f497d791b578a7931d87 (diff)
parent8c914028f5ddaa417b7d0f4b7fdc24caceaa8043 (diff)
Merge branch 'drm-core-next' of git://people.freedesktop.org/~airlied/linux
Pull main drm updates from Dave Airlie: "This is the main merge window request for the drm. It's big, but jam packed will lots of features and of course 0 regressions. (okay maybe there'll be one). Highlights: - new KMS drivers for server GPU chipsets: ast, mgag200 and cirrus (qemu only). These drivers use the generic modesetting drivers. - initial prime/dma-buf support for i915, nouveau, radeon, udl and exynos - switcheroo audio support: so GPUs with HDMI can turn off the sound driver without crashing stuff. - There are some patches drifting outside drivers/gpu into x86 and EFI for better handling of multiple video adapters in Apple Macs, they've got correct acks except one trivial fixup. - Core: edid parser has better DMT and reduced blanking support, crtc properties, plane properties, - Drivers: exynos: add 2D core accel support, prime support, hdmi features intel: more Haswell support, initial Valleyview support, more hdmi infoframe fixes, update MAINTAINERS for Daniel, lots of cleanups and fixes radeon: more HDMI audio support, improved GPU lockup recovery support, remove nested mutexes, less memory copying on PCIE, fix bus master enable race (kexec), improved fence handling gma500: cleanups, 1080p support, acpi fixes nouveau: better nva3 memory reclocking, kepler accel (needs external firmware rip), async buffer moves on nv84+ hw. I've some more dma-buf patches that rely on the dma-buf merge for vmap stuff, and I've a few fixes building up, but I'd decided I'd better get rid of the main pull sooner rather than later, so the audio guys are also unblocked." Fix up trivial conflict due to some duplicated changes in drivers/gpu/drm/i915/intel_ringbuffer.c * 'drm-core-next' of git://people.freedesktop.org/~airlied/linux: (605 commits) drm/nouveau/nvd9: Fix GPIO initialisation sequence. drm/nouveau: Unregister switcheroo client on exit drm/nouveau: Check dsm on switcheroo unregister drm/nouveau: fix a minor annoyance in an output string drm/nouveau: turn a BUG into a WARN drm/nv50: decode PGRAPH DATA_ERROR = 0x24 drm/nouveau/disp: fix dithering not being enabled on some eDP macbooks drm/nvd9/copy: initialise copy engine, seems to work like nvc0 drm/nvc0/ttm: use copy engines for async buffer moves drm/nva3/ttm: use copy engine for async buffer moves drm/nv98/ttm: add in a (disabled) crypto engine buffer copy method drm/nv84/ttm: use crypto engine for async buffer copies drm/nouveau/ttm: untangle code to support accelerated buffer moves drm/nouveau/fbcon: use fence for sync, rather than notifier drm/nv98/crypt: non-stub implementation of the engine hooks drm/nouveau/fifo: turn all fifo modules into engine modules drm/nv50/graph: remove ability to do interrupt-driven context switching drm/nv50: remove manual context unload on context destruction drm/nv50: remove execution engine context saves on suspend drm/nv50/fifo: use hardware channel kickoff functionality ...
Diffstat (limited to 'drivers/gpu/drm/radeon/r600_audio.c')
-rw-r--r--drivers/gpu/drm/radeon/r600_audio.c215
1 files changed, 83 insertions, 132 deletions
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c
index ba66f3093d46..7c4fa77f018f 100644
--- a/drivers/gpu/drm/radeon/r600_audio.c
+++ b/drivers/gpu/drm/radeon/r600_audio.c
@@ -29,7 +29,28 @@
29#include "radeon_asic.h" 29#include "radeon_asic.h"
30#include "atom.h" 30#include "atom.h"
31 31
32#define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */ 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}
33 54
34/* 55/*
35 * check if the chipset is supported 56 * check if the chipset is supported
@@ -42,118 +63,85 @@ static int r600_audio_chipset_supported(struct radeon_device *rdev)
42 || rdev->family == CHIP_RS740; 63 || rdev->family == CHIP_RS740;
43} 64}
44 65
45/* 66struct r600_audio r600_audio_status(struct radeon_device *rdev)
46 * current number of channels
47 */
48int r600_audio_channels(struct radeon_device *rdev)
49{ 67{
50 return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1; 68 struct r600_audio status;
51} 69 uint32_t value;
52 70
53/* 71 value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL);
54 * current bits per sample
55 */
56int 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;
62 case 0x2: return 20;
63 case 0x3: return 24;
64 case 0x4: return 32;
65 }
66 72
67 dev_err(rdev->dev, "Unknown bits per sample 0x%x using 16 instead\n", 73 /* number of channels */
68 (int)value); 74 status.channels = (value & 0x7) + 1;
69 75
70 return 16; 76 /* bits per sample */
71} 77 switch ((value & 0xF0) >> 4) {
72 78 case 0x0:
73/* 79 status.bits_per_sample = 8;
74 * current sampling rate in HZ 80 break;
75 */ 81 case 0x1:
76int r600_audio_rate(struct radeon_device *rdev) 82 status.bits_per_sample = 16;
77{ 83 break;
78 uint32_t value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); 84 case 0x2:
79 uint32_t result; 85 status.bits_per_sample = 20;
86 break;
87 case 0x3:
88 status.bits_per_sample = 24;
89 break;
90 case 0x4:
91 status.bits_per_sample = 32;
92 break;
93 default:
94 dev_err(rdev->dev, "Unknown bits per sample 0x%x, using 16\n",
95 (int)value);
96 status.bits_per_sample = 16;
97 }
80 98
99 /* current sampling rate in HZ */
81 if (value & 0x4000) 100 if (value & 0x4000)
82 result = 44100; 101 status.rate = 44100;
83 else 102 else
84 result = 48000; 103 status.rate = 48000;
104 status.rate *= ((value >> 11) & 0x7) + 1;
105 status.rate /= ((value >> 8) & 0x7) + 1;
85 106
86 result *= ((value >> 11) & 0x7) + 1; 107 value = RREG32(R600_AUDIO_STATUS_BITS);
87 result /= ((value >> 8) & 0x7) + 1;
88 108
89 return result; 109 /* iec 60958 status bits */
90} 110 status.status_bits = value & 0xff;
91 111
92/* 112 /* iec 60958 category code */
93 * iec 60958 status bits 113 status.category_code = (value >> 8) & 0xff;
94 */
95uint8_t r600_audio_status_bits(struct radeon_device *rdev)
96{
97 return RREG32(R600_AUDIO_STATUS_BITS) & 0xff;
98}
99 114
100/* 115 return status;
101 * iec 60958 category code
102 */
103uint8_t r600_audio_category_code(struct radeon_device *rdev)
104{
105 return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff;
106}
107
108/*
109 * schedule next audio update event
110 */
111void r600_audio_schedule_polling(struct radeon_device *rdev)
112{
113 mod_timer(&rdev->audio_timer,
114 jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL));
115} 116}
116 117
117/* 118/*
118 * update all hdmi interfaces with current audio parameters 119 * update all hdmi interfaces with current audio parameters
119 */ 120 */
120static void r600_audio_update_hdmi(unsigned long param) 121void r600_audio_update_hdmi(struct work_struct *work)
121{ 122{
122 struct radeon_device *rdev = (struct radeon_device *)param; 123 struct radeon_device *rdev = container_of(work, struct radeon_device,
124 audio_work);
123 struct drm_device *dev = rdev->ddev; 125 struct drm_device *dev = rdev->ddev;
124 126 struct r600_audio audio_status = r600_audio_status(rdev);
125 int channels = r600_audio_channels(rdev);
126 int rate = r600_audio_rate(rdev);
127 int bps = r600_audio_bits_per_sample(rdev);
128 uint8_t status_bits = r600_audio_status_bits(rdev);
129 uint8_t category_code = r600_audio_category_code(rdev);
130
131 struct drm_encoder *encoder; 127 struct drm_encoder *encoder;
132 int changes = 0, still_going = 0; 128 bool changed = false;
133 129
134 changes |= channels != rdev->audio_channels; 130 if (rdev->audio_status.channels != audio_status.channels ||
135 changes |= rate != rdev->audio_rate; 131 rdev->audio_status.rate != audio_status.rate ||
136 changes |= bps != rdev->audio_bits_per_sample; 132 rdev->audio_status.bits_per_sample != audio_status.bits_per_sample ||
137 changes |= status_bits != rdev->audio_status_bits; 133 rdev->audio_status.status_bits != audio_status.status_bits ||
138 changes |= category_code != rdev->audio_category_code; 134 rdev->audio_status.category_code != audio_status.category_code) {
139 135 rdev->audio_status = audio_status;
140 if (changes) { 136 changed = true;
141 rdev->audio_channels = channels;
142 rdev->audio_rate = rate;
143 rdev->audio_bits_per_sample = bps;
144 rdev->audio_status_bits = status_bits;
145 rdev->audio_category_code = category_code;
146 } 137 }
147 138
148 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 139 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
149 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 140 if (!radeon_dig_encoder(encoder))
150 still_going |= radeon_encoder->audio_polling_active; 141 continue;
151 if (changes || r600_hdmi_buffer_status_changed(encoder)) 142 if (changed || r600_hdmi_buffer_status_changed(encoder))
152 r600_hdmi_update_audio_settings(encoder); 143 r600_hdmi_update_audio_settings(encoder);
153 } 144 }
154
155 if (still_going)
156 r600_audio_schedule_polling(rdev);
157} 145}
158 146
159/* 147/*
@@ -177,7 +165,7 @@ static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable)
177} 165}
178 166
179/* 167/*
180 * initialize the audio vars and register the update timer 168 * initialize the audio vars
181 */ 169 */
182int r600_audio_init(struct radeon_device *rdev) 170int r600_audio_init(struct radeon_device *rdev)
183{ 171{
@@ -186,51 +174,16 @@ int r600_audio_init(struct radeon_device *rdev)
186 174
187 r600_audio_engine_enable(rdev, true); 175 r600_audio_engine_enable(rdev, true);
188 176
189 rdev->audio_channels = -1; 177 rdev->audio_status.channels = -1;
190 rdev->audio_rate = -1; 178 rdev->audio_status.rate = -1;
191 rdev->audio_bits_per_sample = -1; 179 rdev->audio_status.bits_per_sample = -1;
192 rdev->audio_status_bits = 0; 180 rdev->audio_status.status_bits = 0;
193 rdev->audio_category_code = 0; 181 rdev->audio_status.category_code = 0;
194
195 setup_timer(
196 &rdev->audio_timer,
197 r600_audio_update_hdmi,
198 (unsigned long)rdev);
199 182
200 return 0; 183 return 0;
201} 184}
202 185
203/* 186/*
204 * enable the polling timer, to check for status changes
205 */
206void r600_audio_enable_polling(struct drm_encoder *encoder)
207{
208 struct drm_device *dev = encoder->dev;
209 struct radeon_device *rdev = dev->dev_private;
210 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
211
212 DRM_DEBUG("r600_audio_enable_polling: %d\n",
213 radeon_encoder->audio_polling_active);
214 if (radeon_encoder->audio_polling_active)
215 return;
216
217 radeon_encoder->audio_polling_active = 1;
218 if (rdev->audio_enabled)
219 mod_timer(&rdev->audio_timer, jiffies + 1);
220}
221
222/*
223 * disable the polling timer, so we get no more status updates
224 */
225void r600_audio_disable_polling(struct drm_encoder *encoder)
226{
227 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
228 DRM_DEBUG("r600_audio_disable_polling: %d\n",
229 radeon_encoder->audio_polling_active);
230 radeon_encoder->audio_polling_active = 0;
231}
232
233/*
234 * atach the audio codec to the clock source of the encoder 187 * atach the audio codec to the clock source of the encoder
235 */ 188 */
236void r600_audio_set_clock(struct drm_encoder *encoder, int clock) 189void r600_audio_set_clock(struct drm_encoder *encoder, int clock)
@@ -297,7 +250,5 @@ void r600_audio_fini(struct radeon_device *rdev)
297 if (!rdev->audio_enabled) 250 if (!rdev->audio_enabled)
298 return; 251 return;
299 252
300 del_timer(&rdev->audio_timer);
301
302 r600_audio_engine_enable(rdev, false); 253 r600_audio_engine_enable(rdev, false);
303} 254}